文章目錄
- RSA(非對稱)和AES(對稱)加密算法
- 一、RSA(Rivest-Shamir-Adleman)
- 二、AES(Advanced Encryption Standard)
- RSA加密三種填充模式
- 一、RSA填充模式
- 二、常見的RSA填充模式組合
- 三、選擇合適的填充模式
- 四、總結
- AES的基本原理、工作模式、填充機制以及密鑰和初始化向量(IV)的使用
- 一、AES簡介
- 二、AES加密解密過程
- 三、AES常見的工作模式
- 四、AES填充模式
- 五、AES密鑰和初始化向量管理
- RSA 生成 Code
- 一、Java中的RSA加密實現
- 二、選擇合適的密鑰長度
- 三、密鑰的管理和存儲
- Code: 將密鑰轉換為PEM格式
- 四、總結

RSA(非對稱)和AES(對稱)加密算法
在現代信息安全中,加密算法扮演著至關重要的角色。今天我們來聊聊兩種常見的加密算法——RSA和AES,用通俗易懂的語言帶大家理解它們的核心原理和優缺點。
一、RSA(Rivest-Shamir-Adleman)
核心原理:
RSA是一種非對稱加密算法,這意味著它使用一對密鑰:公鑰和私鑰。通俗來說,公鑰可以公開,用來加密信息;而私鑰需要保密,用來解密信息。它的安全性主要依賴于一個數學難題:大整數的質因數分解。具體步驟如下:
- 選擇質數:選擇兩個大質數p和q。
- 計算乘積:計算p和q的乘積n = p * q,這就是公鑰的一部分。
- 計算歐拉函數:計算歐拉函數φ(n) = (p-1)*(q-1)。
- 選擇公鑰指數:選擇一個小于φ(n)的整數e,且e與φ(n)互質,這就是公鑰的另一部分。
- 計算私鑰指數:計算e對于φ(n)的模反元素d,這就是私鑰。
優點:
- 安全性高:由于大整數的質因數分解非常困難,破解RSA幾乎不可能。
- 公鑰加密:公鑰可以公開分享,方便信息的安全傳輸。
缺點:
- 速度慢:加密和解密過程計算復雜,速度較慢。
- 密鑰長度大:需要較長的密鑰(通常為2048位或以上)來保證安全性,存儲和處理成本高。
二、AES(Advanced Encryption Standard)
核心原理:
AES是一種對稱加密算法,這意味著它使用同一個密鑰進行加密和解密。它基于一種叫做“分組密碼”的方法,把數據分成固定大小的塊(通常是128位),然后通過多個輪次的處理來加密數據。每輪處理包括以下步驟:
- 替代(Substitution):使用預先定義的S盒對數據進行替換。
- 換位(Permutation):重新排列數據的順序。
- 混淆(Mixing):對數據進行復雜的數學運算混合。
- 輪密鑰加(Add Round Key):與輪密鑰進行異或運算。
優點:
- 速度快:由于AES算法的設計簡單且高效,處理速度快,適合大數據量的加密。
- 安全性高:AES算法在多年的使用中,未被成功破解,具有很高的安全性。
缺點:
- 密鑰管理復雜:對稱加密要求通信雙方事先共享同一個密鑰,密鑰的分發和管理較為復雜。
- 密鑰泄露風險:一旦密鑰泄露,所有加密的數據都會暴露,因此密鑰保護非常重要。
RSA和AES是現代密碼學中兩種重要的加密算法,各有優缺點。RSA依賴于復雜的數學難題,安全性高但速度較慢;AES則以其高效的加密速度和廣泛應用而著稱,但在密鑰管理上存在挑戰。
RSA加密三種填充模式
RSA加密算法在實際應用中常常使用填充模式來確保數據的安全性和算法的有效性。
填充模式是為了使加密數據和公鑰長度一致,并增加加密的安全性。
接下來我們看下主要的RSA填充模式:ENCRYPTION_OAEP
、ENCRYPTION_PKCS1
和ENCRYPTION_NONE
,以及常見的填充模式組合。
一、RSA填充模式
1. ENCRYPTION_OAEP(Optimal Asymmetric Encryption Padding)
- 簡介:OAEP是目前最安全的RSA填充模式,廣泛推薦用于現代加密應用中。
- 原理:OAEP在加密數據前,先通過一個哈希函數和一個掩碼生成函數(MGF)對數據進行填充,確保每次加密的結果都不同,即使相同的數據和密鑰也不會產生相同的密文。
- 優點:高安全性,防止多種已知攻擊(如選擇密文攻擊)。
- 使用場景:需要高度安全性的數據加密和解密操作。
2. ENCRYPTION_PKCS1(PKCS #1 v1.5 Padding)
- 簡介:PKCS1是RSA加密最常用的填充模式之一,因其隨機填充的特性,確保相同數據每次加密結果不同。
- 原理:PKCS1填充在數據前面添加一個隨機填充字符串,并確保數據長度和密鑰長度一致。
- 優點:較為簡單,已經廣泛使用和支持。
- 缺點:相對于OAEP,安全性略低,可能受到一定類型的攻擊(如選擇密文攻擊)。
- 使用場景:一般數據加密,廣泛應用于SSL/TLS協議中。
3. ENCRYPTION_NONE(No Padding)
- 簡介:無填充模式,直接對數據進行加密。
- 原理:數據長度必須與密鑰長度相同,不進行任何額外的填充處理。
- 優點:實現簡單。
- 缺點:安全性較低,易受各種攻擊,不推薦使用。
- 使用場景:通常僅在特定條件下或內部使用。
二、常見的RSA填充模式組合
1. RSA/None/PKCS1Padding
- 簡介:該模式表示沒有指定具體的塊加密模式(None),使用PKCS1填充。
- 特點:確保相同數據每次加密結果不同,適用于許多常見的加密場景。
2. RSA/ECB/PKCS1Padding
- 簡介:該模式表示使用電子密碼本(ECB)模式進行加密,并使用PKCS1填充。
- 特點:在每個塊中獨立加密,但ECB模式本身不推薦用于大數據量的加密,因為相同的明文塊會被加密成相同的密文塊,這可能導致模式泄露問題。
- 適用場景:一般數據加密,廣泛應用于加密協議中。
三、選擇合適的填充模式
選擇合適的填充模式需要根據具體應用場景來考慮:
- 高安全性需求:推薦使用ENCRYPTION_OAEP填充模式,尤其是在敏感數據的加密和解密中。
- 廣泛兼容性:ENCRYPTION_PKCS1是一個較好的選擇,已經被廣泛支持和使用,適用于大多數應用場景。
- 實驗性或內部使用:ENCRYPTION_NONE模式僅在特定情況下使用,需確保其他安全措施到位。
四、總結
RSA加密算法的填充模式是確保數據安全性和算法有效性的關鍵。ENCRYPTION_OAEP、ENCRYPTION_PKCS1和ENCRYPTION_NONE
各有優缺點和適用場景。在實際應用中,根據具體需求選擇合適的填充模式,能夠有效提升加密的安全性和性能。
AES的基本原理、工作模式、填充機制以及密鑰和初始化向量(IV)的使用
AES(Advanced Encryption Standard)是一種廣泛使用的對稱加密算法,旨在替代原先的DES和3DES。AES憑借其高效的加密速度和強大的安全性,成為現代數據加密的首選。
接下來我們來看下AES的基本原理、工作模式、填充機制以及密鑰和初始化向量(IV)的使用。
一、AES簡介
主要特點:
- 對稱加密:同一個密鑰用于加密和解密。
- 塊加密:以固定大小的塊(128位)對數據進行加密。
- 高效性:比公鑰加密算法快很多,適用于需要高性能的數據加密場景。
主要缺點:
- 密鑰管理:需要加密端和解密端都使用相同的密鑰,密鑰分發和管理較為復雜。
二、AES加密解密過程
AES加密需要:
- 明文:需要加密的數據。
- 密鑰(Key):用于加密和解密的密鑰,長度可以是128位、192位或256位。
- 偏移量(IV):初始化向量,用于將加密隨機化,提高安全性。
- 密碼模式:算法/模式/填充,如AES/CBC/PKCS5Padding。
AES解密需要:
- 密文:已加密的數據。
- 密鑰(Key):與加密時使用的密鑰相同。
- 偏移量(IV):與加密時使用的初始化向量相同。
- 密碼模式:算法/模式/填充,如AES/CBC/PKCS5Padding。
三、AES常見的工作模式
1. 電碼本模式(ECB)
- 特點:每個數據塊獨立加密,相同的明文塊會被加密成相同的密文塊。
- 優點:實現簡單,不需要初始化向量。
- 缺點:不安全,容易受到模式泄露攻擊。
- 使用場景:不推薦在安全需求高的場景下使用。
2. 密碼分組鏈接模式(CBC)
- 特點:每個明文塊與前一個密文塊進行異或運算后再加密,第一個塊需要初始化向量(IV)。
- 優點:安全性高,每個塊的加密結果都不同。
- 使用場景:廣泛用于文件加密和數據傳輸加密。
3. 計算器模式(CTR)
- 特點:將一個計數器的輸出與明文塊進行異或運算,實現加密。
- 優點:可并行處理,提高加密速度。
- 使用場景:適用于流式數據加密和高性能需求的場景。
4. 密碼反饋模式(CFB)
- 特點:前一個密文塊作為下一塊的輸入,結合初始化向量(IV)提高安全性。
- 優點:適用于需要逐字節或逐位加密的場景。
- 使用場景:實時數據加密,如網絡數據流。
5. 輸出反饋模式(OFB)
- 特點:將初始化向量與密鑰結合,通過反饋機制生成加密序列。
- 優點:加密過程獨立于明文塊的內容。
- 使用場景:適用于逐位加密和需要抗噪聲的場景。
四、AES填充模式
填充模式的必要性:
由于AES是一種塊加密算法,處理的數據塊必須是固定長度(128位),因此需要填充模式來確保數據長度符合要求。
常見填充模式:
- PKCS7:在數據末尾添加一系列字節,每個字節的值表示填充的字節數,廣泛使用,兼容性好。
- None:不進行填充,要求輸入數據的長度必須是塊長度的整數倍。
五、AES密鑰和初始化向量管理
密鑰(Key):
- AES標準規定的密鑰長度為128位、192位和256位,分別對應16字節、24字節和32字節。
- 密鑰不能公開傳輸,需要安全地管理和保護。
初始化向量(IV):
- IV用于將加密隨機化,確保相同的明文被多次加密產生不同的密文。
- IV可以公開,但不能重復使用。推薦每次加密時生成一個新的16字節隨機值。
- 在加密端將IV和密文一起發送給解密端,確保解密端能夠正確還原數據。
RSA 生成 Code
RSA加密算法在Java中有多種實現方式,其中默認的實現方式是RSA/None/PKCS1Padding
。在實際應用中,為了確保安全性和兼容性,需要注意密鑰長度、密鑰格式以及密鑰管理。
一、Java中的RSA加密實現
默認實現:RSA/None/PKCS1Padding
- RSA:表示使用RSA算法進行加密。
- None:沒有指定具體的塊加密模式。
- PKCS1Padding:使用PKCS#1 v1.5填充模式,這是常見的RSA填充方式。
為什么選擇PKCS1Padding?
PKCS1Padding是一種較為常用且廣泛支持的填充方式,它通過添加隨機填充數據,確保相同的數據每次加密結果不同,從而提高安全性。
二、選擇合適的密鑰長度
推薦使用2048位或更長的密鑰
- 1024位密鑰:在現代計算能力下已經不再安全,容易受到攻擊。
- 2048位或更長的密鑰:提供更高的安全性,推薦使用2048位或4096位的密鑰,以應對未來更強的攻擊手段。
創建RSA密鑰對
package com.artisan.jasypt.rsa;import java.io.UnsupportedEncodingException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class RsaTest {/*** 主程序入口,用于演示如何生成和打印RSA密鑰對的公鑰和私鑰。** @param args 命令行參數(未使用)* @throws UnsupportedEncodingException 如果編碼不被支持*/public static void main(String[] args) throws UnsupportedEncodingException {// 生成2048位的RSA密鑰對KeyPair keyPair = getKeyPair(2048);// 獲取公鑰byte[] publicKey = getPublicKey(keyPair);// 獲取私鑰byte[] privateKey = getPrivateKey(keyPair);// 打印編碼后的公鑰和私鑰System.out.println("Private Key: " + Base64.getEncoder().encodeToString(publicKey));System.out.println("Public Key: " + Base64.getEncoder().encodeToString(privateKey));}/*** 生成RSA算法的密鑰對* @param keyLength 密鑰長度,用于初始化密鑰生成器* @return 生成的密鑰對,包含公鑰和私鑰*/public static KeyPair getKeyPair(int keyLength) {try {// 實例化密鑰對生成器,并指定算法為RSAKeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");// 初始化密鑰對生成器,設置密鑰長度keyPairGenerator.initialize(keyLength);// 生成密鑰對return keyPairGenerator.generateKeyPair();} catch (NoSuchAlgorithmException e) {// 當指定的加密算法不可用時,拋出運行時異常throw new RuntimeException("生成密鑰對時遇到異常" + e.getMessage());}}/*** 獲取公鑰** @param keyPair 包含公鑰和私鑰的密鑰對* @return 公鑰的字節數組形式*/public static byte[] getPublicKey(KeyPair keyPair) {// 將密鑰對中的公鑰轉換為RSAPublicKey類型RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();// 獲取并返回公鑰的編碼形式return rsaPublicKey.getEncoded();}/*** 獲取私鑰** @param keyPair 包含公鑰和私鑰的密鑰對* @return 返回私鑰的字節數組形式*/public static byte[] getPrivateKey(KeyPair keyPair) {// 將keyPair中的私鑰轉換為RSAPrivateKey類型RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();// 返回私鑰的編碼形式return rsaPrivateKey.getEncoded();}}
package com.artisan.jasypt.rsa;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class RSAKeyPairGenerator {/*** 主函數用于生成RSA算法的密鑰對,并打印出其Base64編碼的字符串形式。** @param args 命令行參數(未使用)* @throws NoSuchAlgorithmException 如果指定的加密算法不可用,則拋出此異常。*/public static void main(String[] args) throws NoSuchAlgorithmException {// 創建RSA算法的密鑰對生成器KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");// 初始化密鑰對生成器,設置密鑰長度為2048位keyPairGen.initialize(2048);// 生成密鑰對KeyPair pair = keyPairGen.generateKeyPair();// 從密鑰對中提取私鑰和公鑰PrivateKey privateKey = pair.getPrivate();PublicKey publicKey = pair.getPublic();// 打印出私鑰和公鑰的Base64編碼System.out.println("Private Key: " + Base64.getEncoder().encodeToString(privateKey.getEncoded()));System.out.println("Public Key: " + Base64.getEncoder().encodeToString(publicKey.getEncoded()));}}
三、密鑰的管理和存儲
密鑰生成與存儲的流程
- 服務器創建密鑰對:服務器負責生成RSA密鑰對,確保私鑰的安全存儲。
- 公鑰下發至客戶端:將公鑰分發給需要加密數據的客戶端。
- 私鑰保存在服務器:私鑰必須保密,通常存儲在服務器上,確保其不被泄露。
密鑰格式:DER和PEM
- DER(Distinguished Encoding Rules):二進制格式,主要用于機器處理,不便于閱讀。
- PEM(Privacy-Enhanced Mail):將DER格式通過Base64編碼轉換為字符格式,更易于閱讀和傳輸。
PEM格式的密鑰示例
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr8p1oxcLljRG/Qffkh6N
...
-----END PUBLIC KEY----------BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCr8p1oxcLljRG/
...
-----END PRIVATE KEY-----
Code: 將密鑰轉換為PEM格式
package com.artisan.jasypt.rsa;import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class KeyToPEM {/*** 主函數:生成RSA密鑰對,并將其轉換為PEM格式輸出。** @param args 命令行參數(未使用)* @throws Exception 如果密鑰生成或轉換過程中發生錯誤*/public static void main(String[] args) throws Exception {// 生成RSA密鑰對,使用2048位長度KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);KeyPair keyPair = keyGen.generateKeyPair();// 提取公鑰和私鑰PublicKey publicKey = keyPair.getPublic();PrivateKey privateKey = keyPair.getPrivate();// 將公鑰和私鑰轉換為PEM格式String publicKeyPEM = convertToPEMFormat(publicKey.getEncoded(), "PUBLIC KEY");String privateKeyPEM = convertToPEMFormat(privateKey.getEncoded(), "PRIVATE KEY");// 輸出轉換后的PEM格式公鑰和私鑰System.out.println(publicKeyPEM);System.out.println(privateKeyPEM);}/*** 將密鑰字節數組轉換為PEM格式的字符串。* PEM(Privacy Enhanced Mail)格式是一種常見的密鑰存儲格式,以 base64 編碼的密鑰數據為主要內容,并以“-----BEGIN”和“-----END”為標記。** @param key 密鑰的字節數組。* @param keyType 密鑰的類型(如RSA PRIVATE KEY等)。* @return 轉換后的PEM格式密鑰字符串。*/public static String convertToPEMFormat(byte[] key, String keyType) {// 將密鑰字節數組轉換為Base64編碼的字符串String base64EncodedKey = Base64.getEncoder().encodeToString(key);StringBuilder pemKey = new StringBuilder();// 添加PEM格式的起始標記pemKey.append("-----BEGIN ").append(keyType).append("-----\n");// 將Base64編碼的密鑰拆分為64字符一組,并添加換行符for (int i = 0; i < base64EncodedKey.length(); i += 64) {pemKey.append(base64EncodedKey, i, Math.min(i + 64, base64EncodedKey.length())).append("\n");}// 添加PEM格式的結束標記pemKey.append("-----END ").append(keyType).append("-----");return pemKey.toString();}
}
四、總結
RSA加密在Java中的默認實現是RSA/None/PKCS1Padding
,推薦使用2048位或更長的密鑰以確保安全。密鑰管理是保證加密系統安全的重要環節,私鑰應保存在服務器上,公鑰分發給客戶端。PEM格式的密鑰更易于閱讀和傳輸,通常用于存儲和交換密鑰。