1)RSA私钥和公钥生成步骤
步骤一,生成JKS文件ecouponNotificationRsa.jks,别名为:ecoupon_notification_key,期限20年,jks证书密码123456,算法是RSA keytool -genkeypair -keyalg RSA -keysize 2048 -validity 7300 -dname "CN=disney, OU=disney, O=disney, L=shanghai, ST=shanghai, C=CN" -alias ecoupon_notification_key -keystore myRsa.jks -storepass 123456 步骤二,查看JKS证书信息 keytool -list -v -keystore ecouponNotificationRsa.jks -storepass 123456 步骤三,根据 jks 私钥生成cer证书, cer证书密码设置为 555666 keytool -export -alias my_service_key -keystore myRsa.jks -storepass 555666 -file myRsaPublicKey.cer 步骤四,根据 cer 证书生成公钥,并将公钥导入到客户端秘钥库中(这一步是调用此service的对方app操作,需要借助第三步生成的cer证书) keytool -import -alias ecoupon_notification_rsa_public_key -file myRsaPublicKey.cer -keystore ecoupon_notification_rsa_public_key.jks -storepass 555666 步骤五,将第一步生成好的jks证书的绝对路径地址配置到配置中心,例子如下
rsa.private.key.jks.path=/key/library/myRsa.jks
rsa.private.key.jks.password=123456
rsa.public.key.certificate.alias=my_service_key
rsa.public.key.certificate.password=555666
2)生成私钥 bean 和 公钥 bean,注入到 spring 容器
import java.io.FileInputStream; import java.io.IOException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; @Slf4j @Configuration public class ConfigRsa { @Bean("keyStore") public KeyStore getKeyStore( @Value("${rsa.private.key.jks.path}") String privateKeyJksPath, @Value("${rsa.private.key.jks.password}") String privateKeyJksPassword ) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException { try (FileInputStream fis = new FileInputStream(privateKeyJksPath)) { KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(fis, privateKeyJksPassword.toCharArray()); return keyStore; } } @Bean("privateKey") public PrivateKey getPrivateKey( @Qualifier("keyStore") KeyStore keyStore, @Value("${rsa.public.key.certificate.alias}") String publicKeyCertificateAlias, @Value("${rsa.public.key.certificate.password}") String publicKeyCertificatePassword ) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException { return (PrivateKey) keyStore.getKey(publicKeyCertificateAlias, publicKeyCertificatePassword.toCharArray()); } @Bean("publicKey") public PublicKey getPublicKey( @Qualifier("keyStore") KeyStore keyStore, @Value("${rsa.public.key.certificate.alias}") String publicKeyCertificateAlias ) throws KeyStoreException { return keyStore.getCertificate(publicKeyCertificateAlias).getPublicKey(); } }
3)自定义 RsaUtil 类去签名和验签
import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.util.Base64; @Slf4j @Component("rsaUtil") public class RsaUtil { private static final String ALGORITHM = "SHA256withRSA"; // sign type: RSA2, refer doc: https://opendocs.alipay.com/open/291/106115 @Autowired @Qualifier("privateKey") private PrivateKey privateKey; @Autowired @Qualifier("publicKey") private PublicKey publicKey; public String sign(String originalData) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { Signature signature = Signature.getInstance(ALGORITHM); signature.initSign(privateKey); signature.update(originalData.getBytes()); String signedData = java.util.Base64.getEncoder() .encodeToString(signature.sign()).replace(" ","").replace(" ",""); return signedData; } public boolean verify(String originalData, String signedData) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { Signature signature = Signature.getInstance(ALGORITHM); signature.initVerify(publicKey); signature.update(originalData.getBytes()); boolean isVerify = signature.verify(Base64.getDecoder().decode(signedData)); return isVerify; } }
end.