JAVA android IOS AES通用加密
阿新 • • 發佈:2019-02-10
1、環境:JDK6
2、IOS端
本文原文轉至:http://my.oschina.net/nicsun/blog/95632?p=2#comments
2、涉及JAR包:
bcprov-jdk15on-152.jar 下載地址:http://www.bouncycastle.org/latest_releases.html 存在位置專案lib目錄下
local_policy.jar、US_export_policy.jar 下載地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html 當前使用JDK路徑下:\jre\lib\security替換原始檔
1、JAVA和ANDROID端:
package encrypt.ios; import java.io.UnsupportedEncodingException; import java.security.Key; import java.security.Security; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class AES256Encryption{ /** * 金鑰演算法 * java6支援56位金鑰,bouncycastle支援64位 * */ public static final String KEY_ALGORITHM="AES"; /** * 加密/解密演算法/工作模式/填充方式 * * JAVA6 支援PKCS5PADDING填充方式 * Bouncy castle支援PKCS7Padding填充方式 * */ public static final String CIPHER_ALGORITHM="AES/ECB/PKCS7Padding"; /** * * 生成金鑰,java6只支援56位金鑰,bouncycastle支援64位金鑰 * @return byte[] 二進位制金鑰 * */ public static byte[] initkey() throws Exception{ //例項化金鑰生成器 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM, "BC"); //初始化金鑰生成器,AES要求金鑰長度為128位、192位、256位 kg.init(256); // kg.init(128); // //生成金鑰 SecretKey secretKey=kg.generateKey(); //獲取二進位制金鑰編碼形式 return secretKey.getEncoded(); /* //為了便於測試,這裡我把key寫死了,如果大家需要自動生成,可用上面註釋掉的程式碼 return new byte[] { 0x08, 0x08, 0x04, 0x0b, 0x02, 0x0f, 0x0b, 0x0c, 0x01, 0x03, 0x09, 0x07, 0x0c, 0x03, 0x07, 0x0a, 0x04, 0x0f, 0x06, 0x0f, 0x0e, 0x09, 0x05, 0x01, 0x0a, 0x0a, 0x01, 0x09, 0x06, 0x07, 0x09, 0x0d };*/ } /** * 轉換金鑰 * @param key 二進位制金鑰 * @return Key 金鑰 * */ public static Key toKey(byte[] key) throws Exception{ //例項化DES金鑰 //生成金鑰 SecretKey secretKey=new SecretKeySpec(key,KEY_ALGORITHM); return secretKey; } /** * 加密資料 * @param data 待加密資料 * @param key 金鑰 * @return byte[] 加密後的資料 * */ public static byte[] encrypt(byte[] data,byte[] key) throws Exception{ //還原金鑰 Key k=toKey(key); /** * 例項化 * 使用 PKCS7PADDING 填充方式,按如下方式實現,就是呼叫bouncycastle元件實現 * Cipher.getInstance(CIPHER_ALGORITHM,"BC") */ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM, "BC"); //初始化,設定為加密模式 cipher.init(Cipher.ENCRYPT_MODE, k); //執行操作 return cipher.doFinal(data); } /** * 加密資料 * @param data 待加密資料 * @param key 金鑰 * @return byte[] 加密後的資料 * */ public static byte[] encrypt(byte[] data,String key) throws Exception{ //還原金鑰 Key k=toKey((new BASE64Decoder()).decodeBuffer(key)); /** * 例項化 * 使用 PKCS7PADDING 填充方式,按如下方式實現,就是呼叫bouncycastle元件實現 * Cipher.getInstance(CIPHER_ALGORITHM,"BC") */ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM, "BC"); //初始化,設定為加密模式 cipher.init(Cipher.ENCRYPT_MODE, k); //執行操作 return cipher.doFinal(data); } /** * 解密資料 * @param data 待解密資料 * @param key 金鑰 * @return byte[] 解密後的資料 * */ public static byte[] decrypt(byte[] data,byte[] key) throws Exception{ //歡迎金鑰 Key k =toKey(key); /** * 例項化 * 使用 PKCS7PADDING 填充方式,按如下方式實現,就是呼叫bouncycastle元件實現 * Cipher.getInstance(CIPHER_ALGORITHM,"BC") */ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM, "BC"); //初始化,設定為解密模式 cipher.init(Cipher.DECRYPT_MODE, k); //執行操作 return cipher.doFinal(data); } /** * 解密資料 * @param data 待解密資料 * @param key 金鑰 * @return byte[] 解密後的資料 * */ public static byte[] decrypt(byte[] data,String key) throws Exception{ //歡迎金鑰 Key k =toKey((new BASE64Decoder()).decodeBuffer(key)); /** * 例項化 * 使用 PKCS7PADDING 填充方式,按如下方式實現,就是呼叫bouncycastle元件實現 * Cipher.getInstance(CIPHER_ALGORITHM,"BC") */ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM, "BC"); //初始化,設定為解密模式 cipher.init(Cipher.DECRYPT_MODE, k); //執行操作 return cipher.doFinal(data); } /** * @param args * @throws UnsupportedEncodingException * @throws Exception */ public static void main(String[] args) throws UnsupportedEncodingException{ String str="AES"; System.out.println("原文:"+str); //初始化金鑰 byte[] key; try { key = (new BASE64Decoder()).decodeBuffer("Fum0rCudZw/fvNCXi05o/NGUqNQuZizD/+xK1FarK38=");//AES256Encryption.initkey(); System.out.println("BASE64金鑰:" + (new BASE64Encoder()).encodeBuffer(key)); System.out.print("\n"); System.out.println("金鑰長度:"+key.length); System.out.print("\n"); System.out.println("金鑰BYTE:"+key.toString()); System.out.print("\n"); System.out.print("金鑰:"); for(int i = 0;i<key.length;i++){ System.out.printf("%x", key[i]); } System.out.print("\n"); //加密資料 byte[] data=AES256Encryption.encrypt(str.getBytes(), key); System.out.print("加密後:"); for(int i = 0;i<data.length;i++){ System.out.printf("%x", data[i]); } System.out.print("\n"); String dateBase64 = new BASE64Encoder().encodeBuffer(data ); System.out.println("加密後BSE64:" + new BASE64Encoder().encodeBuffer(data)); //解密資料 data=AES256Encryption.decrypt(new BASE64Decoder().decodeBuffer("V05aWtYB3G+a689gCGe4CWeFgKu1/X2Zmk9XUD6QflxdbQtjExxZe2PAdFqYnB+c/wCj40VW6ycSmG/rTLdkjA=="), key); System.out.println("解密後:"+new String(data)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
2、IOS端
EncryptAndDecrypt.h檔案 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // // EncryptAndDecrypt.h // AES256EncryptionDemo // // Created by rich sun on 12-12-13. // Copyright (c) 2012年 rich sun. All rights reserved. // #import <Foundation/Foundation.h> @class NSString; @interface NSData (Encryption) - (NSData *)AES256EncryptWithKey:(NSData *)key; //加密 - (NSData *)AES256DecryptWithKey:(NSData *)key; //解密 - (NSString *)newStringInBase64FromData; //追加64編碼 + (NSString*)base64encode:(NSString*)str; //同上64編碼 @end EncryptAndDecrypt.m檔案 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 // // EncryptAndDecrypt.m // AES256EncryptionDemo // // Created by rich sun on 12-12-13. // Copyright (c) 2012年 rich sun. All rights reserved. // #import "EncryptAndDecrypt.h" #import <CommonCrypto/CommonCrypto.h> static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @implementation NSData (Encryption) - (NSData *)AES256EncryptWithKey:(NSData *)key //加密 { //AES256加密,金鑰應該是32位的 const void * keyPtr2 = [key bytes]; char (*keyPtr)[32] = keyPtr2; //對於塊加密演算法,輸出大小總是等於或小於輸入大小加上一個塊的大小 //所以在下邊需要再加上一個塊的大小 NSUInteger dataLength = [self length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding/*這裡就是剛才說到的PKCS7Padding填充了*/ | kCCOptionECBMode, [key bytes], kCCKeySizeAES256, NULL,/* 初始化向量(可選) */ [self bytes], dataLength,/*輸入*/ buffer, bufferSize,/* 輸出 */ &numBytesEncrypted); if (cryptStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer);//釋放buffer return nil; } - (NSData *)AES256DecryptWithKey:(NSData *)key //解密 { //同理,解密中,金鑰也是32位的 const void * keyPtr2 = [key bytes]; char (*keyPtr)[32] = keyPtr2; //對於塊加密演算法,輸出大小總是等於或小於輸入大小加上一個塊的大小 //所以在下邊需要再加上一個塊的大小 NSUInteger dataLength = [self length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesDecrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding/*這裡就是剛才說到的PKCS7Padding填充了*/ | kCCOptionECBMode, keyPtr, kCCKeySizeAES256, NULL,/* 初始化向量(可選) */ [self bytes], dataLength,/* 輸入 */ buffer, bufferSize,/* 輸出 */ &numBytesDecrypted); if (cryptStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; } free(buffer); return nil; } - (NSString *)newStringInBase64FromData //追加64編碼 { NSMutableString *dest = [[NSMutableString alloc] initWithString:@""]; unsigned char * working = (unsigned char *)[self bytes]; int srcLen = [self length]; for (int i=0; i<srcLen; i += 3) { for (int nib=0; nib<4; nib++) { int byt = (nib == 0)?0:nib-1; int ix = (nib+1)*2; if (i+byt >= srcLen) break; unsigned char curr = ((working[i+byt] << (8-ix)) & 0x3F); if (i+nib < srcLen) curr |= ((working[i+nib] >> ix) & 0x3F); [dest appendFormat:@"%c", base64[curr]]; } } return dest; } + (NSString*)base64encode:(NSString*)str { if ([str length] == 0) return @""; const char *source = [str UTF8String]; int strlength = strlen(source); char *characters = malloc(((strlength + 2) / 3) * 4); if (characters == NULL) return nil; NSUInteger length = 0; NSUInteger i = 0; while (i < strlength) { char buffer[3] = {0,0,0}; short bufferLength = 0; while (bufferLength < 3 && i < strlength) buffer[bufferLength++] = source[i++]; characters[length++] = base64[(buffer[0] & 0xFC) >> 2]; characters[length++] = base64[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >> 4)]; if (bufferLength > 1) characters[length++] = base64[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >> 6)]; else characters[length++] = '='; if (bufferLength > 2) characters[length++] = base64[buffer[2] & 0x3F]; else characters[length++] = '='; } NSString *g = [[NSString alloc] initWithBytesNoCopy:characters length:length encoding:NSASCIIStringEncoding freeWhenDone:YES]; return g; } @end ViewController.m檔案 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 // // ViewController.m // AES256EncryptionDemo // // Created by 孫 裔 on 12-12-13. // Copyright (c) 2012年 rich sun. All rights reserved. // #import "ViewController.h" #import "EncryptAndDecrypt.h" @interface ViewController () @end @implementation ViewController @synthesize plainTextField; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } //這個函式實現了使用者輸入完後點擊檢視背景,關閉鍵盤 - (IBAction)backgroundTap:(id)sender{ [plainTextField resignFirstResponder]; } - (IBAction)encrypt:(id)sender { NSString *plainText = plainTextField.text;//明文 NSData *plainTextData = [plainText dataUsingEncoding:NSUTF8StringEncoding]; //為了測試,這裡先把金鑰寫死 Byte keyByte[] = {0x08,0x08,0x04,0x0b,0x02,0x0f,0x0b,0x0c,0x01,0x03,0x09,0x07,0x0c,0x03, 0x07,0x0a,0x04,0x0f,0x06,0x0f,0x0e,0x09,0x05,0x01,0x0a,0x0a,0x01,0x09, 0x06,0x07,0x09,0x0d}; //byte轉換為NSData型別,以便下邊加密方法的呼叫 NSData *keyData = [[NSData alloc] initWithBytes:keyByte length:32]; // NSData *cipherTextData = [plainTextData AES256EncryptWithKey:keyData]; Byte *plainTextByte = (Byte *)[cipherTextData bytes]; for(int i=0;i<[cipherTextData length];i++){ printf("%x",plainTextByte[i]); } } @end
本文原文轉至:http://my.oschina.net/nicsun/blog/95632?p=2#comments