今天在android项目中使用AES对数据进行加解密,遇到了很多问题,网上也找了很多资料,也不行。不过最后还是让我给搞出来了,这里把这个记录下来,不要让别人走我的弯路,因为网上绝大多数的例子都是行不通的。好了,接下来开始讲解
1、Aes工具类
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
|
package
com.example.cheng.aesencrypt;
import
android.text.TextUtils;
import
java.security.NoSuchAlgorithmException;
import
java.security.SecureRandom;
import
javax.crypto.Cipher;
import
javax.crypto.KeyGenerator;
import
javax.crypto.SecretKey;
import
javax.crypto.spec.IvParameterSpec;
import
javax.crypto.spec.SecretKeySpec;
/**
* class description here
*
* @author cheng
* @version 1.0.0
* @since 2016-11-02
*/
public
class
Aes {
private
static
final
String SHA1PRNG =
"SHA1PRNG"
;
// SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法
private
static
final
String IV =
"qws871bz73msl9x8"
;
private
static
final
String AES =
"AES"
;
//AES 加密
private
static
final
String CIPHERMODE =
"AES/CBC/PKCS5Padding"
;
//algorithm/mode/padding
/**
* 加密
*/
public
static
String encrypt(String key, String cleartext) {
if
(TextUtils.isEmpty(cleartext)) {
return
cleartext;
}
try
{
byte
[] result = encrypt(key, cleartext.getBytes());
return
parseByte2HexStr(result);
}
catch
(Exception e) {
e.printStackTrace();
}
return
null
;
}
/**
* 加密
*/
public
static
byte
[] encrypt(String key,
byte
[] clear)
throws
Exception {
byte
[] raw = getRawKey(key.getBytes());
SecretKeySpec skeySpec =
new
SecretKeySpec(raw, AES);
Cipher cipher = Cipher.getInstance(CIPHERMODE);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec,
new
IvParameterSpec(
new
byte
[cipher.getBlockSize()]));
byte
[] encrypted = cipher.doFinal(clear);
return
encrypted;
}
/**
* 解密
*/
public
static
String decrypt(String key, String encrypted) {
if
(TextUtils.isEmpty(encrypted)) {
return
encrypted;
}
try
{
byte
[] enc = parseHexStr2Byte(encrypted);
byte
[] result = decrypt(key, enc);
return
new
String(result);
}
catch
(Exception e) {
e.printStackTrace();
}
return
null
;
}
/**
* 解密
*/
public
static
byte
[] decrypt(String key,
byte
[] encrypted)
throws
Exception {
byte
[] raw = getRawKey(key.getBytes());
SecretKeySpec skeySpec =
new
SecretKeySpec(raw, AES);
Cipher cipher = Cipher.getInstance(CIPHERMODE);
cipher.init(Cipher.DECRYPT_MODE, skeySpec,
new
IvParameterSpec(
new
byte
[cipher.getBlockSize()]));
byte
[] decrypted = cipher.doFinal(encrypted);
return
decrypted;
}
/**
* 生成随机数,可以当做动态的密钥
* 加密和解密的密钥必须一致,不然将不能解密
*/
public
static
String generateKey() {
try
{
SecureRandom secureRandom = SecureRandom.getInstance(SHA1PRNG);
byte
[] key =
new
byte
[
20
];
secureRandom.nextBytes(key);
return
toHex(key);
}
catch
(NoSuchAlgorithmException e) {
e.printStackTrace();
}
return
null
;
}
/**
* 对密钥进行处理
*/
public
static
byte
[] getRawKey(
byte
[] seed)
throws
Exception {
KeyGenerator kgen = KeyGenerator.getInstance(AES);
//for android
SecureRandom sr =
null
;
// 在4.2以上版本中,SecureRandom获取方式发生了改变
if
(android.os.Build.VERSION.SDK_INT >=
17
) {
sr = SecureRandom.getInstance(SHA1PRNG,
"Crypto"
);
}
else
{
sr = SecureRandom.getInstance(SHA1PRNG);
}
// for Java
// secureRandom = SecureRandom.getInstance(SHA1PRNG);
sr.setSeed(seed);
kgen.init(
128
, sr);
//256 bits or 128 bits,192bits
//AES中128位密钥版本有10个加密循环,192比特密钥版本有12个加密循环,256比特密钥版本则有14个加密循环。
SecretKey skey = kgen.generateKey();
byte
[] raw = skey.getEncoded();
return
raw;
}
/**
* 二进制转字符
*/
public
static
String toHex(
byte
[] buf) {
if
(buf ==
null
)
return
""
;
StringBuffer result =
new
StringBuffer(
2
* buf.length);
for
(
int
i =
0
; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return
result.toString();
}
private
static
void
appendHex(StringBuffer sb,
byte
b) {
sb.append(IV.charAt((b >>
4
) &
0x0f
)).append(IV.charAt(b &
0x0f
));
}
/**
* 将二进制转换成16进制
*
* @param buf
* @return
*/
public
static
String parseByte2HexStr(
byte
buf[]) {
StringBuilder sb =
new
StringBuilder();
for
(
int
i =
0
; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] &
0xFF
);
if
(hex.length() ==
1
) {
hex =
'0'
+ hex;
}
sb.append(hex.toUpperCase());
}
return
sb.toString();
}
/**
* 将16进制转换为二进制
*
* @param hexStr
* @return
*/
public
static
byte
[] parseHexStr2Byte(String hexStr) {
if
(hexStr.length() <
1
)
return
null
;
byte
[] result =
new
byte
[hexStr.length() /
2
];
for
(
int
i =
0
; i < hexStr.length() /
2
; i++) {
int
high = Integer.parseInt(hexStr.substring(i *
2
, i *
2
+
1
),
16
);
int
low = Integer.parseInt(hexStr.substring(i *
2
+
1
, i *
2
+
2
),
16
);
result[i] = (
byte
) (high *
16
+ low);
}
return
result;
}
}
|
2、mainActivity和layout文件如下:
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
|
package
com.example.cheng.aesencrypt;
import
android.os.Bundle;
import
android.support.v7.app.AppCompatActivity;
import
android.view.View;
import
android.widget.EditText;
import
android.widget.TextView;
import
android.widget.Toast;
public
class
MainActivity
extends
AppCompatActivity {
private
EditText mInputET;
private
TextView mShowEncryputTV;
private
TextView mShowInputTV;
private
static
final
String PASSWORD_STRING =
"12345678"
;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInputET = (EditText) findViewById(R.id.ase_input);
mShowEncryputTV = (TextView) findViewById(R.id.show_oringe_encrypt);
mShowInputTV = (TextView) findViewById(R.id.show_ase_encrypt);
}
/**
* 加密
*
* @param view
*/
public
void
encrypt(View view) {
String inputString = mInputET.getText().toString().trim();
if
(inputString.length() ==
0
) {
Toast.makeText(
this
,
"请输入要加密的内容"
, Toast.LENGTH_SHORT).show();
return
;
}
String encryStr = Aes.encrypt(PASSWORD_STRING, inputString);
mShowInputTV.setText(encryStr);
}
/**
* 解密
*
* @param view
*/
public
void
decrypt(View view) {
String encryptString = mShowInputTV.getText().toString().trim();
if
(encryptString.length() ==
0
) {
Toast.makeText(
this
,
"解密字符串不能为空"
, Toast.LENGTH_SHORT).show();
return
;
}
String decryStr = Aes.decrypt(PASSWORD_STRING, encryptString);
mShowEncryputTV.setText(decryStr);
}
}
|
layout文件
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
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
android:id
=
"@+id/activity_main"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:gravity
=
"center_vertical"
android:orientation
=
"vertical"
android:paddingBottom
=
"@dimen/activity_vertical_margin"
android:paddingLeft
=
"@dimen/activity_horizontal_margin"
android:paddingRight
=
"@dimen/activity_horizontal_margin"
android:paddingTop
=
"@dimen/activity_vertical_margin"
tools:context
=
"com.example.cheng.aesencrypt.MainActivity"
>
<
EditText
android:id
=
"@+id/ase_input"
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:hint
=
"输入要加密的内容"
/>
<
Button
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:onClick
=
"encrypt"
android:text
=
"点击进行ASE加密"
/>
<
TextView
android:id
=
"@+id/show_ase_encrypt"
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:layout_marginTop
=
"10dp"
android:text
=
"显示加密后的内容"
/>
<
Button
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:onClick
=
"decrypt"
android:text
=
"点击进行ASE解密"
/>
<
TextView
android:id
=
"@+id/show_oringe_encrypt"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_marginTop
=
"10dp"
android:text
=
"显示加密后的内容"
/>
</
LinearLayout
>
|
3、最后的效果如下:
1)、是一个输入框,输入钥加密的字符串;
2)、点击“AES加密”按钮后生产的加密字符串;
3)、点击“AES解密”按钮后,对加密字符串进行解密,然后在3处看到解密后的字符串,可以看到加密字符串和解密字符串相同,所以AES加解密成功了
4、总结
要用真机测试,模拟器是不行的,具体原因没去研究;
点击获取本例的github地址:
也可以通过android studio直接git下来,git地址为https://github.com/chenguo4930/AndroidAES.git
其中也还有DES、RSA的加解密demo的github地址为https://github.com/chenguo4930/EncodeDemo
git地址为: https://github.com/chenguo4930/EncodeDemo.git