2015-04-24 58 views
4

我不知道为什么下面的代码会返回“Hello native!Th”而不是“Hello native!这是jni加载!\ n”,有人可能会提示它吗?AES_encrypt/AES_decrypt只返回部分消息

#include "helloJNI.h" 
#include "openssl/aes.h" 

#define LEN 1024 

jstring jni_text(JNIEnv *env, jclass clz) 
{ 
    AES_KEY aesKey; 
    int result; 
    const char origin[] = "Hello native! This is from jni load!\n"; 
    char out[LEN]; 
    char outout[LEN]; 
    memset(out, '\0', sizeof(out)); 
    memset(outout, '\0', sizeof(outout)); 
    result = AES_set_encrypt_key((const unsigned char *)"abc123", 256, &aesKey); 
    LOGE("encypt key result %d\n", result); /* is 0 */ 
    AES_encrypt((const unsigned char *)origin, (unsigned char *)out, &aesKey); 
    LOGE("after encrypt, chars is %s\n", out); 
    result = AES_set_decrypt_key((const unsigned char *)"abc123", 256, &aesKey); 
    LOGE("decrypt key result %d\n", result); /* is 0 */ 
    AES_decrypt(out, outout, &aesKey); 
    LOGE("after decrypt, chars is %s\n", outout); 
    return (*env)->NewStringUTF(env, outout); /* return "Hello native! Th" */ 
} 
+0

你为什么要为此编写JNI?它可以直接用Java完成。 – EJP

回答

4

AES_encrypt((const unsigned char *)origin, (unsigned char *)out, &aesKey);

AES_encrypt运行在16字节的块。 16是AES的块大小。

实际上,您截断了您的消息。

AES_decrypt(pout, outout, &aesKey);

在这里,你只解密16轮轮空。缓冲区的其余部分用0填充。0用作ASCII-Z终止符。


您正在ECB模式下有效地操作密码。 ECB模式可能是您需要的错误模式。如果一个消息在一个密钥下加密,则ECB模式仅是安全的。否则,攻击者就会知道相同的消息被加密了两次。

此外,它的唯一安全如果消息小于块大小。如果消息大于块大小,则ECB模式可能泄漏信息。


您应该使用CBC模式。您还应该使用EVP_*功能,而不是AES_encryptAES_decrypt。请参阅OpenSSL wiki上的EVP Symmetric Encryption and Decryption

如果您只是对数据进行加密,那么您缺少完整性和真实性保证。所以密文是可塑的,这通常是一件坏事。在这种情况下,最好使用EAX,CCM或GCM模式。为此,请参阅EVP Authenticated Encryption and Decryption

+0

谢谢,我更新,信息非常有帮助! – user3717061

2

每次调用AES_encrypt都会加密一个AES块... 16个字节。这就是为什么,只需一个电话,您的加密缓冲区中就会有16个字符。

+0

非常感谢! – user3717061