AES_encrypt/AES_decrypt 仅 returns 部分消息
AES_encrypt/AES_decrypt only returns part of a message
我不知道为什么下面的代码会return"Hello native! Th"而不是"Hello native! This is from jni load!\n",有人可以提示吗?
#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, '[=12=]', sizeof(out));
memset(outout, '[=12=]', 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" */
}
每次调用 AES_encrypt 都会加密一个 AES 块...16 字节。这就是为什么通过一次调用,您最终会在加密缓冲区中得到恰好 16 个字符。
AES_encrypt((const unsigned char *)origin, (unsigned char *)out, &aesKey);
AES_encrypt
对 16 字节块进行操作。 16是AES的块大小。
实际上,您截断了消息。
AES_decrypt(pout, outout, &aesKey);
在这里,你只解密了16个bye。缓冲区的其余部分用 0 回填。0 作为 ASCII-Z 终止符。
您正在 ECB 模式下有效地操作密码。 ECB 模式可能不是您需要的模式。 ECB 模式只有在使用一个密钥加密一条消息时才是安全的。否则,攻击者会了解到同一条消息被加密了两次。
此外,它唯一安全的是 如果 消息小于块大小。如果消息大于块大小,则 ECB 模式可以泄漏信息。
您或许应该使用 CBC 模式。您还应该使用 EVP_*
函数而不是 AES_encrypt
和 AES_decrypt
。请参阅 OpenSSL wiki 上的 EVP Symmetric Encryption and Decryption。
如果您只是对数据进行加密,那么您就缺乏完整性和真实性保证。所以密文是可塑的,这通常是一件坏事。在这种情况下,最好使用 EAX、CCM 或 GCM 等模式。为此,请参阅 EVP Authenticated Encryption and Decryption。
我不知道为什么下面的代码会return"Hello native! Th"而不是"Hello native! This is from jni load!\n",有人可以提示吗?
#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, '[=12=]', sizeof(out));
memset(outout, '[=12=]', 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" */
}
每次调用 AES_encrypt 都会加密一个 AES 块...16 字节。这就是为什么通过一次调用,您最终会在加密缓冲区中得到恰好 16 个字符。
AES_encrypt((const unsigned char *)origin, (unsigned char *)out, &aesKey);
AES_encrypt
对 16 字节块进行操作。 16是AES的块大小。
实际上,您截断了消息。
AES_decrypt(pout, outout, &aesKey);
在这里,你只解密了16个bye。缓冲区的其余部分用 0 回填。0 作为 ASCII-Z 终止符。
您正在 ECB 模式下有效地操作密码。 ECB 模式可能不是您需要的模式。 ECB 模式只有在使用一个密钥加密一条消息时才是安全的。否则,攻击者会了解到同一条消息被加密了两次。
此外,它唯一安全的是 如果 消息小于块大小。如果消息大于块大小,则 ECB 模式可以泄漏信息。
您或许应该使用 CBC 模式。您还应该使用 EVP_*
函数而不是 AES_encrypt
和 AES_decrypt
。请参阅 OpenSSL wiki 上的 EVP Symmetric Encryption and Decryption。
如果您只是对数据进行加密,那么您就缺乏完整性和真实性保证。所以密文是可塑的,这通常是一件坏事。在这种情况下,最好使用 EAX、CCM 或 GCM 等模式。为此,请参阅 EVP Authenticated Encryption and Decryption。