简体   繁体   English

使用C / C ++与Java进行DES加密

[英]DES encrypt in C/C++ vs Java

Just wondering why same plain text encrypted in Java and C doesn't generate same cipher text. 只是想知道为什么用Java和C加密的相同纯文本不能生成相同的密文。 For DES algo I noticed 对于DES算法,我注意到了

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

C cipher text len = 24 Java generates cipher text len = 8 C密文len = 24 Java生成密文len = 8

For 256Bit AES I noticed similar difference 对于256位AES,我注意到了类似的区别
C cipher text len = 32 Java generates cipher text len = 16 C密文len = 32 Java生成密文len = 16

here is my "C" code 这是我的“ 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;
}

Here is the "Java" code 这是“ 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;
    }

I have list of entries encrypted using C , I want to decrypt those entries in Java. 我有使用C加密的条目列表,我想用Java解密这些条目。

UPDATED 更新
following update helped to get same length , both in 'C' and 'JAVA' 后续更新有助于获得相同的长度,在“ C”和“ JAVA”中

EVP_EncryptUpdate(&ctx, out, &outlen1, in, strlen(text)); EVP_EncryptUpdate(&ctx,out,&outlen1,in,strlen(text));复制代码

No Just wondering why ciphertext returned by "C" and "JAVA" are different for same text and key, I'm expecting them tobe same 不只是想知道为什么“ C”和“ JAVA”返回的密文对于相同的文本和密钥是不同的,我希望它们是相同的

The reason the C code outputs 32 bytes of ciphertext is because you are padding your input string with zeros before passing it to the encryption function. C代码输出32字节密文的原因是因为在将输入字符串传递给加密功能之前,您将其填充为零。

In this line: 在这一行:

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

the function has no idea that you padded your data with zeros. 该函数不知道您用零填充数据。 Since sizeof(in) is 16, it takes 16 as the length of your plaintext. 由于sizeof(in)为16,因此它的明文长度为16。 And with PKCS5 padding (and AES), 16 bytes will pad to 32 bytes. 而使用PKCS5填充(和AES),则16个字节将填充为32个字节。

In your Java code you didn't manually pad your input, you just passed it straight to the encryption function. 在您的Java代码中,您无需手动填充输入,而是直接将其传递给加密函数。 So the encryption function sees your plaintext size as 4 bytes, which pads to 16 with PKCS5 padding. 因此,加密功能将您的纯文本大小视为4字节,使用PKCS5填充将其填充为16。

So your solution is simple: don't manually pad your input in the C code. 因此,您的解决方案很简单:不要手动将输入内容填充到C代码中。 Just pass the plaintext directly to EVP_EncryptUpdate . 只需将纯文本直接传递给EVP_EncryptUpdate It's already designed to handle unpadded plaintext. 它已经被设计来处理未填充的纯文本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM