У меня есть два метода Java: один для шифрования, другой для расшифровки. Я хотел бы зашифровать/расшифровать пароль с помощью мастер-пароля. Но когда я пытаюсь расшифровать зашифрованный пароль, я получаю сообщение. Причина: javax.crypto.IllegalBlockSizeException: длина ввода должна быть кратна 16 при расшифровке с помощью дополненного шифра. Я не могу понять, почему я это понимаю. Я мог бы предположить, что это как-то связано с преобразованием строки в байт, но я не уверен. Как это исправить?
Код:
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
public class AESEncryption implements EncryptionModuleInterface {
private static final int ITERATION_COUNT = 1000000;
private static final int KEY_LENGTH = 256;
private static final String PBKDF_ALGORITHM = "PBKDF2WithHmacSHA1";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
private static final String ALGORITHM = "AES";
@Override
public String encryptPassword(String password, String masterpassword) {
byte[] finalCiphertext;
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance(PBKDF_ALGORITHM);
byte[] key = factory.generateSecret(spec).getEncoded();
SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
byte[] ivBytes = new byte[16];
random.nextBytes(ivBytes);
IvParameterSpec iv = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
byte[] inputBytes = password.getBytes();
byte[] encValue = cipher.doFinal(inputBytes);
finalCiphertext = new byte[encValue.length+2*16];
System.arraycopy(ivBytes, 0, finalCiphertext, 0, 16);
System.arraycopy(salt, 0, finalCiphertext, 16, 16);
System.arraycopy(encValue, 0, finalCiphertext, 32, encValue.length);
} catch (NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException |
InvalidKeySpecException | NoSuchAlgorithmException | IllegalBlockSizeException | BadPaddingException e) {
throw new RuntimeException(e);
}
return new String(finalCiphertext, StandardCharsets.UTF_8);
}
@Override
public String decryptPassword(String password, String masterpassword) {
byte[] ivBytes = new byte[16];
byte[] salt = new byte[16];
byte[] encValue;
byte[] readEncryptedBytesWithIvAndSaltPrefix = password.getBytes();
byte[] inputBytes = new byte[readEncryptedBytesWithIvAndSaltPrefix.length - 32];
System.arraycopy(readEncryptedBytesWithIvAndSaltPrefix, 0, ivBytes, 0, 16);
System.arraycopy(readEncryptedBytesWithIvAndSaltPrefix, 16, salt, 0, 16);
System.arraycopy(readEncryptedBytesWithIvAndSaltPrefix, 32, inputBytes, 0, readEncryptedBytesWithIvAndSaltPrefix.length - 32);
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance(PBKDF_ALGORITHM);
byte[] key = factory.generateSecret(spec).getEncoded();
SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
IvParameterSpec iv = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
encValue = cipher.doFinal(inputBytes);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
BadPaddingException | InvalidKeySpecException | InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
}
return new String(encValue, StandardCharsets.UTF_8);
}
}
< /code>
Изменить:
Я могу преобразовать двоичный байтовый массив в шестнадцатеричную строку: < /p>
StringBuilder result = new StringBuilder();
for (byte b : finalCiphertext){
result.append(String.format("%02X", b));
}
return result.toString();
< /code>
Но у меня есть проблемы, чтобы преобразовать шестнадцатеричную строку обратно в двоичный байтовый массив. < /p>
StringBuilder stringBuilder = new StringBuilder();
HashMap hashMap = new HashMap();
hashMap.put('0', "0000");
hashMap.put('1', "0001");
hashMap.put('2', "0010");
hashMap.put('3', "0011");
hashMap.put('4', "0100");
hashMap.put('5', "0101");
hashMap.put('6', "0110");
hashMap.put('7', "0111");
hashMap.put('8', "1000");
hashMap.put('9', "1001");
hashMap.put('A', "1010");
hashMap.put('B', "1011");
hashMap.put('C', "1100");
hashMap.put('D', "1101");
hashMap.put('E', "1110");
hashMap.put('F', "1111");
for (int i = 0; i < password.length(); i++) {
stringBuilder.append(hashMap.get(password.charAt(i)));
}
String binaryString = stringBuilder.toString();
byte[] readEncryptedBytesWithIvAndSaltPrefix = binaryString.getBytes();
System.out.println(Arrays.toString(readEncryptedBytesWithIvAndSaltPrefix));
Последний оператор печати возвращает массив с числами 48 и 49.
С этими дополнениями я получаю «Вызвано: javax.crypto.BadPaddingException: Данный последний блок не дополнен должным образом. Такие проблемы могут возникнуть, если при расшифровке используется неверный ключ.
У меня есть два метода Java: один для шифрования, другой для расшифровки. Я хотел бы зашифровать/расшифровать пароль с помощью мастер-пароля. Но когда я пытаюсь расшифровать зашифрованный пароль, я получаю сообщение. Причина: javax.crypto.IllegalBlockSizeException: длина ввода должна быть кратна 16 при расшифровке с помощью дополненного шифра. Я не могу понять, почему я это понимаю. Я мог бы предположить, что это как-то связано с преобразованием строки в байт, но я не уверен. Как это исправить? Код: [code]import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec;
public class AESEncryption implements EncryptionModuleInterface { private static final int ITERATION_COUNT = 1000000; private static final int KEY_LENGTH = 256; private static final String PBKDF_ALGORITHM = "PBKDF2WithHmacSHA1"; private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding"; private static final String ALGORITHM = "AES";
@Override public String encryptPassword(String password, String masterpassword) { byte[] finalCiphertext;
SecureRandom random = new SecureRandom(); byte[] salt = new byte[16]; random.nextBytes(salt);
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);
return new String(finalCiphertext, StandardCharsets.UTF_8); }
@Override public String decryptPassword(String password, String masterpassword) { byte[] ivBytes = new byte[16]; byte[] salt = new byte[16]; byte[] encValue;
return new String(encValue, StandardCharsets.UTF_8); } } < /code> Изменить: Я могу преобразовать двоичный байтовый массив в шестнадцатеричную строку: < /p> StringBuilder result = new StringBuilder(); for (byte b : finalCiphertext){ result.append(String.format("%02X", b)); }
return result.toString(); < /code> Но у меня есть проблемы, чтобы преобразовать шестнадцатеричную строку обратно в двоичный байтовый массив. < /p> StringBuilder stringBuilder = new StringBuilder(); HashMap hashMap = new HashMap(); hashMap.put('0', "0000"); hashMap.put('1', "0001"); hashMap.put('2', "0010"); hashMap.put('3', "0011"); hashMap.put('4', "0100"); hashMap.put('5', "0101"); hashMap.put('6', "0110"); hashMap.put('7', "0111"); hashMap.put('8', "1000"); hashMap.put('9', "1001"); hashMap.put('A', "1010"); hashMap.put('B', "1011"); hashMap.put('C', "1100"); hashMap.put('D', "1101"); hashMap.put('E', "1110"); hashMap.put('F', "1111");
for (int i = 0; i < password.length(); i++) { stringBuilder.append(hashMap.get(password.charAt(i))); }
String binaryString = stringBuilder.toString(); byte[] readEncryptedBytesWithIvAndSaltPrefix = binaryString.getBytes(); System.out.println(Arrays.toString(readEncryptedBytesWithIvAndSaltPrefix)); [/code] Последний оператор печати возвращает массив с числами 48 и 49. С этими дополнениями я получаю «Вызвано: javax.crypto.BadPaddingException: Данный последний блок не дополнен должным образом. Такие проблемы могут возникнуть, если при расшифровке используется неверный ключ.