JNI calls C + + for AES encryption and decryption

Source: Internet
Author: User
Tags decrypt

Data encryption and decryption are used in recent projects, which are required for Android, iOS, and server-side functions. The encryption on different platforms is not the same, resulting in the ciphertext can not be used. The decision was made to use C + + to complete encryption and decryption, and other platform invoke methods to handle.

    • Cryptographic decryption implementation

The implementation of AES encryption is not discussed in this article, the implementation code is directly extracted from the OpenSSL source.

Cryptographic decryption calls the following two methods:

int aes_encrypt (charchar char * out) encryption // plaintext, key, cipher int Aes_decrypt (charchar char * out) decryption // ciphertext, key, clear text

The plaintext needs to be obtained externally, and in general the key needs to be customized, so it is externally acquired; out is the result of encryption or decryption and needs to be returned to the caller.

So the next thing to do is to get the external data, give the encryption and decryption method processing, return the results to the outside.

    • Writing a Java local method

The Java call C + + code is implemented by JNI, and the native method needs to be declared in Java.

Aesutil.java
 Public class aesutil{    publicnative  string Encrypt (string plaintext, string key);      Public native string Decrypt (string ciphertext, string key);}

Javac compiled Aesutil.java generates class file Aesutil.class.

Javah Aesutil generates AESUtil.h, which will be included as a header file in the C project.

Open AESUtil.h with the following code:

/*Do not EDIT this file-it are machine generated*/#include<jni.h>/*Header for Class Aesutil*/#ifndef _included_aesutil#define_included_aesutil#ifdef __cplusplusextern "C" {#endif/** Class:aesutil * method:encrypt * Signature: (ljava/lang/string; ljava/lang/string;) ljava/lang/string; */jniexport jstring jnicall java_aesutil_encrypt (jnienv*, Jobject, jstring, jstring);/** Class:aesutil * method:decrypt * Signature: (ljava/lang/string; ljava/lang/string;) ljava/lang/string; */jniexport jstring jnicall java_aesutil_decrypt (jnienv*, Jobject, jstring, jstring); #ifdef __cplusplus}#endif#endif

The header file declares two methods Java_aesutil_encrypt and Java_aesutil_decrypt, respectively, corresponding to the two native methods in Java encrypt and decrypt. The two string arguments passed in the two native methods are converted to the Jstring type in the header file. With this type we can implement the conversion of strings between Java and C.

    • Implementing methods that are called in Java in C + +

These two methods need to be implemented after the header file is introduced. New AESUtil.cpp, introduce AESUtil.h, implement the encryption and decryption method of declaration:

#defineLEN 512jniexport jstring jnicall java_aesutil_encrypt (jnienv*env, Jobject obj, jstring s, jstring K) {        //Converts a string that needs to be encrypted into a const char* type        Const Char* str = Env->getstringutfchars (S,0); //Key string converted into char*        Char* Key = (Char*) Env->getstringutfchars (k,0); inti; CharSource[len]; CharDst[len]; memset ((Char*) Source,0, LEN); memset ((Char*) DST,0, LEN);        strcpy (source, str); if(!aes_encrypt (SOURCE,KEY,DST))//(in,key,out)//Encrypt{printf ("Encrypt error\n"); }        Chart[3]; stringTempStr; intreallen=LEN;  for(i=len-1;! dst[i];i--) {//The encryption result may contain ' \ s ', while ' \ ' is the end of the string in C + +, so in order to ensure that the ciphertext after ' s ' can be removed, starting from the end of the array, the first element that is not ' s ' is the last value we want to take.Reallen =i; }         for(i=0; i<=reallen-1; i+=1){//Converts cryptographic results to 16, stitching into string outputsprintf (T,"%x", (unsignedChar) dst[i]); if((unsignedChar) dst[i]<=0x0f) {TempStr= tempstr+"0"+T; }Else{tempstr= tempstr+T; }                    }        Char*data= (Char*) Tempstr.data (); returnENV-&GT;NEWSTRINGUTF (data);//Convert char* to jstring as a result with the conversion method provided by JNI}jniexport jstring jnicall java_aesutil_decrypt (jnienv*env, Jobject obj, jstring s, jstring K) {        Const Char* str = Env->getstringutfchars (S,0); Char* Key = (Char*) Env->getstringutfchars (k,0); inti; CharSource[len]; CharDst[len]; memset ((Char*) Source,0, LEN); memset ((Char*) DST,0, LEN);        strcpy (DST,STR); CharData[len]; intj =0; memset ((Char*) data,0, LEN); intlen=strlen (DST);  for(i=0;d st[i];i++){                if((i+1)%2==0){//the encryption results in a string of 22 separated into hexadecimal translated into a specific value into the array for decryptionDATA[J] = Ascii2hex (& (Char) dst[i-1]),1)* -+ascii2hex (& (Char) Dst[i]),1); J++; }        }        if(!Aes_decrypt (Data,key,source)) {printf ("Decrypt error\n"); }        returnEnv->Newstringutf (source); }

You can see that jni.h is introduced into the generated header file, and the method we use to convert the string between Java and C + + is from that file. Jni.h can be found from the JDK installation directory \include, and jni_mod.h can be found under the JDK installation directory \include\win32.

Java calls C + + needs to be done by calling the DLL, so we need to build the C + + DLL, I am here directly in the VS2010 to create a new DLL project, specifically can Google.

After building the DLL and adding it to classpath, I put it directly underneath the JDK root \ bin. You can also add the directory that contains the DLL to the environment variable.

    • Calling the Java local method

DLL generated, Java method has, the following is called method to test ~ ~ ~

 Public classStringUtils { Public Static voidMain (string[] args) {system.loadlibrary ("Aescpp");//load DLL, do not need to include a. dll suffix nameAesutil s =NewAesutil ();//the native method is included in the AesutilString plain = "[Email protected]#&*99huiwb1=-";//plaintextSystem.out.println (plain); String Key= "1234567890123456afhiu$^&682036490";//secret keyString str = s.encrypt (Plain,key);//EncryptSystem.out.println ("\nhahaha:\n" +str);//Print ResultsSystem.out.println ("Length:" +str.length ()); System.out.println ("@@@@@@@@@@@"); String SS= S.decrypt (Str,key);//decryptionSYSTEM.OUT.PRINTLN ("----->-------->"); SYSTEM.OUT.PRINTLN (ss);//Decryption Results    }    }
Run for a Moment ~

You can see that the encryption and decryption results are consistent.

The results we get in C + + code are stored in the dst[] array, and the Mi Wenzheng we get is the string that the values in the array are converted into hexadecimal output after they are spelled. When decrypting, we need to take these strings 22 apart (62,f8,a8 ... ) is re-deposited in the array for decryption.

This is probably the case with Windows.

The. So file needs to be generated under Linux because DLL files cannot be called. In addition to introducing jni.h and Jni_mod.h, these two files are required for Linux under the JDK directory. It can be done in Google, similar to Windows.

    • Called in Android

Previously generated under Linux. So is because the DLL is not available in Android, but after the success of Linux built into Android discovery or not to use, and Android and Linux are not too familiar with, after the discovery of Linux is x86_64 platform, And the tested Android phone is the arm platform.

So there's a new thing: ndk~~.

Specific NDK environment construction will not repeat, I was the link to build the http://my.oschina.net/lifj/blog/176916

After setting up the environment, first create a new Android project Aestest under Eclipse.

Right-click the project name to select Android Tools->add Native support.

To open the Android.mk file under the JNI directory, you can see the following code: (You can not join yourself)

Local_path: = $ (call my-dir) include $ (clear_vars) local_module    := aesutillocal_src_files:=  Aesutil.cppinclude $ (build_shared_library)

The corresponding value of Local_module is the string to be used when loading the library (system.loadlibrary ("XXX");)

The corresponding value of the local_src_files represents the file where the implementation method resides.

New file application.mk under JNI directory, join

App_stl:=stlport_static

Do not add this file before the C + + method will be error, the specific reason has not been explored, just search error information from the StackOverflow found this method.

In the JNI directory, add the header and implementation files that we used to generate the DLLs.

Open Cygwin, enter the project root directory, enter the $ndk/ndk-build to generate so file

You can see that the so file is generated under the Libs/armeabi folder, and the file is compiled and run in the Android code.

Embarrassed ~ first time to write a blog ~ ~ Off =_=

JNI calls C + + for AES encryption and decryption

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.