android AES加密
来源:互联网 发布:linux用户和组管理 编辑:程序博客网 时间:2024/05/17 06:25
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://xuxiong3316.blog.51cto.com/8126857/1343251
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/***
* 关于加解密JAVA一般使用的JCE,关于C++可以实现AES加解密的开源项目就多的数不胜数的。
理论上上算法一样,对称密钥一样就能够互相识别了。
相信很多人开始想法都同我一样,起初我JAVA用JCE,C++使用openssl。
结果发现加密出的密文完全不相同。
出现问题就要解决
了解了一下JCE:
JCE中AES支持五中模式:CBC,CFB,ECB,OFB,PCBC;支持三种填充:NoPadding,PKCS5Padding,ISO10126Padding。
不支持SSL3Padding。不支持“NONE”模式。
好原来有模式和填充一说。
在OPENSSL中直接有一个CBC加解密函数。填充没找到,试过后发现C++加密出的内容比JAVA的要长出一截,前面的内容是完全一样的。
这应该就出现在填充上。
本来以为找到问题关键就应该很容易解决的。结果发现OPENSSL的填充是固定实现的,而我所需要解密的java端代码不能改动。
一条路走不通咱就换条路。最后发现有一个开源项目Botan什么都有而且同JCE十分相似并且满足我要求垮平台,好就是它了。
附:
算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度
AES/CBC/NoPadding 16 不支持
AES/CBC/PKCS5Padding 32 16
AES/CBC/ISO10126Padding 32 16
AES/CFB/NoPadding 16 原始数据长度
AES/CFB/PKCS5Padding 32 16
AES/CFB/ISO10126Padding 32 16
AES/ECB/NoPadding 16 不支持
AES/ECB/PKCS5Padding 32 16
AES/ECB/ISO10126Padding 32 16
AES/OFB/NoPadding 16 原始数据长度
AES/OFB/PKCS5Padding 32 16
AES/OFB/ISO10126Padding 32 16
AES/PCBC/NoPadding 16 不支持
AES/PCBC/PKCS5Padding 32 16
AES/PCBC/ISO10126Padding 32 16
可以看到,在原始数据长度为16的整数倍时,
假如原始数据长度等于16*n,
则使用NoPadding时加密后数据长度等于16*n
,其它情况下加密数据长度等于16*(n+1)。
在不足16的整数倍的情况下,假如原始数据长度等于16*n+m[其中m小于16]
,除了NoPadding填充之外的任何方式,加密数据长度都等于16*(n+1)
;NoPadding填充情况下,CBC、ECB和PCBC三种模式是不支持的,CFB、OFB两种模式下则加密数据长度等于原始数据长度。
*/
package
com.example.ex_crypto;
import
java.io.UnsupportedEncodingException;
import
javax.crypto.Cipher;
import
javax.crypto.spec.SecretKeySpec;
/**
* AES加密解密类
*
* @author xuxiong
*/
public
class
AESHelper {
/** 算法/模式/填充 **/
private
static
final
String CipherMode =
"AES/ECB/NoPadding"
;
/**
* 创建密钥
*
* @param password
* 例如:"0123456701234567" 128位 16*8 所有密钥长度不能超过16字符中文占两个。192 24;
* 256 32
* @return SecretKeySpec 实例
*/
private
static
SecretKeySpec createKey(String password) {
byte
[] data =
null
;
if
(password ==
null
) {
password =
""
;
}
StringBuffer sb =
new
StringBuffer(
16
);
sb.append(password);
while
(sb.length() <
16
) {
sb.append(
"0"
);
}
if
(sb.length() >
16
) {
sb.setLength(
16
);
}
try
{
data = sb.toString().getBytes(
"UTF-8"
);
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
return
new
SecretKeySpec(data,
"AES"
);
}
/**
* 加密字节数据
*
* @param content
* 需要加密的字节数组
* @param password
* 密钥 128 <16个字节 192 <24,256 <32个字节
* @return 加密完后的字节数组
*/
public
static
byte
[] encrypt(
byte
[] content, String password) {
try
{
SecretKeySpec key = createKey(password);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte
[] result = cipher.doFinal(content);
return
result;
}
catch
(Exception e) {
e.printStackTrace();
}
return
null
;
}
/**
* 加密(结果为16进制字符串)
*
* @param content
* 要加密的字符串
* @param password
* 密钥
* @return 加密后的16进制字符串
*/
public
static
String encrypt(String content, String password) {
byte
[] data =
null
;
try
{
data = content.getBytes(
"UTF-8"
);
}
catch
(Exception e) {
e.printStackTrace();
}
data = encrypt(data, password);
String result = byte2hex(data);
return
result;
}
/** 解密字节数组 **/
public
static
byte
[] decrypt(
byte
[] content, String password) {
try
{
SecretKeySpec key = createKey(password);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.DECRYPT_MODE, key);
byte
[] result = cipher.doFinal(content);
return
result;
}
catch
(Exception e) {
e.printStackTrace();
}
return
null
;
}
/** 解密16进制的字符串为字符串 **/
public
static
String decrypt(String content, String password) {
byte
[] data =
null
;
try
{
data = hex2byte(content);
}
catch
(Exception e) {
e.printStackTrace();
}
data = decrypt(data, password);
if
(data ==
null
)
return
null
;
String result =
null
;
try
{
result =
new
String(data,
"UTF-8"
);
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
return
result;
}
/**
* 字节数组转成16进制字符串
*
* @param b
* @return 16进制字符串
*/
public
static
String byte2hex(
byte
[] b) {
// 一个字节的数,
StringBuffer sb =
new
StringBuffer(b.length *
2
);
String tmp =
""
;
for
(
int
n =
0
; n < b.length; n++) {
// 整数转成十六进制表示
tmp = (java.lang.Integer.toHexString(b[n] &
0XFF
));
if
(tmp.length() ==
1
) {
sb.append(
"0"
);
}
sb.append(tmp);
}
return
sb.toString().toUpperCase();
// 转成大写
}
/**
* 将hex字符串转换成字节数组 *
*
* @param 16进制的字符串
* @return 字节数组
*/
private
static
byte
[] hex2byte(String inputString) {
if
(inputString ==
null
|| inputString.length() <
2
) {
return
new
byte
[
0
];
}
inputString = inputString.toLowerCase();
int
l = inputString.length() /
2
;
byte
[] result =
new
byte
[l];
for
(
int
i =
0
; i < l; ++i) {
String tmp = inputString.substring(
2
* i,
2
* i +
2
);
result[i] = (
byte
) (Integer.parseInt(tmp,
16
) &
0xFF
);
}
return
result;
}
}
1
2
3
4
//需要加密的字符 密钥
String encrypt = AESHelper.encrypt(
"0123456701234567"
,
"0123456701234567"
);
// 加密完后的字符 密钥
String decrypt = AESHelper.decrypt(encrypt,
"0123456701234567"
);
0 0
- Android AES加密
- Android AES加密实现
- AES Android 加密
- 7、Android AES加密
- Android之AES加密
- android AES加密
- Android AES 加密,解密
- ios android aes 加密
- android AES加密 --java
- android AES加密
- Android中的AES加密
- Android AES加密解密
- Android AES加密解密
- android AES加密代码
- android AES加密
- Android AES加密解密
- Android AES 加密
- Android AES加密 解密
- 定义结构体与分配内存
- 老程序员的python快速学习之旅
- 【文智背后的奥秘】系列篇——关键词智能提取
- hibernate 返回非受管实体
- Iterator去除一个List中与另一个List相同的元素,或者Iterator按条件去除元素
- android AES加密
- java多线程编程基础讲解
- 运行时和编译时异常
- PAT(Basic Level):数素数
- Android studio 更新问题
- Android Studio中Java控制台中文输出乱码
- 深度学习的几种库
- Elasticsearch索引重建(Rebuild)
- 位域相关