java - 在 Java 中解密 CommonCrypto 加密的 Base 64 编码字符串 (AES/CBC/PKCS7Padding)

标签 java encryption aes commoncrypto cbc-mode

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

加密的字符串来自使用标准CommonCrypto库的Web服务,该库响应一些统计信息 作为定期加密的字符串。

规范为 AES/CBC/PKCS7Padding,其中 KeySize = 32 BytesBlockSize = 16 Bytes,以及 Encoding UTF-8(原始) & Base64。我打算编写一个 Java 客户端,可以请求这些统计数据、解密它们并存储它们以供以后分析。

问题1. 如果 key 很短,CommonCrypto 是否会自动用额外的字符填充 key ?例如小于 16 字节或 32 字节

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

示例字符串和键

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);
}

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

提前感谢各位。 :)

最佳答案

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

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

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

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

注意:9 位 key 仅具有大约 33 位的安全性,这还不够。简单地使用哈希函数不足以从密码中导出加密 key ,而是 PBKDF2Argon2应该使用。

关于java - 在 Java 中解密 CommonCrypto 加密的 Base 64 编码字符串 (AES/CBC/PKCS7Padding),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51117998/

相关文章:

java - 使用 JAXB 注释,当每个列表元素的名称未知时,如何获取包装在元素中的列表的每个 XML 元素?

android - aes-256-cbc加密解密

objective-c - AES256EncryptWithKey 方法的 openssl 等效项

java - 为什么 Java 加密 AES 会填充我的 16 字节明文消息?

java - ScheduledExecuterService.scheduleAtFixedRate 创建多个线程池 - Android

java - 实例变量的构造函数/自引用

java - 使用 java 对象创建一个简单的数学游戏

iphone - 在 iOS 应用程序中使用 SSL 进行登录

sqlite - 如何覆盖 UIManagedDocument 中的 NSPersistentStoreCoordinator

ios - 在 iOS 上加密 SQLite 数据库文件