1. 程式人生 > >JAVA android IOS AES通用加密

JAVA android IOS AES通用加密

1、環境:JDK6 

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