【问题标题】:Decrypting CommonCrypto encrypted Base 64 encoded string in Java (AES/CBC/PKCS7Padding)在 Java (AES/CBC/PKCS7Padding) 中解密 CommonCrypto 加密的 Base 64 编码字符串
【发布时间】:2018-07-04 23:34:54
【问题描述】:

我正在尝试使用标准Cipher API 使用 Java 中的已知密钥解密 String

加密的String 来自Web Service,使用标准CommonCrypto 库,其中responds 和一些statistics 定期作为加密字符串。

规格为AES/CBC/PKCS7PaddingKeySize = 32 BytesBlockSize = 16 Bytes,以及Encoding UTF-8 (raw)Base64。我打算编写一个 Java 客户端,它可以请求这些 statisticsdecrypt 并存储它们以供以后分析。

问题 1. 如果密钥很短,CommonCrypto 会自动用额外的字符填充密钥吗?例如小于16 Bytes or 32 Bytes

问题2.我应该采取什么编码措施来确保两端相同的encryption/decryption

示例字符串和键

String message = "mQp9sp8ri1E0V1Xfso1d5g==Mrf3wtaqUjASlZmUO+BI8MrWsrZSC0MxxMocswfYnqSn/VKB9luv6E8887eCxpLNNAOMB0YXv6OS7rFDFdlvC53pCHo3cVZiLJFqgWN/eNiC9p4RMxyFCcOzWrwKzT5P8sy55DwE25DNJkvMthSaxK5zcP1OdLgBiZFOSxYRsX4rBk7VP7p5xr2uTGjRL+jmGgB9u3TmeCNCr8NxGLNt6g==";
String userKey = "123456789";

private static String decrypt (String message, String userKey) throws UnsupportedEncodingException,
            NoSuchPaddingException,
            NoSuchAlgorithmException,
            InvalidKeyException,
            ShortBufferException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, NoSuchProviderException {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        if (message.length() >= 48) {

        ivFromEncryptedString = message.substring(0, Math.min(message.length(), 24));
        messageFromEncryptedString = message.substring(24, message.length());

        System.out.println(ivFromEncryptedString);
        System.out.println(messageFromEncryptedString);

        byte[] data = decodeBase64(messageFromEncryptedString);
        byte[] ivData = decodeBase64(ivFromEncryptedString);

        paddedKey = padShortKeys(userKey);

        byte[] keyBytes = paddedKey.getBytes(CHARSET);

        MessageDigest sha = MessageDigest.getInstance("SHA-256"); //key
        keyBytes = sha.digest(keyBytes);

        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivData);
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);

            byte [] encrypted = new byte[cipher.getOutputSize(data.length)];
            int ctLength = cipher.update(data, 0, data.length, encrypted, 0);
            ctLength += cipher.doFinal(encrypted, ctLength);
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            return encrypted;
        }
    }
    return null;
    }
private static String encodeBase64(byte [] in){
    return Base64.getEncoder().encodeToString(in);
}

private static byte[] decodeBase64(String str) throws UnsupportedEncodingException {
    return DatatypeConverter.parseBase64Binary(str);
}

此外,在当前代码状态下,我得到的是占位符字符,而不是所需的结果。

在此先感谢各位。 :)

【问题讨论】:

  • 您将消息拆分为 IV 和加密数据。对于 IV,您采用 Base 64 编码字符串的 24 个字符,即 18 个原始字节。你的 IV 真的是 18 字节长吗?
  • 1.为什么要在密钥传递到 MD5 时填充密钥,这没有任何意义。 2. MD5 产生一个 16 字节的输出,而您使用 AES 和 32 字节的密钥,这同样没有意义。 3. MD5不是安全密钥派生函数,PBKDF2是安全的。
  • @Codo 这 24 个字符是 Base64 编码并解码为 16 字节,最后两个字符“==”是 Base64 填充。见Base64 Output Padding
  • 除了 zaph 所说的一切之外,您还错误地使用了 Cipher.update()Cipher.doFinal()。请仔细重新阅读这些方法的Javadocs。我怀疑你想要的只是一个电话doFinal(),即。 byte [] out = cipher.doFinal(data).
  • @Codo IV 应该是 16 字节。

标签: java encryption aes commoncrypto cbc-mode


【解决方案1】:

CommonCrypto 不清楚,您使用的是哪个实现? Apple、Apache、Java Class Cipher 或其他,请提供指向它的链接。

  1. 永远不要假设加密会填充密钥或 IV,它们应该始终以准确的长度提供,这种填充没有标准。如果他们需要填充(他们不应该)自己做。

  2. 如果需要将加密数据表示为字符串,通常会使用 Base64 编码。

正如 James 所说,对于一次性加密,只需使用 doFinal(ByteBuffer input, ByteBuffer output) 即可 在单部分操作中加密或解密数据。

注意:9 位密钥只有大约 33 位的安全性,这还不够。简单地使用散列函数不足以从密码中导出加密密钥,应使用PBKDF2Argon2

【讨论】:

  • 苹果,先生。加密的字符串来自 Apple 设备,前面的 IV 是16 BytesKeyChar 1 填充在那里。这是一种标准加密,但有一种方法公开,它说 padKeys 并且填充限制是一个幻数25。这就是让我质疑是否通过CommonCrypto 自动填充键的原因。因为密钥长度是kCCKeySizeAES256所以25 Bytes必须转换成32 Bytes
  • 谢谢先生。衷心感谢您在这方面的宝贵时间。
  • 更新:在测试 Apple Common Crypto 时,用空值填充短键。
猜你喜欢
  • 1970-01-01
  • 2016-08-21
  • 2018-10-08
  • 2019-04-07
  • 2015-05-27
  • 2011-12-22
  • 2020-08-24
  • 2021-06-24
  • 2014-01-13
相关资源
最近更新 更多