springboot手动定义datasource及AES/CBC/PKCS7Padding

该博客介绍了如何在Spring Boot应用中配置使用AES/CBC/PKCS7Padding加密的数据库连接密码,并展示了Java实现的解密方法。同时,还提供了Golang辅助工具用于加密配置文件中的密码。
摘要由CSDN通过智能技术生成

配置

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true
    username: test
    password: 0e6cdec059aa47a8c59c0ec004c3d302
    driver-class-name: com.mysql.cj.jdbc.Driver
test:
  encrypt:
    key: testabc@12345678

处理datasource

@Repository
public class CustomDateSource {

    @Value("${test.encrypt.key}")
    private String encryptKey;

    @Bean
    public DataSource dataSource(DataSourceProperties properties) throws Exception {
        String cypherPwd = properties.getPassword();
        if (cypherPwd == null) throw new IOException("spring.datasource.password is null");
        String pwd = Utils.decryptAesCbcPad7(encryptKey, cypherPwd);
        DataSourceBuilder<?> builder = DataSourceBuilder
                .create(properties.getClassLoader())
                .driverClassName(properties.determineDriverClassName())
                .url(properties.determineUrl())
                .username(properties.determineUsername())
                .password(pwd);
        return builder.type(HikariDataSource.class).build();
    }

}

AES/CBC/PKCS7Padding

        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>1.69</version>
        </dependency>

for PKCS7Padding,jdk have PKCS5Padding

  public static String encryptAesCbcPad7(String key, String text) throws Exception {
        try {
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(key.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] original = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8));
            return HexBin.encode(original, false);
        } catch (Exception e) {
            throw new IOException("encrypt password[" + text + "] by key[" + key + "] fail [" + e.getMessage() + "]");
        }
    }
    
  public static String decryptAesCbcPad7(String key, String password) throws Exception {
        try {
            Security.addProvider(new BouncyCastleProvider());
            byte[] pbytes = HexBin.decode(password);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(key.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            byte[] original = cipher.doFinal(pbytes);
            return new String(original, StandardCharsets.UTF_8).trim();
        } catch (Exception e) {
            throw new IOException("decrypt password[" + password + "] by key[" + key + "] fail [" + e.getMessage() + "]");
        }
    }

golang helper

生成可执行文件,辅助配置文件密码生成

// AES,CBC,PKCS7Padding

package handler

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/hex"
	"errors"
)

type AesHandler struct{}

// aes加密,填充秘钥key的16位,24,32分别对应AES-128, AES-192, or AES-256.
func (handler AesHandler) Encrypt(key string, text string) (cypher string, err error) {
	pk := []byte(key)
	block, err := aes.NewCipher(pk)
	if err != nil {
		return "", err
	}
	ciphertext := []byte(text)
	blockSize := block.BlockSize()
	originData := pkcs7pad(ciphertext, blockSize)
	iv := []byte(key)
	blockMode := cipher.NewCBCEncrypter(block, iv)
	crypted := make([]byte, len(originData))
	blockMode.CryptBlocks(crypted, originData)
	return hex.EncodeToString(crypted), nil
}

func pkcs7pad(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值