首页 文章

JNI的包装到的OpenSSL AES_ENCRYPT - 不工作

提问于
浏览
3

我正在尝试使用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加密和解密演示

Encryption Text: UZ L\n c a [ ܰ h 0_

Decryption Text: 这是一个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' .

构建命令失败 . 执行进程C:\ android \ sdk \ cmake \ 3.6.4111459 \ bin \ cmake.exe时出错{--build C:\ Users \ SampleJni \ app.externalNativeBuild \ cmake \ debug \ armeabi-v7a --target native -lib} [1/1]链接CXX共享库........ \ 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 / n dk-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'inmplate'../../../../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:错误:未定义引用'inflateEnd'../ . ./../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_free:错误:未定义引用'deflateEnd'../../../ . ./openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function zlib_stateful_finish:错误:未定义引用'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:错误:未定义引用'deflate'../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_ctrl:error:undefined reference 'zError'../../../../openssl-armeabi-v7a/lib/libcrypto.a(c_zlib.o):c_zlib.c:function bio_zlib_write:错误:未定义引用'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:未定义引用'inflateInit_'clang .exe:错误:链接器命令失败,退出代码为1(使用-v查看调用)ninja:build stopped:子命令失败 .

1 回答

  • 2

    AES是块密码,块长度为16个字节 . 这里的问题是 aes_encrypt()aes_decrypt() 是低级函数,只能在一个块上运行(你不知道,为什么没有长度参数?) . 因此,您只加密和解密了16个字节的演示字符串,其余的解密缓冲区仍保持未初始化!

    因此,您应该迭代以在更多块上操作,或者使用更高级别的接口,如EVP-functionfamily . 一个好的入门书是OpenSSL Wiki

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

相关问题