【发布时间】:2014-09-27 10:55:16
【问题描述】:
我有一个由 SJCL 服务器端加密的字符串,需要在 Android 中使用任何可用的库进行解密。我尝试了 BouncyCastle,直到遇到无法从 PBKDF2 生成密钥的问题。现在我正在使用 SpongyCastle,但我仍然遇到问题。到目前为止,这是我生成密钥和解密字符串的代码:
private static byte[] decrypt(SecretKey key, byte[] encrypted, byte[] iv) throws Exception {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static SecretKey generateKey(char[] passphraseOrPin, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
// Number of PBKDF2 hardening rounds to use. Larger values increase
// computation time. You should select a value that causes computation
// to take >100ms.
final int iterations = 1000;
// Generate a 128-bit key
final int outputKeyLength = 128;
/*SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);*/
PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator(new SHA256Digest());
generator.init(PBEParametersGenerator.PKCS5PasswordToBytes(passphraseOrPin), salt, iterations);
KeyParameter key = (KeyParameter) generator.generateDerivedMacParameters(outputKeyLength);
SecretKey secretKey = new SecretKeySpec(key.getKey(), "AES");
return secretKey;
}
这是我在函数中的调用方式:
char[] key = * put PBKDF2 password here *;
// Generate key from password
SecretKey decryptionKey = null;
try {
decryptionKey = generateKey(key, decodedObject.get("salt").getAsString().getBytes());
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
byte[] decryptedTicketBytes = null;
// Decrypt the ticket
try {
decryptedTicketBytes = decrypt(decryptionKey, decodedObject.get("ct").getAsString().getBytes(), decodedObject.get("iv").getAsString().getBytes());
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
decodedObject 是来自 SJCL 的字符串,它在通过带有 UTF-8 的 JsonParser 并被 Base64 解码后运行。我拿了它并用密码通过SJCL Demo 运行它并解密字符串没问题。我一定在这里遗漏了一些简单的东西。
我在 cipher.doFinal 步骤中遇到错误,如下所示:
java.security.InvalidKeyException: nonce must have length from 7 to 13 octets
我认为 SJCL 没有在他们的密码上使用任何填充,因此我尝试在 getInstance 上使用“AES/CCM/PKCS5Padding”,但随后出现此错误:
javax.crypto.NoSuchPaddingException: Only NoPadding can be used with AEAD modes.
TLDR:我正在寻找在 Android 中解密 SJCL 字符串的最简单方法。建议将不胜感激。
谢谢!
【问题讨论】:
-
您正在加密客户端和服务器之间的通信?这正是TLS 的设计目的。请注意,您的方案不保护任何东西。任何人都可以对客户端应用程序进行逆向工程以获取密码并继续解密其他客户端的通信。
-
@ntoskrnl,我没有加密通信,只是解密从 Web 服务调用返回的字符串。密码也不会在最终实现中那样存储,这只是在我可以让它工作之前。
-
我在 Java 中创建了一个 SJCL 库,只是为了放弃它。他们很快在他们的便利代码中发现了一个可怕的错误——在我无法验证(没有验证 AAD)之后,我实际上不希望 SJCL 成功;维护不善,这种东西不应该用JS。
-
@owlstead 你的 SJCL 库还能用吗?我很想继续检查一下,看看我是否无法从中得到一些工作。
-
呃,不知道 :) 我会试试看能不能找到/更新任何东西。
标签: android cryptography bouncycastle spongycastle sjcl