J'ai le programme suivant pour le cryptage des données.
import Java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.Apache.commons.codec.binary.Base64;
public class Test {
private static final String ALGORITHM = "AES";
private static final byte[] keyValue = "ADBSJHJS12547896".getBytes();
public static void main(String args[]) throws Exception {
String encriptValue = encrypt("dude5");
decrypt(encriptValue);
}
/**
* @param args
* @throws Exception
*/
public static String encrypt(String valueToEnc) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);
System.out.println("valueToEnc.getBytes().length "+valueToEnc.getBytes().length);
byte[] encValue = c.doFinal(valueToEnc.getBytes());
System.out.println("encValue length" + encValue.length);
byte[] encryptedByteValue = new Base64().encode(encValue);
String encryptedValue = encryptedByteValue.toString();
System.out.println("encryptedValue " + encryptedValue);
return encryptedValue;
}
public static String decrypt(String encryptedValue) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
byte[] enctVal = c.doFinal(encryptedValue.getBytes());
System.out.println("enctVal length " + enctVal.length);
byte[] decordedValue = new Base64().decode(enctVal);
return decordedValue.toString();
}
private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
return key;
}
}
Ici, je reçois ce qui suit avec une exception?
valueToEnc.getBytes().length 5
encValue length16
encryptedValue [B@aa9835
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.Sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.Sun.crypto.provider.SunJCE_f.b(DashoA13*..)
Quelqu'un peut-il m'expliquer la cause? Pourquoi son seul mot lors du déchiffrement de cette longueur devrait être 16. Ne convertit-il pas en 16 comme un chiffrement avec la méthode doFinal.
Et comme le dit l’exception " comment décrypter sans chiffrement renforcé?"
Votre commande pour chiffrer: getBytes, chiffrer, coder, toString
Votre commande de déchiffrement (Wrong *): getBytes, déchiffrer, décoder, toString
Deux problèmes:
Remarque: De plus, vous n'avez pas besoin d'appeler generateKey()
deux fois.
Résoudre le problème n ° 1 en utilisant l'ordre inverse du déchiffrement.
Ordre correct pour déchiffrer: getBytes, décoder, déchiffrer, toString
Résoudre le problème n ° 2 en remplaçant xxx.toString()
par new String(xxx)
. Faites cela dans les fonctions de chiffrement et de déchiffrement.
Votre déchiffrement devrait ressembler à ceci:
c.init(Cipher.DECRYPT_MODE, key)
val decodedValue = new Base64().decode(encryptedValue.getBytes())
val decryptedVal = c.doFinal(decodedValue)
return new String(decryptedVal)
Cela devrait vous rendre "mec5"
La ligne
String encryptedValue = encryptedByteValue.toString();
c'est le problème. Le type de encryptedByteValue est byte [] et appeler toString sur ce n'est pas ce que vous voulez faire ici. Au lieu d'essayer
String encryptedValue = Base64.getEncoder().encodeToString(encValue);
Ensuite, utilisez Base64.decodeBase64(encryptedValue)
dans déchiffrer. Vous devez cependant le faire avant de tenter de décrypter. Vous devez annuler les opérations dans l'ordre inverse de la méthode de chiffrement.
Où trouvez-vous une version du codec Apache contenant encodeToString ou encodeBase64String?
J'ai téléchargé la version 1.5 à partir du site Apache et bien que la documentation indique que ces méthodes existent, elles ne s'affichent pas lorsque vous complétez du code et créent une méthode inconnue lorsque vous les fournissez.
J'ai pu faire:
byte raw[] = md.digest(); //step 4
byte hashBytes[] = Base64.encodeBase64(raw); //step 5
StringBuffer buffer = new StringBuffer();
for( int i=0; i<hashBytes.length; i++ )
buffer.append(hashBytes[i]);
return buffer.toString(); //step 6
Et puis la chaîne que j'ai obtenue était très longue, MAIS elle a été décryptée correctement.
Je ne pense pas que ce soit la "bonne" façon de faire les choses, mais je ne trouve pas les méthodes décrites dans la documentation.
J'ai remplace la ligne dans l'exemple:
String encryptedValue = encryptedByteValue.toString();
avec le prochain:
String encryptedValue = new String(encryptedByteValue);
Tout fonctionne bien!
C'était bien, il fallait juste
1) Utilisez new String au lieu de toString () car toString () ne renvoie pas ce dont vous avez besoin ici (dans les deux cas, chiffrement et déchiffrement).
2) vous devez d'abord décoder car la valeur est encodée en base64.
Je suis tombé sur ce fil de discussion, mais il m'a fallu un certain temps pour trouver le point réel. Je publie mon code pour le reste des personnes qui rencontrent ce problème.
public abstract class EncryptionDecryption {
static byte[] key = "!@#$!@#$%^&**&^%".getBytes();
final static String algorithm="AES";
public static String encrypt(String data){
byte[] dataToSend = data.getBytes();
Cipher c = null;
try {
c = Cipher.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SecretKeySpec k = new SecretKeySpec(key, algorithm);
try {
c.init(Cipher.ENCRYPT_MODE, k);
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] encryptedData = "".getBytes();
try {
encryptedData = c.doFinal(dataToSend);
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] encryptedByteValue = new Base64().encode(encryptedData);
return new String(encryptedByteValue);//.toString();
}
public static String decrypt(String data){
byte[] encryptedData = new Base64().decode(data);
Cipher c = null;
try {
c = Cipher.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SecretKeySpec k =
new SecretKeySpec(key, algorithm);
try {
c.init(Cipher.DECRYPT_MODE, k);
} catch (InvalidKeyException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
byte[] decrypted = null;
try {
decrypted = c.doFinal(encryptedData);
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new String(decrypted);
}
public static void main(String[] args){
String password=EncryptionDecryption.encrypt("password123");
System.out.println(password);
System.out.println(EncryptionDecryption.decrypt(password));
}
}
Fondamentalement, il existe une asymétrie entre votre fonction de chiffrement et votre fonction de déchiffrement. Lorsque vous chiffrez, vous effectuez un chiffrement AES, puis un codage base64. Lorsque vous décryptez, vous n'annulez pas au préalable l'étape de codage base64.
Je pense qu'il y a quelque chose qui ne va pas avec votre encodage en base64, et [
ne devrait pas apparaître dans une chaîne encodée en base64.
En regardant la documentation pour org.Apache.commons.codec.binary.Base64
, vous devriez pouvoir le faire sur encoder:
String encryptedValue = Base64.encodeBase64String(encValue);
et ceci sur décoder:
byte[] encValue = Base64.decodeBase64(encryptedValue);