java - jni-wrapper-to-openssl-AES_encrypt-不工作

标签 java android c openssl java-native-interface

我正在尝试使用 android open ssl 加密和解密文件。 下面分享相同的 JNI 包装器。

JNIEXPORT jbyteArray JNICALL
Java_com_example_MainActivity_AESencrypt( JNIEnv* env, jobject thiz, jint 
length, jbyteArray jarrByte)
{
unsigned char plaintext[AES_BLOCK_SIZE * 4];
unsigned char ciphertext[AES_BLOCK_SIZE * 4];
unsigned char checktext[AES_BLOCK_SIZE * 4];
const unsigned char userKey[AES_BLOCK_SIZE * 4] = "123456";
const int bits = 128;
AES_KEY keyin = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
                    0,
                    0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, }, 12 };
AES_KEY *key = &keyin;
jbyte* pJbyte = env->GetByteArrayElements(jarrByte, NULL);
if(pJbyte!=NULL){
   memcpy(plaintext, pJbyte, length);
   env->ReleaseByteArrayElements(jarrByte, pJbyte, JNI_ABORT);
}
unsigned char* beforeEncrypt = &plaintext[0];
unsigned char* afterEncrypt = &ciphertext[0];
AES_set_encrypt_key(userKey, bits, key);
AES_encrypt(beforeEncrypt, afterEncrypt, key);
jbyteArray jarrRet = env->NewByteArray(strlen((char*) ciphertext));
env->SetByteArrayRegion(jarrRet, 0, strlen((char*) ciphertext), (jbyte *) ciphertext);
return jarrRet;
}

JNIEXPORT jbyteArray JNICALL
Java_com_example_MainActivity_AESdecrypt( JNIEnv* env, jobject thiz, jint 
length, jbyteArray jarrByte)
{
 unsigned char encryptText[AES_BLOCK_SIZE * 4];
 unsigned char ciphertext[AES_BLOCK_SIZE * 4];
 unsigned char checktext[AES_BLOCK_SIZE * 4];
 const unsigned char userKey[AES_BLOCK_SIZE * 4] = "123456";
 const int bits = 128;
AES_KEY keyin = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
                    0,
                    0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, }, 12 };
AES_KEY *key = &keyin;
jbyte* pJbyte = env->GetByteArrayElements(jarrByte, NULL);
if(pJbyte!=NULL){
    memcpy(encryptText, pJbyte, length);
    env->ReleaseByteArrayElements(jarrByte, pJbyte, JNI_ABORT);
}

unsigned char* beforeDecrypt = &encryptText[0];
unsigned char* afterDecrypt = &ciphertext[0];
AES_set_decrypt_key(userKey, bits, key);
AES_decrypt(beforeDecrypt, afterDecrypt, key);

jbyteArray jarrRet = env->NewByteArray(strlen((char*) ciphertext));
env->SetByteArrayRegion(jarrRet, 0, strlen((char*) ciphertext), (jbyte *) ciphertext);
return jarrRet;
}

我正在调用 JNI 方法,如下所示。

Mainactivity.java :
   public void jni_encryption_and_decryption {

                    // reads the file and converts into bytes 
                    plainTextBytes = getBytesFromInputFile(); 
                    len = plainTextBytes.length;

                    // encrypts the plain text and returns the encrypted bytes
                    byte[] encryptedByte = AESencrypt(len, plainTextBytes);
                    String encryptString = new String(encryptedByte);
                    encrypt.setText(encryptString);

                    len = encryptedByte.length;
                    // decrypts encrypted bytes and returns the decrypted bytes
                    decryptedByte = AESdecrypt(len, encryptedByte);
                    String decryptString = new String(decryptedByte);
                    decrypt.setText(decryptString);
      }

加密工作正常,但在解密时,垃圾来了,而且如果文件包含更多纯文本,则它不会解密完整的纯文本。

Input from File:这是一个android openssl加解密demo

解密文本:这是一个andro�������0_��!

我还分享了加密前后的字节。直到第 15 个索引字节相同。之后发现字节不一样。

Jni Wrapper 有什么问题?我错过了什么吗?请帮忙。

enter image description here enter image description here

JNIEXPORT jbyteArray JNICALL 
Java_com_example_MainActivity_doEncryption(jbyteArray data_plaintext, int 
plaintext_len, jbyteArray data_key,
        jbyteArray data_iv, jbyteArray data_ciphertext)
{
unsigned char* key = (unsigned char*) data_key;
unsigned char* iv = (unsigned char*) data_iv;
unsigned char* plaintext =  (unsigned char*) data_plaintext;
unsigned char* ciphertext =  (unsigned char*) data_ciphertext;
EVP_CIPHER_CTX *ctx;

int len;

int ciphertext_len;

/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())){
    ERR_print_errors_fp(stderr);
    abort();
}


/* Initialise the encryption operation. IMPORTANT - ensure you use a key
 * and IV size appropriate for your cipher
 * In this example we are using 256 bit AES (i.e. a 256 bit key). The
 * IV size for *most* modes is the same as the block size. For AES this
 * is 128 bits */
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)){
    ERR_print_errors_fp(stderr);
    abort();
}

/* Provide the message to be encrypted, and obtain the encrypted output.
 * EVP_EncryptUpdate can be called multiple times if necessary
 */
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)){
    ERR_print_errors_fp(stderr);
    abort();
}
ciphertext_len = len;

/* Finalise the encryption. Further ciphertext bytes may be written at
 * this stage.
 */
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)){
    ERR_print_errors_fp(stderr);
    abort();
}
ciphertext_len += len;

/* Clean up */
EVP_CIPHER_CTX_free(ctx);
jbyteArray  ciphertext_copy = (jbyteArray ) ciphertext;

return ciphertext_copy;
} 

下面分享错误详情:

错误详情: * 什么地方出了错: 任务“:app:externalNativeBuildDebug”执行失败。

Build command failed. Error while executing process C:\android\sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {--build C:\Users\SampleJni\app.externalNativeBuild\cmake\debug\armeabi-v7a --target native-lib} [1/1] Linking CXX shared library ........\build\intermediates\cmake\debug\obj\armeabi-v7a\libnative-lib.so FAILED: cmd.exe /C "cd . && C:\android\sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=armv7-none-linux-androideabi --gcc-toolchain=C:/android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64 --sysroot=C:/android/sdk/ndk-bundle/sysroot -fPIC -isystem C:/android/sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=14 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fno-integrated-as -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a --sysroot C:/android/sdk/ndk-bundle/platforms/android-14/arch-arm -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libnative-lib.so -o ........\build\intermediates\cmake\debug\obj\armeabi-v7a\libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o ../../../../openssl-armeabi-v7a/lib/libcrypto.a ../../../../openssl-armeabi-v7a/lib/libssl.a -llog -lm "C:/android/sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/libgnustl_static.a" && cd ." ../../../../openssl-armeabi-v7a/lib/libcrypto.a(ui_openssl.o):ui_openssl.c:function read_string_inner: error: undefined reference to 'signal' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(ui_openssl.o):ui_openssl.c:function read_string_inner: error: undefined reference to 'tcsetattr' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(ui_openssl.o):ui_openssl.c:function read_string_inner: error: undefined reference to 'tcsetattr' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(ui_openssl.o):ui_openssl.c:function open_console: error: undefined reference to 'tcgetattr' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function zlib_stateful_expand_block: error: undefined reference to 'inflate' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function zlib_stateful_compress_block: error: undefined reference to 'deflate' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_free: error: undefined reference to 'inflateEnd' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_free: error: undefined reference to 'deflateEnd' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function zlib_stateful_finish: error: undefined reference to 'inflateEnd' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function zlib_stateful_finish: error: undefined reference to 'deflateEnd' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function zlib_stateful_init: error: undefined reference to 'inflateInit_' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function zlib_stateful_init: error: undefined reference to 'deflateInit_' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_ctrl: error: undefined reference to 'deflate' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_ctrl: error: undefined reference to 'zError' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_write: error: undefined reference to 'deflate' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_write: error: undefined reference to 'zError' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_write: error: undefined reference to 'deflateInit_' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_read: error: undefined reference to 'inflate' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_read: error: undefined reference to 'zError' ../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_read: error: undefined reference to 'inflateInit_' clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed.

最佳答案

AES是一种分组密码,分组长度为16字节。这里的问题是 aes_encrypt()aes_decrypt() 是低级函数,它们只在单个 block 上运行(不是吗?奇怪,为什么没有长度参数?)。所以,您只加密和解密了演示字符串的 16 个字节,解密缓冲区的其余部分保持未初始化状态!

因此,您应该迭代操作更多 block ,或者使用更高级别的接口(interface),如 EVP 函数系列。 OpenSSL Wiki 是一本很好的入门书

在这两种情况下,您还应该根据 PKCS#7 实现适当的填充。

关于java - jni-wrapper-to-openssl-AES_encrypt-不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47346440/

相关文章:

c - 创建一个通用 C 列表来包含指针

java - 如何使 Jtextpane 中的某些文本不可由用户编辑?

java - 如何在 Eclipse 本身中运行 Spring Boot Web 应用程序?

android - 如何在 android 中使用 glreadpixels ——通常会得到零

C编程分段故障链表程序

c - memcpy 性能与字节移位

java - 在屏幕上的任何地方触摸时隐藏和显示工具栏

java - Google DataStore 不存储子对象

android - APK 压缩级别,尺寸减小

android - android "app lock"应用程序如何工作?