Original: Ios,android,. NET Universal AES Encryption algorithm
These two days for the mobile app development API, the results of encryption verification encountered a big pit. It had to be spit down and smelly and hard ios,windows server could not decrypt the correct results, Android could, and later used the Universal AES256 encryption algorithm to finally fix it.
The server side of the small partner did not contact the iOS, so also did not expect this situation. He uses the AES128 with IV encryption algorithm, the Android side can pass the encryption authentication smoothly.
However, the iOS side uses the AES128 algorithm after the problem, although the local encryption can be decrypted, but could not be decrypted by the server successfully.
Later through the multi-find, only to understand the fact that an egg hurts, iOS only support AES pkcs7padding algorithm, after the server-side modified to respond to the algorithm, successfully passed.
Here is the main reference to a blog post, the following general AES algorithm:
Objective-c:
Header file
#import <Foundation/Foundation.h>@interface nsdata (AES)-(NSData *) Aes256encryptwithkey: (NSString *) key; -(NSData *) Aes256decryptwithkey: (NSString *) key; @end
Implementation code:
#import "nsdata+aes256.h"#import<CommonCrypto/CommonCryptor.h>@implementationNSData (AES)-(NSData *) Aes256encryptwithkey: (NSString *) Key {//' key ' should is bytes for AES256, 'll be null-padded otherwise Charkeyptr[kcckeysizeaes256+1];//Terminator (unused)Bzero (Keyptr,sizeof(keyptr));//fill with zeroes (for padding)//Fetch key Data[Key getcstring:keyptr MaxLength:sizeof(KEYPTR) encoding:nsutf8stringencoding]; Nsuinteger datalength=[self length]; //See the doc:for block ciphers, the output size would always be less than or//equal to the input size plus the size of one block. //That's why we need to add the size of a block heresize_t buffersize = datalength +kCCBlockSizeAES128; void*buffer =malloc (buffersize); size_t numbytesencrypted=0; Cccryptorstatus Cryptstatus=Cccrypt (Kccencrypt, kCCAlgorithmAES128, kccoptionpkcs7padding, Keyptr, Kccke ySizeAES256, NULL/*initialization vector (optional)*/, [self bytes], datalength,/*input*/buffer, buffersize,/*Output*/&numbytesencrypted); if(Cryptstatus = =kccsuccess) { //The returned NSData takes ownership of the buffer and would free it on deallocation return[NSData Datawithbytesnocopy:buffer length:numbytesencrypted]; } free (buffer); //Free the buffer; returnNil;}-(NSData *) Aes256decryptwithkey: (NSString *) Key {//' key ' should is bytes for AES256, 'll be null-padded otherwise Charkeyptr[kcckeysizeaes256+1];//Terminator (unused)Bzero (Keyptr,sizeof(keyptr));//fill with zeroes (for padding)//Fetch key Data[Key getcstring:keyptr MaxLength:sizeof(KEYPTR) encoding:nsutf8stringencoding]; Nsuinteger datalength=[self length]; //See the doc:for block ciphers, the output size would always be less than or//equal to the input size plus the size of one block. //That's why we need to add the size of a block heresize_t buffersize = datalength +kCCBlockSizeAES128; void*buffer =malloc (buffersize); size_t numbytesdecrypted=0; Cccryptorstatus Cryptstatus=Cccrypt (Kccdecrypt, kCCAlgorithmAES128, kccoptionpkcs7padding, Keyptr, Kccke ySizeAES256, NULL/*initialization vector (optional)*/, [self bytes], datalength,/*input*/buffer, buffersize,/*Output*/&numbytesdecrypted); if(Cryptstatus = =kccsuccess) { //The returned NSData takes ownership of the buffer and would free it on deallocation return[NSData Datawithbytesnocopy:buffer length:numbytesdecrypted]; } free (buffer); //Free the buffer; returnNil;}@end
C#:
#region /// <summary> ///256-bit AES encryption/// </summary> /// <param name= "Toencrypt" ></param> /// <returns></returns> Public Static stringEncrypt (stringToencrypt) { //256-aes Key byte[] Keyarray =UTF8Encoding.UTF8.GetBytes (key); byte[] Toencryptarray =UTF8Encoding.UTF8.GetBytes (Toencrypt); RijndaelManaged Rdel=Newrijndaelmanaged (); Rdel.key=Keyarray; Rdel.mode=CIPHERMODE.ECB; Rdel.padding=PADDINGMODE.PKCS7; ICryptoTransform Ctransform=Rdel.createencryptor (); byte[] Resultarray = Ctransform.transformfinalblock (Toencryptarray,0, toencryptarray.length); returnConvert.tobase64string (Resultarray,0, resultarray.length); } /// <summary> ///256-bit AES decryption/// </summary> /// <param name= "Todecrypt" ></param> /// <returns></returns> Public Static stringDecrypt (stringTodecrypt) { //256-aes Key byte[] Keyarray =UTF8Encoding.UTF8.GetBytes (key); byte[] Toencryptarray =convert.frombase64string (Todecrypt); RijndaelManaged Rdel=Newrijndaelmanaged (); Rdel.key=Keyarray; Rdel.mode=CIPHERMODE.ECB; Rdel.padding=PADDINGMODE.PKCS7; ICryptoTransform Ctransform=Rdel.createdecryptor (); byte[] Resultarray = Ctransform.transformfinalblock (Toencryptarray,0, toencryptarray.length); returnUTF8Encoding.UTF8.GetString (resultarray); } #endregion
Java:
Importjava.io.UnsupportedEncodingException;Importjava.security.InvalidAlgorithmParameterException;Importjava.security.InvalidKeyException;Importjava.security.NoSuchAlgorithmException;Importjava.util.Arrays;Importjavax.crypto.BadPaddingException;ImportJavax.crypto.Cipher;Importjavax.crypto.IllegalBlockSizeException;Importjavax.crypto.NoSuchPaddingException;ImportJavax.crypto.spec.IvParameterSpec;ImportJavax.crypto.spec.SecretKeySpec;Importandroid.util.Base64; Public classAesutils {/*** Encryption *@paramcontent needs to be encrypted *@paramPassword encrypted password *@return */ Private StaticString key= "gca*23jkjf0df09osf09834ljljf0920"; Public StaticString encode (String stringtoencode)throwsNullPointerException {Try{secretkeyspec Skeyspec=GetKey (Key); byte[] cleartext = Stringtoencode.getbytes ("UTF8"); Final byte[] IV =New byte[16]; Arrays.fill (iv, (byte) 0x00); Ivparameterspec Ivparameterspec=NewIvparameterspec (iv); Cipher Cipher= Cipher.getinstance ("aes/cbc/pkcs7padding"); Cipher.init (Cipher.encrypt_mode, Skeyspec, Ivparameterspec); String Encrypedvalue=base64.encodetostring (cipher.dofinal (cleartext), base64.default); returnEncrypedvalue; } Catch(InvalidKeyException e) {e.printstacktrace (); } Catch(unsupportedencodingexception e) {e.printstacktrace (); } Catch(nosuchalgorithmexception e) {e.printstacktrace (); } Catch(badpaddingexception e) {e.printstacktrace (); } Catch(nosuchpaddingexception e) {e.printstacktrace (); } Catch(illegalblocksizeexception e) {e.printstacktrace (); } Catch(invalidalgorithmparameterexception e) {e.printstacktrace (); } return""; } Private StaticSecretkeyspec GetKey (String password)throwsunsupportedencodingexception {intKeylength = 256; byte[] Keybytes =New byte[KEYLENGTH/8]; Arrays.fill (Keybytes, (byte) 0x0); byte[] passwordbytes = Password.getbytes ("UTF-8"); intLength = Passwordbytes.length < keybytes.length?passwordBytes.length:keyBytes.length; System.arraycopy (Passwordbytes,0, Keybytes, 0, length); Secretkeyspec Key=NewSecretkeyspec (Keybytes, "AES"); returnkey; } }
Ios,android,. NET Universal AES Encryption algorithm