2

只是想知道为什么用 Java 和 C 加密的相同纯文本不会生成相同的密文。对于 DES 算法,我注意到

输入text = "text", key = "test"

C 密文len = 24 Java 生成密文len = 8

对于 256Bit AES,我注意到类似的差异
C 密文len = 32 Java 生成密文len = 16

这是我的“C”代码

char* enc(const char* text, const char* keyStr)
{
    EVP_CIPHER_CTX ctx;
    unsigned char key[32] = {0};
    unsigned char iv[16] = {0};
    unsigned char in[16] = {0};
    unsigned char out[32]; /* at least one block longer than in[] */
    memset(out, 0, 32);
    int outlen1, outlen2;

    memcpy(in, text, strlen(text));
    memcpy(key, keyStr, strlen(keyStr));

    EVP_EncryptInit(&ctx, EVP_aes_256_cbc(), key, iv);    
    EVP_EncryptUpdate(&ctx, out, &outlen1, in, sizeof(in));
    EVP_EncryptFinal(&ctx, out + outlen1, &outlen2);

    char* ret  = (char*)malloc(outlen1 + outlen2+1);
    memset(ret, 0, outlen1 + outlen2+1);
    memcpy(ret, out, outlen1 + outlen2);

    EVP_CIPHER_CTX_cleanup(&ctx);

    return ret;
}

这是“Java”代码

public static byte[] enc(byte[] input, byte[] keyStr){
        byte[] output = null;

        try {           
            byte[] newKey = getByteArrays(keyStr, 0, 32);
            SecretKey secretKey = new SecretKeySpec(newKey, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");  
            //Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            String ivStr = "";
            byte[] ivKey = getByteArrays(ivStr.getBytes("UTF-8"), 0, 16);
            IvParameterSpec ips = new IvParameterSpec(ivKey);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ips, null);         
            output = cipher.doFinal(input);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
        return output;
    }

我有使用 C 加密的条目列表,我想用 Java 解密这些条目。

更新
后的更新有助于在“C”和“JAVA”中获得相同的长度

EVP_EncryptUpdate(&ctx, out, &outlen1, in, strlen(text));

不只是想知道为什么“C”和“JAVA”返回的密文对于相同的文本和密钥是不同的,我希望它们是相同的

4

1 回答 1

1

C 代码输出 32 字节密文的原因是因为您在将输入字符串传递给加密函数之前用零填充了它。

在这一行:

EVP_EncryptUpdate(&ctx, out, &outlen1, in, sizeof(in));

该函数不知道您用零填充数据。因为sizeof(in)是 16,所以它需要 16 作为明文的长度。使用 PKCS5 填充(和 AES),16 个字节将填充到 32 个字节。

在您的 Java 代码中,您没有手动填充输入,而是直接将其传递给加密函数。因此,加密函数将您的明文大小视为 4 个字节,使用 PKCS5 填充填充为 16。

所以您的解决方案很简单:不要在 C 代码中手动填充您的输入。只需将明文直接传递给EVP_EncryptUpdate. 它已经设计用于处理未填充的纯文本。

于 2013-09-17T16:32:49.890 回答