一. 技術(shù)需求
由于項(xiàng)目中的配置文件 配置的地方過多,現(xiàn)將配置文件統(tǒng)一放到nacos上集中管理 且密碼使用加密的方式放在配置文件中
項(xiàng)目中組件使用的版本環(huán)境如下
spring cloud 2021.0.5
spring cloud alibaba 2021.0.5.0
spring boot 2.6.13
二. 技術(shù)實(shí)現(xiàn)
配置文件的加密使用 加密庫 jasypt
三. 簡(jiǎn)單使用步驟
-
引入maven依賴
<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.5</version> </dependency>
-
添加配置
#加解密使用的密碼 可以理解為密鑰 jasypt.encryptor.password=12581
-
使用jasypt配置的密碼來加密密碼 并替換配置原先密碼 (提供工具類進(jìn)行加密)
#原密碼 spring.datasource.passsword=1232456 #新的密碼 其實(shí) rngDAJwRU09A3oNLkxzNaP3wfyhHt5N4DPAjudNJKDYAWXDeFmdGcFvgZJSh4gqZ 為源密碼加密后的值 spring.datasource.password=ENC(rngDAJwRU09A3oNLkxzNaP3wfyhHt5N4DPAjudNJKDYAWXDeFmdGcFvgZJSh4gqZ)
工具類如下
@Slf4j
public class Custom {
public static void main(String[] args) {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
//TODO 替換為配置文件中的密碼
config.setPassword("12581");
//默認(rèn)的加密算法
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
//TODO 123456 替換為所需加密的 原文
String encrypt = encryptor.encrypt("123456");
log.info("encrypt: {}", encrypt);
}
}
到此就完成基本的配置文件加解密
你以為結(jié)束了嗎,no~~~~
四. 高級(jí)使用篇
上面使用的默認(rèn)的加解密的工具類,但是jasypt.encryptor.password 還是需要配置在配置文件中的 (配置文件、jvm參數(shù)等)本質(zhì)來講還是容易統(tǒng)一泄露。到這里,可能就有靈感了。不如我們自定義的加密的工具類 復(fù)雜的話 也可以搞個(gè)非對(duì)稱加密(這個(gè)可自行研究)
目前我們來使用下 自定義加密的工具
(1)首先實(shí)現(xiàn)自定義的加密工具 需要實(shí)現(xiàn) StringEncryptor 即可 我們這是用的國(guó)密4的對(duì)稱加密算法 同時(shí)使用了 hutool的工具類
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SM4;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.jasypt.encryption.StringEncryptor;
import java.nio.charset.StandardCharsets;
/**
* @author leon
* @date 2023-08-19 10:54:32
*/
@Slf4j
public class Sm4Encryptor implements StringEncryptor {
private static final SM4 SM_4;
static {
byte[] key = "1234567891234560".getBytes();
byte[] iv = "1234567891234560".getBytes();
SM_4 = new SM4(Mode.CBC, Padding.PKCS5Padding, key, iv);
}
@Override
public String encrypt(String message) {
return SM_4.encryptHex(message);
}
@Override
public String decrypt(String encryptedMessage) {
return SM_4.decryptStr(encryptedMessage);
}
public static void main(String[] args) {
String originalValue = "123456";
String encrypted = SM_4.encryptHex(originalValue);
String decrypted = SM_4.decryptStr(encrypted);
log.info("Original Value: {}" , originalValue);
log.info("Encrypted Value: {}" , encrypted);
log.info("Decrypted Value: {}", decrypted);
}
}
(2)注冊(cè)該bean 這需要使用特殊的方式注冊(cè)bean 因?yàn)槲覀兿M?Spring Boot 應(yīng)用程序啟動(dòng)期間提前將自定義的加解密類添加到 Spring 的應(yīng)用程序上下文中,以便在配置文件加載之前,加解密類已經(jīng)可用。這樣可以確保配置文件中的加密屬性能夠在加載時(shí)使用正確的自定義加解密邏輯進(jìn)行解密
新建初始化類
import com.stlye.encryptor.Sm4Encryptor;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @date 2023-08-21 13:57:20
* @author leon
*/
public class CustomContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.getBeanFactory().registerSingleton("encryptorBean", new Sm4Encryptor());
}
}
其次在resource 下新建 META_INF文件夾 并新建 spring.factories 文件
org.springframework.context.ApplicationContextInitializer=com.style.order.config.CustomContextInitializer
(3)調(diào)整配置
#移除該配置
jasypt.encryptor.password=12581
#新增如下配置 自定義加解密工具的bean名稱
jasypt.encryptor.bean=encryptorBean
(4) 使用該工具類生成需要加密的內(nèi)容 并替換 原配置文件中的內(nèi)容
#其中cab60ba208f8a7d87c4f631e2763607a為源密碼加密后的內(nèi)容
spring.datasource.password=ENC(cab60ba208f8a7d87c4f631e2763607a)
#另外屬性解密的前綴和后綴都是支持自定義 默認(rèn)如下
jasypt.encryptor.property.prefix=ENC(
jasypt.encryptor.property.suffix=)
到這里就完成配置的文件的加密 你肯定會(huì)好奇,解密需要我們自己做么,回答當(dāng)然不需要,這個(gè)框架中已經(jīng)自動(dòng)幫我們進(jìn)行了解密
具體的實(shí)現(xiàn)原理可看源碼類 EnableEncryptablePropertiesBeanFactoryPostProcessor 和 EncryptablePropertyResolverConfiguration 兩大核心類 本質(zhì)上來講也是動(dòng)態(tài)代理。
以下是國(guó)密4加密算法的參數(shù)介紹
密碼的加密算法選擇了 SM4 國(guó)密的對(duì)稱加密算法
內(nèi)置參數(shù) 模式和補(bǔ)碼方式對(duì)比如下
//不同的模式和補(bǔ)碼方式在加密算法中有不同的作用,它們會(huì)影響加密和解密的行為以及安全性。下面我會(huì)簡(jiǎn)要解釋一下不同模式和補(bǔ)碼方式的區(qū)別,并提供一些關(guān)于安全性的信息:
//
//**模式(Mode)**:
//加密模式定義了數(shù)據(jù)塊之間是如何加密的,它影響到同一消息分成多個(gè)數(shù)據(jù)塊時(shí)的加密方式。以下是一些常見的加密模式:
//
//1. **ECB(Electronic Codebook)**:每個(gè)數(shù)據(jù)塊都獨(dú)立加密,相同的輸入會(huì)得到相同的輸出。不適合加密大量數(shù)據(jù),安全性較差。
//
//2. **CBC(Cipher Block Chaining)**:前一個(gè)數(shù)據(jù)塊的加密結(jié)果會(huì)與當(dāng)前數(shù)據(jù)塊一起進(jìn)行加密。需要一個(gè)初始化向量(IV)來增加安全性。
//
//3. **CFB(Cipher Feedback)**:前一個(gè)密文塊被解密并與當(dāng)前明文塊進(jìn)行異或操作,然后再進(jìn)行加密。不需要 IV。
//
//4. **OFB(Output Feedback)**:類似于 CFB,但是前一個(gè)密文塊只用于生成密鑰流,不直接與明文塊進(jìn)行操作。不需要 IV。
//
//5. **CTR(Counter)**:將 IV 與一個(gè)計(jì)數(shù)器組合,生成密鑰流,然后與明文塊進(jìn)行異或操作。不需要 IV。
//
//**補(bǔ)碼方式(Padding)**:
//補(bǔ)碼方式是在加密塊大小與數(shù)據(jù)大小不匹配時(shí),如何填充數(shù)據(jù)塊的方式。以下是一些常見的補(bǔ)碼方式:
//
//1. **NoPadding**:不進(jìn)行任何填充,要求明文的大小必須是加密塊大小的倍數(shù)。
//
//2. **PKCS5Padding** / **PKCS7Padding**:在數(shù)據(jù)塊的末尾填充字節(jié),字節(jié)的值等于需要填充的字節(jié)數(shù)。
//
//3. **ISO10126Padding**:在數(shù)據(jù)塊的末尾填充隨機(jī)字節(jié),最后一個(gè)字節(jié)指示填充的字節(jié)數(shù)。
//
//4. **ZeroBytePadding**:在數(shù)據(jù)塊的末尾填充零字節(jié)。
//
//**安全性評(píng)估**:
//安全性評(píng)估涉及多個(gè)因素,包括加密算法的強(qiáng)度、密鑰的管理、數(shù)據(jù)傳輸?shù)陌踩缘?。在選擇加密模式和補(bǔ)碼方式時(shí),要根據(jù)具體的應(yīng)用場(chǎng)景和安全需求進(jìn)行權(quán)衡。一般而言,以下是一些建議:
//
//- **模式選擇**:CBC 模式相對(duì)較為常見和安全,適用于大多數(shù)場(chǎng)景。CTR 也是一種常見的選擇,適合并行加解密。
//
//- **補(bǔ)碼方式選擇**:PKCS7Padding / PKCS5Padding 是常見的選擇,它們會(huì)根據(jù)需要填充的字節(jié)數(shù)進(jìn)行填充,相對(duì)比較安全。
//
//總之,選擇加密模式和補(bǔ)碼方式時(shí),應(yīng)該綜合考慮性能、安全性和適用性。在設(shè)計(jì)和實(shí)現(xiàn)加密系統(tǒng)時(shí),最好參考專業(yè)的加密標(biāo)準(zhǔn)和最佳實(shí)踐,以確保數(shù)據(jù)的安全性。
其中安全性較高 mode參數(shù)可選擇值的是 CBC / GCM
在國(guó)密4(SM4)加密算法中,GCM(Galois/Counter Mode)和CBC(Cipher Block Chaining)都是加密模式,用于定義不同的加密操作方式。它們有一些區(qū)別,包括加密過程、性能、安全性等方面。
-
GCM模式(Galois/Counter Mode):
- GCM是一種高級(jí)的分組加密模式,除了提供加密和解密功能外,還具有認(rèn)證和完整性校驗(yàn)的能力。
- GCM模式在加密過程中會(huì)使用一個(gè)稱為"Nonce"的值,用于確保每個(gè)加密操作的唯一性,避免重復(fù)使用Nonce導(dǎo)致的安全問題。
- GCM模式可以同時(shí)進(jìn)行加密和認(rèn)證,因此在一些場(chǎng)景中可以減少通信的復(fù)雜性和性能開銷。
- 由于GCM模式的性能較高且提供了認(rèn)證能力,通常在需要較高性能和安全性的場(chǎng)景中被使用。
-
CBC模式(Cipher Block Chaining):
- CBC是一種較為傳統(tǒng)的分組加密模式,每個(gè)分組的密文會(huì)依賴于前一個(gè)分組的明文,因此具有一定的關(guān)聯(lián)性。
- CBC模式需要在加密前進(jìn)行填充操作,以適應(yīng)固定長(zhǎng)度的分組大小。
- 由于每個(gè)分組的加密都依賴于前一個(gè)分組的密文,所以在并行處理時(shí)可能存在性能上的限制。
- CBC模式通常需要額外的認(rèn)證步驟來保證數(shù)據(jù)完整性和安全性。
性能方面,GCM模式通常在處理大量數(shù)據(jù)時(shí)具有更好的性能,因?yàn)樗梢酝瑫r(shí)進(jìn)行加密和認(rèn)證,而且不需要像CBC那樣需要明確的填充步驟。然而,由于GCM模式引入了額外的認(rèn)證計(jì)算,對(duì)于較小的數(shù)據(jù)塊,GCM的性能可能會(huì)略遜于CBC。
選擇合適的加密模式取決于具體的應(yīng)用場(chǎng)景和需求。如果你需要高性能和認(rèn)證能力,可以考慮使用GCM模式。如果你更關(guān)注傳統(tǒng)的分組加密模式,并且不需要認(rèn)證能力,可以選擇CBC模式。文章來源:http://www.zghlxwxcb.cn/news/detail-672173.html
GCM 由于使用一個(gè)稱為"Nonce"的值,每次加密都需要保證唯一 ,每次需要新建實(shí)例 ,避免重復(fù)使用Nonce導(dǎo)致的安全問題 這就導(dǎo)致了性能來講可能稍遜于 CBC 且GCM模式 不需要補(bǔ)碼文章來源地址http://www.zghlxwxcb.cn/news/detail-672173.html
到了這里,關(guān)于spring boot集成jasypt 并 實(shí)現(xiàn)自定義加解密的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!