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