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公钥文件操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。