AES(Advanced Encryption Standard)高级加密标准
,安全性要高于DES,其实AES的出现本身就是为了取代DES的,AES具有比DES更好的安全性、效率、灵活性,
所以对称加密优先采用AES
。在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES。
项目中除了登陆,支付等接口采用RAS非对称加密,之外的可以采用AES对称加密
对称加密过程
对称密码的加密方案有5个组成部分(如图所示)
1)明文:原始信息。
2)加密算法:以密钥为参数,对明文进行多种置换和转换的规则和步骤,变换结果为密文。
3)密钥:加密与解密算法的参数,直接影响对明文进行变换的结果。
4)密文:对明文进行变换的结果。
5)解密算法:加密算法的逆变换,以密文为输入、密钥为参数,变换结果为明文。
对称密码中的数学运算
对称密码当中有几种常用到的数学运算。这些运算的共同目的就是把被加密的明文数码尽可能深地打乱,从而加大破译的难度。
- 移位和循环移位
移位就是将一段数码按照规定的位数整体性地左移或右移。循环右移就是当右移时,把数码的最后的位移到数码的最前头,循环左移正相反。例如,对十进制数码12345678循环右移1位(十进制位)的结果为81234567,而循环左移1位的结果则为23456781。 - 置换
就是将数码中的某一位的值根据置换表的规定,用另一位代替。它不像移位操作那样整齐有序,看上去杂乱无章。这正是加密所需,被经常应用。 - 扩展
就是将一段数码扩展成比原来位数更长的数码。扩展方法有多种,例如,可以用置换的方法,以扩展置换表来规定扩展后的数码每一位的替代值。 - 压缩
就是将一段数码压缩成比原来位数更短的数码。压缩方法有多种,例如,也可以用置换的方法,以表来规定压缩后的数码每一位的替代值。 - 异或
这是一种二进制布尔代数运算。异或的数学符号为⊕ ,它的运算法则如下:
1⊕1 = 0
0⊕0 = 0
1⊕0 = 1
0⊕1 = 1
也可以简单地理解为,参与异或运算的两数位如相等,则结果为0,不等则为1。 - 迭代
迭代就是多次重复相同的运算,这在密码算法中经常使用,以使得形成的密文更加难以破解。
AES代码实现
1)常量简介
private final static String HEX = "0123456789ABCDEF";
private static final String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";
private static final String AES = "AES";
private static final String SHA1PRNG = "SHA1PRNG";
2)动态生成秘钥
* 动态生成密钥
* @return 生成随机数,可以当做动态的密钥 加密和解密的密钥必须一致,不然将不能解密
public static String generateKey() {
try {
SecureRandom secureRandom = SecureRandom.getInstance(SHA1PRNG, "Crypto");
byte[] bytesKey = new byte[20];
secureRandom.nextBytes(bytesKey);
String strKey = ByteToHex(bytesKey);
return strKey;
} catch (Exception e) {
e.printStackTrace();
return null;
3)处理秘钥Key(转换密钥)
* 对密钥进行处理
private static byte[] getRawKey(String key) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance(AES);
SecureRandom sr = SecureRandom.getInstance(SHA1PRNG, "Crypto");
sr.setSeed(key.getBytes());
kgen.init(128, sr);
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
4)加密实现
* AES加密
public static String encrypt(String key, String data) {
if (TextUtils.isEmpty(data)) {
return data;
try {
byte[] result = encrypt(key, data.getBytes());
return Base64.encodeToString(result, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
return null;
* AES加密
private static byte[] encrypt(String key, byte[] bytes) throws Exception {
byte[] raw = getRawKey(key);
SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
byte[] encrypted = cipher.doFinal(bytes);
return encrypted;
5)解密实现
* AES 解密
public static String decrypt(String key, String data) {
if (TextUtils.isEmpty(data)) {
return data;
try {
byte[] bytes = Base64.decode(data, Base64.DEFAULT);
byte[] result = decrypt(key, bytes);
return new String(result);
} catch (Exception e) {
e.printStackTrace();
return null;
* AES 解密
private static byte[] decrypt(String key, byte[] data) throws Exception {
byte[] raw = getRawKey(key);
SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
byte[] decrypted = cipher.doFinal(data);
return decrypted;
6)进制转换
* 二进制转(16进制)字符串
private static String ByteToHex(byte[] bytesKey) {
if (bytesKey == null)
return "";
StringBuilder sb = new StringBuilder();
for (byte b : bytesKey) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
return sb.toString();
* (16进制)字符转二进制
private static byte[] HexToByte(String hexString) {
int len = hexString.length() / 2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
return result;
private String data = "这是一个测试编码和加解密的字符串数据";
private String AES_Key = "aeskey";
private boolean isAesEncrypt = true;
* AES 加解密
private void aesEncrypt() {
tvContent.setText("");
if (isAesEncrypt) {
encryptAES = AESUtils.encrypt(AES_Key, data);
Log.d("TAG:" + TAG, "----AES加密后: " + encryptAES);
tvContent.setText("AES加密后: " + encryptAES);
} else {
String decryptAES = AESUtils.decrypt(AES_Key, encryptAES);
Log.d("TAG:" + TAG, "----AES解密后: " + decryptAES);
tvContent.setText("AES解密后: " + decryptAES);
isAesEncrypt = !isAesEncrypt;
完整代码参考github:Android-Encrypt-master
背景AES(Advanced Encryption Standard)高级加密标准,安全性要高于DES,其实AES的出现本身就是为了取代DES的,AES具有比DES更好的安全性、效率、灵活性,所以对称加密优先采用AES。
1.AES加密简介
AES是一种对称加密算法,即加密解密使用同一把秘钥。非对称加密则是加密解密使用不同的秘钥(如RSA加密,下一篇文章会介绍)。
AES通常是这样使用的:
客户端每次随机生成一个秘钥,对待传输的数据加密,然后再用其他加密手段(如RSA),对秘钥本身进行加密,最后将加密后的数据和AES秘钥一同发送给服务端。
在Java 后端发来的AES加密数据时,发现Android APP不能解密 而且Android 端 加密同样的数据返回的结果居然不一致,所以我在网上查询后,发现在SecureRandom在产生安全随机数时 Windows系统和Linux系统的机制不一样,所以在同样的java AES加密源码加密同意的数据产生不一样的加密结果。
下面我给出网络的常用的AES加密的源码。
网络常用的AES加解密源码:
* AES加密字符串
* @param conte
Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
package com.example.logindemo;import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;public class User {
private String mId;
private String mPwd;
private static
```java
public static String encrypt(String key, String iv, String data) throws Exception {
byte[] keyBytes = key.getBytes("UTF-8");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes("UTF-8"));
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(data.getBytes());
return Base64.encodeToString(encrypted, Base64.DEFAULT);
```java
public static String decrypt(String key, String iv, String encryptedData) throws Exception {
byte[] keyBytes = key.getBytes("UTF-8");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes("UTF-8"));
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decrypted = cipher.doFinal(Base64.decode(encryptedData, Base64.DEFAULT));
return new String(decrypted);
其中,key为密钥,iv为初始化向量,data为待加密的数据。加密后返回Base64编码的字符串。解密时需要传入相同的key和iv,以及加密后的Base64编码字符串。注意,加密和解密时使用的加密算法和填充方式必须相同。
Error:The SDK Build Tools revision (23.0.3) is too low for project ':app'. Minimum required is 25.0.
11538