文章目錄
- 概述
- 疑問
- PBE 算法 ( Password Based Encryption)
- Code
- POM
- 實現
- 小結
概述
加密與安全_探索對稱加密算法中我們提到AES加密密鑰長度是固定的128/192/256位,而不是我們用WinZip/WinRAR那樣,隨便輸入幾位都可以。
這是因為對稱加密算法決定了口令必須是固定長度,然后對明文進行分塊加密。又因為安全需求,口令長度往往都是128位以上,即至少16個字符。
疑問
我們平時使用的加密軟件,輸入6位、8位都可以,難道是加密方式不一樣嗎?
用戶輸入的口令往往不能直接作為AES的密鑰進行加密,因為它們的長度通常不符合AES密鑰的要求,而且可能存在規律性,容易受到字典攻擊等安全威脅。
為了解決這個問題,通常會使用PBE算法,采用隨機數雜湊計算出真正的密鑰,再進行加密。。
PBE 算法 ( Password Based Encryption)
PBE算法(Password-Based Encryption
)是一種安全的密碼基礎加密算法,用于將用戶輸入的口令轉換為符合要求的密鑰,以便進行加密操作。 在使用PBE算法時,用戶只需輸入一個口令,而不需要直接提供一個符合要求的密鑰。PBE算法的作用是通過結合用戶輸入的口令和一個安全隨機生成的鹽值,采用雜湊計算的方式生成最終的密鑰。
通俗的可以理解為下面的函數:
key = generate(userPassword, secureRandomPassword);
以AES密鑰生成為例,用戶只需輸入一個口令,而不需要擔心口令的長度和復雜度是否符合要求。PBE算法會在內部生成一個安全的隨機數作為鹽值,并將用戶輸入的口令與鹽值一起進行雜湊計算,從而生成一個符合AES加密算法要求的真正密鑰。
通過這種方式,PBE算法實現了對用戶口令的保護,同時確保生成的密鑰符合加密算法的要求,從而提高了整個加密系統的安全性。
Code
POM
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.68</version></dependency>
實現
package com.artisan.securityalgjava.peb;import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world* 使用PBE算法進行加密和解密示例*/
public class PBEExample {public static void main(String[] args) throws Exception {// 將BouncyCastle作為Provider添加到java.security:Security.addProvider(new BouncyCastleProvider());// 原文:String message = "Hello, world!";// 加密口令:String password = "hello12345";// 16 bytes隨機Salt:byte[] salt = SecureRandom.getInstanceStrong().generateSeed(16);System.out.printf("salt: %032x\n", new BigInteger(1, salt));// 加密:byte[] data = message.getBytes("UTF-8");byte[] encrypted = encrypt(password, salt, data);System.out.println("encrypted: " + Base64.getEncoder().encodeToString(encrypted));// 解密:byte[] decrypted = decrypt(password, salt, encrypted);System.out.println("decrypted: " + new String(decrypted, "UTF-8"));}// 加密:public static byte[] encrypt(String password, byte[] salt, byte[] input) throws GeneralSecurityException {// 使用口令生成PBEKeySpec對象PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());// 創建密鑰工廠SecretKeyFactory skeyFactory = SecretKeyFactory.getInstance("PBEwithSHA1and128bitAES-CBC-BC");// 生成密鑰對象SecretKey skey = skeyFactory.generateSecret(keySpec);// 創建PBE參數對象PBEParameterSpec pbeps = new PBEParameterSpec(salt, 1000);// 創建加密器Cipher cipher = Cipher.getInstance("PBEwithSHA1and128bitAES-CBC-BC");// 初始化加密器cipher.init(Cipher.ENCRYPT_MODE, skey, pbeps);// 執行加密操作return cipher.doFinal(input);}// 解密:public static byte[] decrypt(String password, byte[] salt, byte[] input) throws GeneralSecurityException {// 使用口令生成PBEKeySpec對象PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());// 創建密鑰工廠SecretKeyFactory skeyFactory = SecretKeyFactory.getInstance("PBEwithSHA1and128bitAES-CBC-BC");// 生成密鑰對象SecretKey skey = skeyFactory.generateSecret(keySpec);// 創建PBE參數對象PBEParameterSpec pbeps = new PBEParameterSpec(salt, 1000);// 創建解密器Cipher cipher = Cipher.getInstance("PBEwithSHA1and128bitAES-CBC-BC");// 初始化解密器cipher.init(Cipher.DECRYPT_MODE, skey, pbeps);// 執行解密操作return cipher.doFinal(input);}
}
在使用PBE時,引入BouncyCastle
提供了更多的加密算法支持,并且可以使用其中的PBE算法。
-
指定算法為
PBEwithSHA1and128bitAES-CBC-BC
表明了我們使用SHA1和128位AES加密算法結合的PBE算法。 -
真正的AES密鑰是在調用
Cipher#init()
方法時同時傳入SecretKey
和PBEParameterSpec
實現的。在創建PBEParameterSpec
時,我們指定了循環次數為1000。循環次數的增加可以增加破解所需的計算量,從而提高加密的安全性。 -
如果我們固定了salt和循環次數,就得到了一個通用的“口令”加密軟件。用戶只需要輸入口令,程序就可以使用固定的salt和循環次數來加密和解密數據。
-
如果我們將隨機生成的salt存儲在U盤中,就可以得到一個“口令”加USB Key的加密軟件。這種方式的好處在于,即使用戶使用了一個非常弱的口令,沒有U盤也無法解密,因為U盤存儲的隨機數密鑰具有很高的安全性。
小結
-
PBE算法(
Password-Based Encryption
)通過用戶輸入的口令和一個安全的隨機salt結合,經過多次迭代的雜湊計算生成最終的密鑰(Key),然后再使用這個密鑰進行加密操作。這種方式的安全性得到了顯著提高,因為即使用戶輸入的口令較弱,通過引入隨機salt和多次迭代的雜湊計算,生成的密鑰也具有足夠的復雜性和隨機性,從而增加了破解的難度。 -
PBE算法內部使用的仍然是標準的對稱加密算法,例如AES。生成的密鑰(Key)是由用戶口令和隨機salt計算得出的,然后再傳遞給底層的對稱加密算法進行加密和解密操作。這種結構既保留了對稱加密算法的高效性和快速性,又通過PBE算法增加了用戶口令的安全性,使得整個加密過程更加安全可靠。
總之,PBE算法通過結合用戶口令和安全的隨機salt,生成一個復雜且安全的密鑰,進而增強了對稱加密算法的安全性,為數據加密提供了更加可靠的保障。