Java读取OpenSSL生成的PEM公钥文件操作
JDK8的JCE是不支持读取PEM文件的。需要使用bouncycastle。
项目需求,使用SHA1WithRSA算法,对接口数据做签名。
代码如下:
@Service
classSignService{
privatestaticLoggerLOG=LoggerFactory.getLogger(SignService.class);
@Autowired
privateConfigconfig;
privateSignaturesignature;
@PostConstruct
privatevoidinit(){
try{
PKCS8EncodedKeySpecpriKeySpec=newPKCS8EncodedKeySpec(
getDecoder().decode(config.getPrivateKey().getBytes(ISO_8859_1)));
KeyFactoryfactory=KeyFactory.getInstance("RSA");
PrivateKeyprivateKey=factory.generatePrivate(priKeySpec);
signature=Signature.getInstance("SHA1WithRSA");
signature.initSign(privateKey);
}catch(NoSuchAlgorithmException|
/*InvalidAlgorithmParameterException|*/
InvalidKeySpecException|
InvalidKeyExceptionex){
LOG.warn("RSAiniterror:{}.",ex);
}
}
StringsignAndEncode(Stringsource){
if(Objects.isNull(source)){
returnnull;
}else{
returnsign(source)
.map(this::encode)
.orElse("");
}
}
privateStringencode(byte[]source){
returngetEncoder()
.encodeToString(source);
}
privatesynchronizedOptionalsign(Stringsource){
try{
signature.update(source.getBytes(ISO_8859_1));
returnOptional.of(signature.sign());
}catch(SignatureExceptione){
LOG.warn("SHA1WithRSA{}error:{}.",source,e);
returnOptional.empty();
}
}
}
单元测试,验证签名是否正确。先初始化Signature:
privateSignaturesignature;
@Before
publicvoidinit(){
try{
byte[]key=Files.readAllBytes(Paths.get("/home/ls","ras_public_key.pem"));
Security.addProvider(newBouncyCastleProvider());
finalPemObjectpemObject;
try(PemReaderpemReader=newPemReader(newInputStreamReader(
newByteArrayInputStream(key)))){
pemObject=pemReader.readPemObject();
}
X509EncodedKeySpecpubKeySpec=newX509EncodedKeySpec(pemObject.getContent());
KeyFactoryfactory=KeyFactory.getInstance("RSA");
PublicKeypublicKey=factory.generatePublic(pubKeySpec);
signature=Signature.getInstance("SHA1WithRSA");
signature.initVerify(publicKey);
}catch(Exceptione){
e.printStackTrace();
}
}
验证方法
privatebooleanverify(Stringsource,Stringsign){
byte[]data=getDecoder().decode(sign);
try{
signature.update(source.getBytes());
returnsignature.verify(data);
}catch(SignatureExceptione){
e.printStackTrace();
returnfalse;
}
}
测试
Stringsource=service.signature(request); Stringsign=signService.signAndEncode(source); System.out.println(sign); assertTrue(verify(source,sign));
证明,内容没有被篡改。
其中,ras_public_key.pem文件由openSSL生成。
ls@LS-8500:~$opensslgenrsa-outrsa_private_key.pem1024 GeneratingRSAprivatekey,1024bitlongmodulus(2primes) ...+++++ ...............+++++ eis65537(0x010001) ls@LS-8500:~$opensslpkcs8-topk8-informPEM-inrsa_private_key.pem-outformPEM-nocrypt -----BEGINPRIVATEKEY----- MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAOk4nqif4LtwfePZ IeGgUc5XYbWk8FpT6UEgO/43i0uprf2RXs3j9eDjOyRwkW2iMCF6S3bNxYuiyJv4 eNc+8w87PJ9bOMRq9WH+ISWIfnPu2x6A1oNOeNkAL7v3ztmpcAn2bNMJ5VscSKp8 S1U02LbHpOErPjvnEul9a/e8xb7TAgMBAAECgYEAvpMeyuoCKQiORo6aqhVoY7Vx yY2jPhyNYUNm4qAeulBINgkBMDtUI1VrcaZun+jFbcXSPp19DFKTnSgYDsOItt04 VLRSZm5yU1EfL21ZvbxIQjjSMv4BxndjdfdoGh5Gve0p1vqtnXtMivkNNI/HdCrx R2CpcGNo4Uqg+zgvwzECQQD1yULuH1sMTEGqLHZaBXVVt1ny+oF+3CnDz2ZdQTWj SLFfBSKplCL8TuEakauUiYf6BVtOjrpzKHRs7hDuZLW5AkEA8umwPbO09ijQdg5e /nkEnJnG5C4krXZuIcsYnf1wrBCLAoOImgDSvVzRrXHMGNvvP0D3gTIxwZSNPt57 1OFe6wJBAJmcOm9WO3IZKqTvetxSMv3qRJY+B7bAZH3TXleEDMDLCsenDv3K7n6f 0cHoLsL7nXcd5+3V+CNGslTuCLjlSkkCQQCM1fqNu5xmwAElAW4IIkgPN4U+FJbF T43I4ATUzPU/fZPrEDHqACIvEhqrcfgATbuns9YMPPrmHmfKFJo9MbGjAkEAzmbW IsDQP4S8TJVd6PvyNZgNrTZvtlMT8/v4MytaEErrljhAR/YLKLcWFxLmQNAL9g4M SsHT8KunE5YrBmkXkg== -----ENDPRIVATEKEY----- ls@LS-8500:~$opensslrsa-inrsa_private_key.pem-pubout-outras_public_key.pem writingRSAkey
补充知识:Java导入OpenSSL生成的公私钥文件
1.生成2048-bitRSA私钥
$opensslgenrsa-outprivate_key.pem2048
2.导出RSA公钥
$opensslrsa-inprivate_key.pem-pubout-outpublic_key.pem
3.将公私钥文件private_key.pem和public_key.pem的头尾注释去掉
即:
-----BEGINPUBLICKEY-----
-----ENDPUBLICKEY-----
-----BEGINRSAPRIVATEKEY-----
-----ENDRSAPRIVATEKEY-----
4.读取公私钥文件内容
//filePath即为private_key.pem和public_key.pem
publicstaticStringgetKeyFromFile(StringfilePath)throwsException{
Filefile=newFile(filePath);
InputStreamins=newFileInputStream(file);
BufferedReaderbr=newBufferedReader(newInputStreamReader(ins));
StringreadLine=null;
StringBuffersb=newStringBuffer();
while((readLine=br.readLine())!=null){
sb.append(readLine);
}
br.close();
ins.close();
returnnewString(sb);
}
5.读取私钥
publicstaticPrivateKeygetPrivateKey(StringprivateKey)throwsException{
//解码由base64编码的私钥
byte[]keyBytes=decryptBASE64(privateKey);
PKCS8EncodedKeySpecpkcs8KeySpec=newPKCS8EncodedKeySpec(keyBytes);
KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
//取得私钥
PrivateKeypriKey=keyFactory.generatePrivate(pkcs8KeySpec);
returnpriKey;
}
6.读取公钥
publicstaticPublicKeygetPublicKey(StringpublicKeyStr)throwsException{
//解码由base64编码的公钥
byte[]keyBytes=decryptBASE64(publicKeyStr);
//取得公钥
X509EncodedKeySpecx509KeySpec=newX509EncodedKeySpec(keyBytes);
KeyFactorykeyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
PublicKeypublicKey=keyFactory.generatePublic(x509KeySpec);
returnpublicKey;
}
以上这篇Java读取OpenSSL生成的PEM公钥文件操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。