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<byte[]> 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

你可能感兴趣的:(java)