轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/120285594
本文出自【趙彥軍的博客】
文章目錄
- AES 簡介
- 對稱加密
- 加密模式
- PKCS5Padding到底是什么?
- 偏移量
- 字符集
- 實際作業中的加密流程
- AES 加密/解密 注意的問題
- 實戰,AES加解密
AES 簡介
- DES 全稱為Data Encryption Standard,即資料加密標準,是一種使用密鑰加密的塊演算法,1977年被美國聯邦政府的國家標準局確定為聯邦資料處理標準(FIPS)
- AES 密碼學中的高級加密標準(Advanced Encryption Standard,AES),又稱Rijndael加密法,是美國聯邦政府采用的一種區塊加密標準,這個標準用來替代原先的DES(Data Encryption Standard),已經被多方分析且廣為全世界所使用,
為什么 DES 被廢棄?
我們知道資料加密標準(Data Encryption Standard: DES)的密鑰長度是56位元,因此演算法的理論安全強度是2的56次方,但二十世紀中后期正是計算機飛速發展的階段,元器件制造工藝的進步使得計算機的處理能力越來越強,DES將不能提供足夠的安全性,
簡單來說,DES標準的秘鑰長度要求太短,安全性不夠,
為什么AES演算法被稱為 Rijndael 演算法?
1997年1月2號,美國國家標準技術研究所(National Institute of Standards and Technology: NIST)宣布希望征集高級加密標準(Advanced Encryption Standard: AES)[3],用以取代DES,AES得到了全世界很多密碼作業者的回應,先后有很多人提交了自己設計的演算法,最終有5個候選演算法進入最后一輪:Rijndael,Serpent,Twofish,RC6和MARS,下圖分別為其中的5位作者,最終經過安全性分析、軟硬體性能評估等嚴格的步驟,Rijndael演算法獲勝,
為什么AES演算法安全性高?
AES的區塊長度固定為128位,密鑰長度則可以是128 bit,192 bit 或256位 bit ,換算成位元組長度,就是密碼必須是 16個位元組,24個位元組,32個位元組,AES密碼的長度更長了,破解難度就增大了,所以就更安全,
對稱加密
- 對稱加密 : 也就是加密秘鑰和解密秘鑰是一樣的,
- 非對稱加密 : 也就是加密秘鑰和解密秘鑰是不一樣的,
AES 是對稱加密演算法,優點:加密速度快;缺點:如果秘鑰丟失,就容易解密密文,安全性相對比較差
RSA 是非對稱加密演算法 , 優點:安全 ;缺點:加密速度慢
AES加密需要:明文 + 密鑰+ 偏移量(IV)+密碼模式(演算法/模式/填充)
AES解密需要:密文 + 密鑰+ 偏移量(IV)+密碼模式(演算法/模式/填充)
AES的演算法模式一般為 AES/CBC/PKCS5Padding
加密模式
AES的加密模式有以下幾種
- 電碼本模式(ECB)
- 密碼分組鏈接模式(CBC)
- 計算器模式(CTR)
- 密碼反饋模式(CFB)
- 輸出反饋模式(OFB)
密碼分組鏈接模式(CBC):將整段明文切成若干小段,然后每一小段與初始塊或者上一段的密文段進行異或運算后,再與密鑰進行加密,

根據圖示,在 CBC 模式下,使用 AES 加解密方式進行分組加解密時,需要用到的兩個引數
-
1、初始化向量,也就是偏移量
-
2、加解密秘鑰
PKCS5Padding到底是什么?
為什么 JAVA 里指定演算法時,寫的是 AES/CBC/PKCS5Padding,每個都是什么含義,又有什么作用,
-
AES,加解密演算法
-
CBC,資料分組模式
-
PKCS5Padding,資料按照一定的大小進行分組,最后分剩下那一組,不夠長度,就需要進行補齊, 也可以叫
補齊模式
簡單的說:拿到一個原始資料以后,首先需要對資料進行分組,分組以后如果長度不滿足分組條件,需要進行補齊,最后形成多個分組,在使用加解密演算法,對這多個分組進行加解密,所以這個程序中,AES,CBC,PKCS5Padding 缺一不可,
在對資料進行加解密時,通常將資料按照固定的大小(block size)分成多個組,那么隨之就產生了一個問題,如果分到最后一組,不夠一個 block size 了,要怎么辦?此時就需要進行補齊操作,
補齊規則:The value of each added byte is the number of bytes that are added, i.e. N bytes, each of value N are added.
舉例:
36 位的 UUID,如果按照 block size=16 位元組(即 128 位元),那么就需要補齊到 48 位,差 12 個位元組,那么最后填充的 12 個位元組的內容,都是位元組表示的 0x0c(即 12),
偏移量
偏移量 的添加一般是為了增加 AES 加密的復雜度,增加資料的安全性,一般在 AES_256 中會使用到 偏移量 ,而在 AES_128 加密中不會使用到,
字符集
在 AES 加密中,特別也要注意到字符集的問題,一般用到的字符集是 utf-8 和 gbk ,
實際作業中的加密流程
在實際的作業中,客戶端跟服務器互動一般都是字串格式,所以一個比較好的加密流程是:
- 加密流程 :明文通過
密鑰(有時也需要偏移量),利用AES加密演算法,然后通過Base64轉碼,最后生成加密后的字串, - 解密流程 :加密后的字串通過
密鑰(有時也需要偏移量),利用AES解密演算法,然后通過Base64轉碼,最后生成解密后的字串,
AES 加密/解密 注意的問題
AES 加密/解密的時候,通常是用在服務端和客戶端通訊的程序中,一端加密傳輸,另一端解密使用,雖然 AES 加密看似簡單,但在使用程序程序中,仍然會出現在一端加密ok,但是另一端解密失敗的情況,一旦出現 AES 解密失敗,我們可以通過以下幾個方面進行排查:
1. AES 加密/解密 使用相同的密鑰
2. 若涉及到偏移量,則AES 加密/解密 使用的偏移量要一樣
3. AES 加密/解密 要使用相同加密數位,如都使用`AES_256`
4. AES 加密/解密 使用相同的字符集
5. AES 加密/解密 使用相同的加密,填充模式,如都使用`AES/CBC/PKCS5Padding`模式
6. 由于不同開發語言(如C 和 Java)及不同開發環境(如 Java 和 Android)的影響,可能相同的加解密演算法在實作上出現差異,若你們注意到這個差異,就可能導致加解密出現問題
最后,當我們需要驗證自己的 AES 解密演算法是否與別人的加密方法為一套的時候,可以讓加密方發你一份加密后的密文和加密前的明文,然后你用密文解密,看解密結果和加密方發你的是否一致,需要注意的是,加密方給你的明文要盡量簡潔,如就 中國 二字,這樣既能看出加密方和解密方的字符集是否一致,而且能避免復制粘貼等環節出現空格,回車等轉義字符對驗證結果的干擾,
實戰,AES加解密
首先定義加密、解密工具類
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.GeneralSecurityException;
/**
* AES加解密工具類
*/
public class AES {
/**
* AES加密
*
* @param key
* @param iv
* @throws GeneralSecurityException
* @throws IOException
*/
public static byte[] encryptAes(byte[] data, byte[] key, byte[] iv)
throws GeneralSecurityException, IOException {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
return cipher.doFinal(data);
}
/**
* AES解密
*
* @param key
* @param iv
* @return
* @throws GeneralSecurityException
* @throws IOException
*/
public static byte[] decryptAesToByteString(byte[] data, byte[] key, byte[] iv)
throws GeneralSecurityException, IOException {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
return cipher.doFinal(data);
}
}
加密和解密的代碼很像,唯一的不同點是,加密 Cipher.ENCRYPT_MOD , 解密用的是 Cipher.DECRYPT_MODE
下面我們寫一個測驗代碼:
try {
//加密密碼
String key = "zhaoyanjunzhaoy1";
//偏移量
String iv = "1234567890123456";
String message = "今天是周二,我好開心";
//加密
byte[] encryResult = AES.encryptAes(message.getBytes(), key.getBytes(), iv.getBytes());
//解密
byte[] decryResult = AES.decryptAesToByteString(encryResult, key.getBytes(), iv.getBytes());
System.out.println("解密資料 = " + new String(decryResult));
} catch (IOException | GeneralSecurityException e) {
e.printStackTrace();
}
輸出結果:
解密資料 = 今天是周二,我好開心
可以看到資料已經正常解密了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/300296.html
標籤:區塊鏈
