AES encryption — the solution of Java and iOS

Wikipedia on AES’s encryption explanation:

Advanced Encryption Standard (English: Advanced, Encryption, Standard, abbreviation: AES), also called Rijndael encryption in cryptography, is a kind of block encryption standard adopted by the federal government. This standard is used to replace the original DES, has been analyzed by many parties, and widely used around the world. After five years of selection process, the advanced encryption standard was released by the National Institute of standards and Technology (NIST) in November 26, 2001 at FIPS PUB 197, and became an effective standard in May 26, 2002. In 2006, advanced encryption standard has become one of the most popular algorithms in symmetric key cryptography.

The algorithm is designed by Belgian cryptography experts Joan Daemen and Vincent Rijmen, and combines the names of two authors in order to contribute to the selection process of advanced encryption standards in the name of Rijndael. (Rijndael’s pronunciation is close to “Rhine Doll”)

Strictly speaking, AES and Rijndael encryption method is not exactly the same (although both in the practical application, because of the block can be interchanged) and the length of the key Rijndael encryption method can support a wider range of AES fixed block length is 128 bits, key length can be 128192 or 256 bits; and the key and the block length is Rijndael can be an integer multiple of 32 bits, 128 bits to 256 bits for the upper limit. The keys used during encryption are generated by the Rijndael key generation scheme.

Most AES computations are done in a particular finite field.

AES encryption process is operating in a 4 x 4 byte matrix, the matrix is also known as “the body (state), its initial value is a plaintext block (a Byte the size of the matrix is clearly an element in the block). (Rijndael encryption support larger blocks, which can increase the number of rows in each round) encryption, AES encryption cycle (except the last round outside) contains 4 steps:

  1. Each byte in the AddRoundKey – matrix is XOR with the second round key (round, key); each subkey is generated by the key generation scheme.
  2. SubBytes – replaces each byte with the look-up table in the form of a look-up table by means of a non-linear substitution function.
  3. ShiftRows – each in the row matrix cyclic shift.
  4. MixColumns – in order to fully mix the straight lines in the matrix. This step uses a linear transformation to blend four bytes per inline. In the last encryption loop, omit the MixColumns step and replace it with another AddRoundKey.

Today, after the mobile terminal and the back-end agreement using AES encryption method, there will always be some problems encountered, and today I will use the iOS side and the Java side as an example to explain the mobile terminal and back-end AES encryption method.

First, we use AES encryption method, to determine the mode encryption mode and pad filling method, and in this project I choose CBC encryption mode and PKCS5 filling method, and the use of the AES+Base64 data encryption and decryption.

These patterns, as well as the choice of filling methods, will be reflected in our code.

AES encryption of iOS platform

First, we’ll create a category for the NSData class. And refer to the header file

#import < CommonCrypto/CommonCryptor.h>

Simply use AES encryption and decryption code as follows

/ / (key and IV vector here is 16 bits) this is the CBC encryption mode, higher security - (NSData) AES128EncryptWithKey: (NSString * key) gIv: (NSString *) Iv{// encryption char keyPtr[kCCKeySizeAES128+1]; (keyPtr, bZero sizeof (keyPtr)); [key getCString:keyPtr maxLength:sizeof (keyPtr) encoding:NSUTF8StringEncoding]; char ivPtr[kCCKeySizeAES128+1]; memset (ivPtr, 0, sizeof (ivPtr)); [Iv getCString:ivPtr maxLength:sizeof (ivPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc (bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus = CCCrypt (kCCEncrypt, kCCAlgorith, cryptStatus MAES128, kCCOptionPKCS7Padding, keyPtr, kCCBlockSizeAES128, ivPtr, [self, bytes], dataLength, buffer, bufferSize, & numBytesEncrypted); if (cryptStatus = = kCCSuccess) {return [NSData} dataWithBytesNoCopy:buffer length: numBytesEncrypted]; free (buffer); return nil;} //AES (NSData * AES128DecryptWithKey:) - decryption (NSString * gIv: * NSString (key) Iv) {char keyPtr[kCCKeySizeAES128+1]; bZero (keyPtr, sizeof (keyPtr)); [key getCString:keyPtr maxLength:sizeof (keyPtr) encoding:NSUTF8StringEncoding]; char ivPtr[kCCKeySizeAES128+1]; memset (ivPtr, 0, sizeof (ivPtr)); [Iv getCString:ivPtr maxLength:sizeof (ivPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void = *buffer malloc (bufferSize); size_t numBytesDecrypted = 0; CCCryptorStatus cryptStatus = CCCrypt (kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, KCCBlockSizeAES128, ivPtr, [self, bytes], dataLength, buffer, bufferSize, & numBytesDecrypted); if (cryptStatus = = kCCSuccess) {return} [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; free (buffer); return nil;}

As we said before, there is a need for mixed encryption and decryption with AES+Base64 data.

What about a complete and detailed encryption process?.

Look at the following code

#pragma mark - AES / String convert encrypted with a password of data + (NSString*) neu_encryptAESData: (NSString* string) {/ / nsstring into nsdata NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; / / use the password encryption NSData * encryptedData = [data AES128EncryptWithKey:KEY gIv:Iv] nsdata; / / return to Base64 return [self encodeBase64Data:encryptedData] transcoding encryption string;}

The above is the encryption method we use, the note is very detailed, of course, – encodeBase64Data: method is that I have wrapped it up, when the time to download it out of use.

So when we encrypt and decrypt, as long as the call + (NSString*) neu_encryptAESData: (NSString*) string this method can be, is it actually very simple and convenient?. Decrypt the code, I also paste it, is the same simple.

#pragma mark - AES / data password decryption will turn into string + (NSString*) neu_decryptAESData: (NSString *) string //base64 NSData *decodeBase64Data=[NEUBase64 decodeString:string] {decryption; / / use the password to decrypt the NSData *decryData = AES128DecryptWithKey:KEY gIv:Iv] [decodeBase64Data to data; / / solution password nsdata into nsstring NSString *str = [[NSString alloc] initWithData:decryData encoding:NSUTF8StringEncoding]; return str;}

The AES encryption of the iOS platform ends here.

AES encryption of Java platform

Java platform encryption and decryption, all configuration and principle and iOS end is the same, so I’m lazy, directly to the Java side of the code paste up.

Import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; Created by Lix on 16/9/21. / * * * * public class AESOperator * Key {/ * encrypted with the encryption mode used here can be composed of AES-128-CBC with 26 letters and numbers, key to 16. * private String sKey = "ed16b1f8a9e648d4"; private String ivParameter = "ed16b1f8a9e648d4"; private static AESOperator instance (private = null; AESOperator) {public} static {if (getInstance) AESOperator (instance = = null) instance = new (AESOperator); return instance; public static String Encrypt} (String encData, String secretKey throws Exception, String vector) {if (secretKey = = null) {return null;} if (secretKey.length ()! = 16) {return null}; Cipher cipher = Cipher.getInstance ("AES/CBC/PKCS5Padding"); byte[] raw = secretKey.getBytes (SecretKeySpec); skeySpec new = SecretKeySpec (raw, AE " S "); IvParameterSpec IV = new (IvParameterSpec) (vector.getBytes); / / CBC mode requires a vector IV, can increase the strength of cipher.init encryption algorithm (Cipher.ENCRYPT_MODE, skeySpec, IV); byte[] encrypted = cipher.doFinal (encData.getBytes (" UTF-8 ")); return new (BASE64Encoder).Encode (encrypted); here the use of BASE64 / / do transcoding. Public String encrypt} / / encryption (String sSrc) throws Exception {Cipher cipher = Cipher.getInstance ("AES/CBC/PKCS5Padding"); byte[] raw = sKey.getBytes (SecretKeySpec); skeySpec new = SecretKeySpec (raw, AES); IvParameterSpec IV = new (IvParameterSpec) (ivParameter.getBytes); / / CBC mode requires a vector IV that can increase the strength of cipher.init encryption algorithm (Cipher.ENCRYPT_MODE, skeySpec, IV); byte[] encrypted = cipher.doFinal (sSrc.getBytes ("UTF-8")); return new (BASE64Encoder).Encode (encrypted); / / to make use of BASE64 transcoding. Public String decrypt} / / decryption (String sSrc) throws Exception {try {byte[] raw = sKey.getBytes ("ASCII"); SecretKeySpec skeySpec = new SecretKeySpec (raw, AES); Cipher cipher = Cipher.getInstance ("AES/CBC/PKCS5Padding"); IvParameterSpec IV = new (IvParameterSpec (ivParameter.getBytes) cipher.init (Cipher.DECRYPT_MODE, skeySpec); IV; byte[], encrypted1) = new (BASE64Decoder).DecodeBuffer (sSrc); / / the first Base64 decryption byte[] original = cipher.doFinal (encrypted1); String originalString = new String (original, UTF-8); return originalString;} catch (Exception Ex) {return null;}} p Ublic String decrypt (String sSrc, String key, String IVS, throws Exception) {try {byte[] raw = key.getBytes ("ASCII"); SecretKeySpec skeySpec = new SecretKeySpec (raw, AES); Cipher cipher = Cipher.getInstance ("AES/CBC/ PKCS5Padding"); IvParameterSpec IV = new IvParameterSpec (ivs.getBytes) (cipher.init); (Cipher.DECRYPT_MODE, skeySpec, IV); byte[] encrypted1 = new (BASE64Decoder).DecodeBuffer (sSrc); / / the first Base64 decryption byte[] original = cipher.doFinal (encrypted1); String originalString = new String (original, UTF-8); return originalString;} catch (Exception Ex) {return null}}; public sta Tic String encodeBytes (byte[] bytes) {StringBuffer strBuf = new (StringBuffer); for (int i = 0; I < bytes.length; i++) {strBuf.append ((char) (((bytes[i] > > & 4) (0xF) + (int)'a') strBuf.append ((char)); (() (bytes[i]) & (0xF) + (int)'a') return (strBuf.toString));}}); public static void main throws Exception (String[] args) {/ / encrypted string String cSrc = 123456; / / lStart = System.currentTimeMillis (long encryption enString = AESOperator.getInstance (String);.Encrypt (cSrc)); System.out.println ("the encrypted string is:" + enString); long lUseTime = System.currentTimeMillis (- lStart); System.out.println ("encryption time:" + lUseTime + "Ms"); / / lStart = (System.currentTimeMillis); decryption String = AESOperator.getInstance (DeString).Decrypt (enString); System.out.println ("the decrypted string is:" + DeString); lUseTime = System.currentTimeMillis (- lStart); System.out.println ("decryption time:" + lUseTime + "Ms");}}

Java side and iOS side of the code, are here, and I hope to help you, you can Star.