java 生成 pem 公钥_Java读取OpenSSL生成的PEM公钥文件

JDK8的JCE是不支持读取PEM文件的。需要使用bouncycastle。

项目需求,使用SHA1WithRSA算法,对接口数据做签名。代码如下:

@Service

class SignService {

private static Logger LOG = LoggerFactory.getLogger(SignService.class);

@Autowired

private Config config;

private Signature signature;

@PostConstruct

private void init() {

try {

PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(

getDecoder().decode(config.getPrivateKey().getBytes(ISO_8859_1)));

KeyFactory factory = KeyFactory.getInstance("RSA");

PrivateKey privateKey = factory.generatePrivate(priKeySpec);

signature = Signature.getInstance("SHA1WithRSA");

signature.initSign(privateKey);

} catch (NoSuchAlgorithmException |

/*InvalidAlgorithmParameterException |*/

InvalidKeySpecException |

InvalidKeyException ex) {

LOG.warn("RSA init error: {}.", ex);

}

}

String signAndEncode(String source) {

if (Objects.isNull(source)) {

return null;

} else {

return sign(source)

.map(this::encode)

.orElse("");

}

}

private String encode(byte[] source) {

return getEncoder()

.encodeToString(source);

}

private synchronized Optional sign(String source) {

try {

signature.update(source.getBytes(ISO_8859_1));

return Optional.of(signature.sign());

} catch (SignatureException e) {

LOG.warn("SHA1WithRSA {} error: {}.", source, e);

return Optional.empty();

}

}

}

单元测试,验证签名是否正确。先初始化Signature:

private Signature signature;

@Before

public void init() {

try {

byte[] key = Files.readAllBytes(Paths.get("/home/ls", "ras_public_key.pem"));

Security.addProvider(new BouncyCastleProvider());

final PemObject pemObject;

try (PemReader pemReader = new PemReader(new InputStreamReader(

new ByteArrayInputStream(key)))) {

pemObject = pemReader.readPemObject();

}

X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(pemObject.getContent());

KeyFactory factory = KeyFactory.getInstance("RSA");

PublicKey publicKey = factory.generatePublic(pubKeySpec);

signature = Signature.getInstance("SHA1WithRSA");

signature.initVerify(publicKey);

} catch (Exception e) {

e.printStackTrace();

}

}

验证方法

private boolean verify(String source, String sign) {

byte[] data = getDecoder().decode(sign);

try {

signature.update(source.getBytes());

return signature.verify(data);

} catch (SignatureException e) {

e.printStackTrace();

return false;

}

}

测试

String source = service.signature(request);

String sign = signService.signAndEncode(source);

System.out.println(sign);

assertTrue(verify(source, sign));

证明,内容没有被篡改。

其中,ras_public_key.pem文件由openSSL生成。

ls@LS-8500:~$ openssl genrsa -out rsa_private_key.pem 1024

Generating RSA private key, 1024 bit long modulus (2 primes)

...+++++

...............+++++

e is 65537 (0x010001)

ls@LS-8500:~$ openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

-----BEGIN PRIVATE KEY-----

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==

-----END PRIVATE KEY-----

ls@LS-8500:~$ openssl rsa -in rsa_private_key.pem -pubout -out ras_public_key.pem

writing RSA key

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值