У меня есть блок шифрованного текста, который был создан с помощью JCE algorithim "PBEWithSHA256And256BitAES-CBC-BC". Поставщиком является BouncyCastle. Что я хотел бы сделать это, дешифруют этот шифрованный текст с помощью легкого веса BouncyCastle API. Я не хочу использовать JCE, потому что это требует установки Неограниченных Файлов политики Юрисдикции Силы.
Документация, кажется, редко встречается когда дело доходит до использования до н.э с PBE и AES.
Вот то, что я имею до сих пор. Код дешифрования работает без мусора возвратов, но исключения.
Код шифрования,
String password = "qwerty";
String plainText = "hello world";
byte[] salt = generateSalt();
byte[] cipherText = encrypt(plainText, password.toCharArray(), salt);
private static byte[] generateSalt() throws NoSuchAlgorithmException {
byte salt[] = new byte[8];
SecureRandom saltGen = SecureRandom.getInstance("SHA1PRNG");
saltGen.nextBytes(salt);
return salt;
}
private static byte[] encrypt(String plainText, char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
Security.addProvider(new BouncyCastleProvider());
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 20);
PBEKeySpec pbeKeySpec = new PBEKeySpec(password);
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
Cipher encryptionCipher = Cipher.getInstance("PBEWithSHA256And256BitAES-CBC-BC");
encryptionCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
return encryptionCipher.doFinal(plainText.getBytes());
}
Код дешифрования,
byte[] decryptedText = decrypt(cipherText, password.getBytes(), salt);
private static byte[] decrypt(byte[] cipherText, byte[] password, byte[] salt) throws DataLengthException, IllegalStateException, InvalidCipherTextException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
BlockCipher engine = new AESEngine();
CBCBlockCipher cipher = new CBCBlockCipher(engine);
PKCS5S1ParametersGenerator keyGenerator = new PKCS5S1ParametersGenerator(new SHA256Digest());
keyGenerator.init(password, salt, 20);
CipherParameters keyParams = keyGenerator.generateDerivedParameters(256);
cipher.init(false, keyParams);
byte[] decryptedBytes = new byte[cipherText.length];
int numBytesCopied = cipher.processBlock(cipherText, 0, decryptedBytes, 0);
return decryptedBytes;
}
Я пробовал это, и мне показалось, что это сработало. Заимствовано в значительной степени из класса BC org.bouncycastle.jce.provider.test.PBETest
private byte[] decryptWithLWCrypto(byte[] cipher, String password, byte[] salt, final int iterationCount)
throws Exception
{
PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(new SHA256Digest());
char[] passwordChars = password.toCharArray();
final byte[] pkcs12PasswordBytes = PBEParametersGenerator
.PKCS12PasswordToBytes(passwordChars);
pGen.init(pkcs12PasswordBytes, salt, iterationCount);
CBCBlockCipher aesCBC = new CBCBlockCipher(new AESEngine());
ParametersWithIV aesCBCParams = (ParametersWithIV) pGen.generateDerivedParameters(256, 128);
aesCBC.init(false, aesCBCParams);
PaddedBufferedBlockCipher aesCipher = new PaddedBufferedBlockCipher(aesCBC,
new PKCS7Padding());
byte[] plainTemp = new byte[aesCipher.getOutputSize(cipher.length)];
int offset = aesCipher.processBytes(cipher, 0, cipher.length, plainTemp, 0);
int last = aesCipher.doFinal(plainTemp, offset);
final byte[] plain = new byte[offset + last];
System.arraycopy(plainTemp, 0, plain, 0, plain.length);
return plain;
}
Это не тривиально - генерировать ключ точно так же, как аналоги JCE. Я только что бегло просмотрел ваш код. Нашел по крайней мере одно несоответствие. JCE использует генератор PKCS12, а вы используете PKCS5S1.
Я не удивлюсь, если есть и другие различия. Вам нужно сравнить ваш код с исходниками BC.
Было несколько проблем с вашим методом дешифрования:
private static byte[] decrypt(final byte[] bytes, final char[] password, final byte[] salt) throws DataLengthException, IllegalStateException, InvalidCipherTextException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
final PBEParametersGenerator keyGenerator = new PKCS12ParametersGenerator(new SHA256Digest());
keyGenerator.init(PKCS12ParametersGenerator.PKCS12PasswordToBytes(password), salt, 20);
final CipherParameters keyParams = keyGenerator.generateDerivedParameters(256, 128);
final BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()), new PKCS7Padding());
cipher.init(false, keyParams);
final byte[] processed = new byte[cipher.getOutputSize(bytes.length)];
int outputLength = cipher.processBytes(bytes, 0, bytes.length, processed, 0);
outputLength += cipher.doFinal(processed, outputLength);
final byte[] results = new byte[outputLength];
System.arraycopy(processed, 0, results, 0, outputLength);
return results;
}
Основные проблемы заключались в том, как вы выполняли дешифрование без использования блочного шифра, и в отсутствии размера IV для generateDerivedParameters
метод. Первую проблему я увидел довольно быстро, вторая была гораздо менее очевидной. Я обнаружил это только при просмотре теста Bouncy Castle под названием PBETest .