工作中常用的五種加密算法
最近,項目中做了一些安全性要求的整改。而加密是使用過程中常用的手段之一。這里簡單的整理下,希望對小伙伴有幫助。
使用場景
加密是一種將原始信息(明文)轉換成難以被直接理解的形式(密文)的過程,
其主要目的是為了保護信息的安全和隱私。主要應用于以下場景:
- 數據保密:防止未經授權的個人身份信息和敏感數據。保護個人隱私、商業機密和國家機密。如:公司內部文件、云存儲信息防截獲。
- 數據完整性:確保數據在傳輸或存儲過程中未被篡改。如:軟件下載、銀行轉賬等。
- 身份驗證:驗證通信雙方的身份,確保數據是從一個可信的來源發送的,并且在整個傳輸過程中沒有被攔截或篡改。如:用戶登錄、電子郵件認證等。
- 數據訪問控制:加密可以限制對數據的訪問,只有擁有正確密鑰的用戶才能解密和訪問數據。如:企業VPN等。
- 網絡安全:在互聯網上傳輸數據時,加密可以防止中間人攻擊和其他網絡攻擊,確保數據在網絡中的傳輸安全。如:SSL/TLS協議等。
- 金融交易安全:在電子商務和在線銀行中,加密用于保護交易數據,防止信用卡欺詐和其他金融犯罪。如:在線支付(金融機構提供的RSA簽名和證書)等。
常用加密算法
1.MD5 加密
(1) 適用場景
MD5 作為一種廣泛使用的哈希函數,主要用于以下場景:
- 數據完整性校驗:驗證文件傳輸過程中是否被篡改。
- 數字簽名:確保信息傳輸的完整性和來源的真實性。
- 密碼存儲:在數據庫中存儲用戶密碼的哈希值,而非明文。
(2) 功能特性
- 長度固定:無論輸入長度如何,輸出都是128位(16字節)的哈希值。
- 快速計算:MD5 算法計算速度快,適用于大量數據的哈希處理。
- 不可逆性:MD5 加密是不可逆的,因此通常只有加密過程,而沒有解密過程
(3) 原理及流程圖
MD5 算法將輸入的消息經過填充、分段、循環處理等步驟,最終生成一個128位的哈希值。
用字符串"Hello"的加密過程說明 MD5 算法的基本處理流程:
1. 原始輸入(明文)
|
|(轉換為二進制)
V
2. 二進制數據 "Hello"
|
|(填充到512位的倍數)
V
3. 填充后的二進制數據
|
|(添加原始長度的64位表示)
V
4. 長度附加后的二進制數據
|
|(分割成512位的消息塊)
V
5. 消息塊1 ... 消息塊n
|
|(每塊512位,共16個32位字)
V
6. 初始MD5值(ABCD)
|
|(通過主循環處理每個塊)
V
7. 主循環(每塊16步)
|_________|_________|
| | |
V V V
8. 經過F, G, H, I函數的32位字
|_________|_________|
| | |
V V V
9. 更新后的MD5值
|
V
10. 最終MD5散列值(128位)
(4) 代碼實現
使用 Java 實現 MD5 加密的示例代碼:
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Example {
//用于將字節數組轉換為十六進制表示的字符串
public static String toHexString(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
public static String getMD5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
return toHexString(messageDigest);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
String password = "Hello, World!";
//輸出結果:65a8e27d8879283831b664bd8b7f0ad4
System.out.println("MD5 Hash: " + getMD5(password));
}
}
(5) 注意事項
- MD5 算法已經不再被認為是安全的,因此不推薦用于需要高安全性的加密場景。
- MD5 算法的輸出可以作為數據完整性校驗,但不應用于加密和解密操作。
2.AES 加密
(1) 適用場景
AES(高級加密標準)是一種廣泛使用的對稱加密算法,適用于以下場景:
- 數據傳輸安全:在網絡通信中加密數據,保護數據傳輸過程中的隱私和完整性。
- 文件和數據存儲:對存儲在服務器或云端的敏感文件進行加密。
- VPN 連接:確保遠程連接的安全性。
(2) 功能特性
- 安全性:AES 提供強大的安全性,是目前最推薦使用的對稱加密算法之一。
- 靈活性:支持128、192和256位的密鑰長度,適應不同的安全級別需求。
- 效率高:AES算法效率高,適合大量數據的快速加密。
(3) 原理及流程圖
例如,使用AES加密算法加密字符串 "hello"
1. 明文 "hello"
|
|(轉換為二進制格式)
V
2. 128位二進制明文
|
|(可能需要填充)
V
3. 填充后的128位二進制數據
|
|(密鑰擴展)
V
4. 生成輪密鑰
|
|(初始輪密鑰加)
V
5. 與輪密鑰異或后的數據塊
|
|(主輪加密處理)
V
|_________________________|
| |
| SubBytes(字節代換) |
|_________________________|
| |
| ShiftRows(行移位) |
|_________________________|
| |
| MixColumns (列混淆) |
|_________________________|
| |
| AddRoundKey(輪密鑰加) |
|_________________________|
V V
6. 密文數據塊
|
V
7. 密文(二進制格式)
(4) 示例代碼
對字符串 "hello" 進行AES加密的示例:
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
public class AESExample {
public static void main(String[] args) {
try {
// 實例化密鑰生成器,并初始化為AES(128位)
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
// 初始化128位 ,可修改
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
// 實例化Cipher對象,用于AES加密
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// 轉換明文字符串 "hello" 為二進制數據
String plainText = "hello";
byte[] plainTextBytes = plainText.getBytes();
// 加密得到密文
byte[] encryptedBytes = cipher.doFinal(plainTextBytes);
// 打印加密后的密文(通常以十六進制形式表示)
System.out.println("Encrypted bytes: " + bytesToHex(encryptedBytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
// 將字節數組轉換為十六進制字符串
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}
(5) 注意事項
- AES加密是對稱加密,加密和解密使用相同的密鑰。
- 密鑰長度的選擇需要根據具體的應用場景和安全需求來確定。
3.DES加密
(1) 適用場景
DES(數據加密標準)是一種較早的對稱加密算法,由于密鑰長度(56位有效密鑰,相對較短),其安全性相對較低,一般一些舊的系統中仍然使用。
主要適用場景包括:
數據傳輸:在安全性要求不是特別高的場合,DES仍可用于數據傳輸的加密。
(2) 功能特性
- 對稱加密:使用相同的密鑰進行加密和解密。
- 密鑰長度:實際有效的密鑰長度為56位,另外8位用于奇偶性校驗。
- 效率:由于算法較老,在現代硬件上的相對速度較慢。
- 安全性:由于密鑰長度較短,DES容易受到暴力破解攻擊,因此認為不安全的。
(3) 原理及流程圖
我們通過以下步驟使用DES加密字符串 "hello":
1. 明文 "hello"
|
|(轉換為二進制并填充)
V
2. 64位二進制明文
|
|(初始置換 IP)
V
3. 初始置換后的數據塊
|
|(密鑰加)
V
4. 與密鑰異或后的數據塊
|
|(Feistel網絡處理)
V
|_________________________|
| |
| 密鑰加 |
|_________________________|
| |
| 置換 |
|_________________________|
| |
| 代換 |
|_________________________|
| |
| 循環左移 |
|_________________________|
V V
5. Feistel網絡輸出
|
|(逆置換 IP^-1)
V
6. 逆置換后的密文塊
|
V
7. 密文
(4) 示例代碼(Java)
以下是使用Java代碼對字符串 "hello" 進行DES加密的示例:
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class DESExample {
public static void main(String[] args) {
try {
// 實例化密鑰生成器,并初始化為DES
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
keyGenerator.init(56); // DES密鑰長度為56位
SecretKey secretKey = keyGenerator.generateKey();
// 實例化Cipher對象,用于DES加密
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
IvParameterSpec iv = new IvParameterSpec(new byte[8]); // 使用8位的IV
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
// 轉換明文字符串 "hello" 為二進制數據
String plainText = "hello";
byte[] plainTextBytes = plainText.getBytes("UTF-8");
// 加密得到密文
byte[] encryptedBytes = cipher.doFinal(plainTextBytes);
// 打印加密后的密文(通常以Base64形式表示)
System.out.println("Encrypted text: " + Base64.getEncoder().encodeToString(encryptedBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
}
(5) 注意事項
- DES由于其較短的密鑰長度,已不適用于安全性要求高的場合。
- 在實際使用中,推薦使用AES或其他更安全的加密算法。
4.國密算法加密
(1) 適用場景
國密算法,即中國國家商用密碼算法標準,包括但不限于SM1、SM2、SM3、SM4等。主要用于:
- 金融服務:在金融服務行業中用于保證交易安全。
- 政府通信:確保政府數據傳輸的安全性。
- 企業數據保護:用于保護商業機密和客戶數據。
- 安全令牌:用于安全令牌的加密。
(2) 功能特性
- 標準性:國密算法符合中國的商用密碼標準。
- 安全性:可抵御多種已知攻擊方式。
- 多樣性:包含多種算法,如SM2用于數字簽名,SM4用于數據加密。
(3) 原理及流程圖
使用字符串 "hello" 進行說明:
1. 明文 "hello"
|
|(轉換為二進制格式)
V
2. 二進制明文數據
|
|(配置密鑰和參數)
V
3. 初始化加密模塊
|
|(設置SM4密鑰和IV)
V
4. 使用SM4加密明文
|
|(多輪迭代加密處理)
V
5. 輸出SM4密文
(4) 示例代碼(Java)
使用Java偽代碼對字符串 "hello" 進行SM4加密的示例:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
public class SM4Example {
public static void main(String[] args) {
try {
// 添加Bouncy Castle安全提供者
Security.addProvider(new BouncyCastleProvider());
// 實例化密鑰生成器,并初始化為SM4
KeyGenerator keyGenerator = KeyGenerator.getInstance("SM4");
keyGenerator.init(128); // SM4密鑰長度為128位
SecretKey secretKey = keyGenerator.generateKey();
// 實例化Cipher對象,用于SM4加密
Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS7Padding");
IvParameterSpec iv = new IvParameterSpec(new byte[16]); // 16字節的IV
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
// 轉換明文字符串 "hello" 為二進制數據
String plainText = "hello";
byte[] plainTextBytes = plainText.getBytes("UTF-8");
// 加密得到密文
byte[] encryptedBytes = cipher.doFinal(plainTextBytes);
// 打印加密后的密文(通常以十六進制或Base64形式表示)
System.out.println("Encrypted text: " + bytesToHex(encryptedBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
// 將字節數組轉換為十六進制字符串
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}
(5) 注意事項
- 密鑰管理是加密過程中的一個重要環節,密鑰應該安全地生成、存儲和分發。
- 國密算法的使用需要遵守相關的法律法規和標準。
5. RSA 加密
(1) 適用場景
使用場景:
- 安全電子郵件:使用 RSA 對郵件內容進行加密,確保郵件傳輸過程中的安全性。
- SSL/TLS:在 SSL/TLS 協議中,RSA 用于加密交換對稱密鑰,以建立安全通信。
- 數字簽名:RSA 用于生成數字簽名,驗證軟件或文檔的完整性和來源。
- 身份驗證:用于身份驗證過程,確保通信雙方的身份。
(2) 功能特性
- 非對稱加密:使用一對密鑰,公鑰加密,私鑰解密。
- 安全性:難以破解,安全性高。
- 密鑰長度:通常使用 1024 位、2048 位或更長的密鑰,以提高安全性。
(3) 原理及流程圖
例如,明文"hello"加密解密過程如下:
1. 明文 "hello"
|
|(轉換為數值 m)
V
2. 使用公鑰 (e, n) 加密
|___________|
| |
| m^e mod n|
|___________|
|
V
3. 得到密文 c
|
|(使用私鑰 (d, n) 解密)
V
|___________|
| |
| c^d mod n|
|___________|
|
V
4. 恢復明文 m
|
V
5. 明文 "hello"
(4) 程序實現
使用Java實現RSA加密和解密的簡單示例:
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAExample {
public static void main(String[] args) throws Exception {
// 生成密鑰對
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 公鑰和私鑰
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 明文
String plainText = "hello";
byte[] data = plainText.getBytes();
// 加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedData = cipher.doFinal(data);
System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encryptedData));
// 解密
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedData = cipher.doFinal(encryptedData);
String decryptedText = new String(decryptedData);
System.out.println("Decrypted: " + decryptedText);
}
}
(5) 注意事項
- 密鑰長度:推薦使用2048位或更長的密鑰以確保安全性。
- 密鑰管理:公鑰可以公開,但私鑰必須保密,防止泄露。
- 性能:RSA加密和解密的速度相對較慢,不適合加密大量數據。
總結
綜上,實際使用中,常常根據自身系統特征選擇。比如:執行效率、數據量、安全合規要求等,這里給出上述簡易版整理。
加密算法 | 名稱 | 有效長度 | 特性 | 是否加密解密 | 優點 | 缺點 |
MD5 | MD5 散列算法 | 128位 | 散列函數 | 不可逆 | 速度快,簡單 | 安全性低,易受碰撞攻擊 |
AES | AES 加密算法 | 128/192/256位 | 對稱加密 | 是 | 安全性高,效率高 | 無嚴重弱點 |
DES | DES 加密算法 | 56位 | 對稱加密 | 是 | 速度快,曾廣泛使用 | 密鑰短,安全性低 |
國密SM4 | SM4 加密算法 | 128位 | 對稱加密 | 是 | 符合國內標準,安全性好 | 使用不如AES廣泛 |
RSA | RSA 加密算法 | 1024/2048位 | 非對稱加密 | 是 | 非對稱加密,適合數字簽名 | 計算量大,速度慢 |