Java读取OpenSSL生成的PEM公钥文件操作

    科技2024-10-02  28

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

    项目需求,使用SHA1WithRSA算法,对接口数据做签名。

    代码如下:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 @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:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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();  } } 验证方法

    1 2 3 4 5 6 7 8 9 10 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;  } } 测试

    1 2 3 4 String source = service.signature(request); String sign = signService.signAndEncode(source); System.out.println(sign); assertTrue(verify(source, sign)); 证明,内容没有被篡改。

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

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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导入OpenSSL生成的公私钥文件

    1. 生成2048-bit RSA私钥

    $ openssl genrsa -out private_key.pem 2048

    2. 导出RSA公钥

    $ openssl rsa -in private_key.pem -pubout -out public_key.pem

    3. 将公私钥文件private_key.pem和public_key.pem的头尾注释去掉

    即:

    -----BEGIN PUBLIC KEY-----

    -----END PUBLIC KEY-----

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

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

    4. 读取公私钥文件内容

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 // filePath即为private_key.pem和public_key.pem public static String getKeyFromFile(String filePath) throws Exception {  File file = new File(filePath);  InputStream ins = new FileInputStream(file);  BufferedReader br = new BufferedReader(new InputStreamReader(ins));  String readLine = null;  StringBuffer sb = new StringBuffer();  while ((readLine = br.readLine()) != null) {   sb.append(readLine);  }  br.close();  ins.close();  return new String(sb); } 5. 读取私钥

    1 2 3 4 5 6 7 8 9 public static PrivateKey getPrivateKey(String privateKey) throws Exception {  // 解码由base64编码的私钥  byte[] keyBytes = decryptBASE64(privateKey);  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  // 取得私钥  PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);  return priKey; } 6. 读取公钥

    1 2 3 4 5 6 7 8 9 public static PublicKey getPublicKey(String publicKeyStr) throws Exception {  // 解码由base64编码的公钥  byte[] keyBytes = decryptBASE64(publicKeyStr);  // 取得公钥  X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);  return publicKey; } 以上这篇Java读取OpenSSL生成的PEM公钥文件操作就是小编分享给大家的全部内容了

    Processed: 0.009, SQL: 8