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导入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. 读取公私钥文件内容

// 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. 读取私钥

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. 读取公钥

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

(0)

相关推荐

  • Java如何基于command调用openssl生成私钥证书

    在windows环境下进行的测试,前提条件,windows上需要先安装openssl. 配置环境变量,查看版本: import java.io.*; import java.util.Properties; public class OpensslCommand { private static void runCMD(String[] CMD) { java.lang.Process process = null; try { process = Runtime.getRuntime().ex

  • Java OpenSSL生成的RSA公私钥进行数据加解密详细介绍

    Java中使用OpenSSL生成的RSA公私钥进行数据加解密 RSA是什么:RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准.目前该加密方式广泛用于网上银行.数字签名等场合.RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困

  • 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; @PostConst

  • Java 读取类路径下的资源文件实现代码

    Java 读取类路径下的资源文件实现代码 一.工具类代码ResourceLoadUtil.java import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; public class ResourceLoadUtil { /** * @par

  • Java读取json数据并存入数据库的操作代码

    Java读取json数据并存入数据库 1. pom依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency> 2.students.json文件 { "students": [ { "stuId&quo

  • python加密解密库cryptography使用openSSL生成的密匙加密解密

    密匙使用步骤一般是:     1. 私匙签名,发送签名后的数据, 公匙验证.     2.公匙加密,发送加密后的数据,私匙解密. 一般使用情景是通过 openssl 生成密匙后再操作的.Linux下生成密匙也很简单. yum 安装 openssl yum -y install openssl 生成三个密匙文件. rsa_private_key.pem 私匙文件 rsa_private_key_pkcs8.pem  pkcs8格式私匙,  rsa_public_key.pem 公匙 openssl

  • Java实现读取及生成Excel文件的方法

    本文实例讲述了Java实现读取及生成Excel文件的方法.分享给大家供大家参考,具体如下: 一.读取Excel文件 需要先下载poi-3.0.1-FINAL-20070705.jar(点击此处本站下载poi-3.0.1-FINAL-20070705.jar.) ExcelExamRead.java import java.io.File; import java.io.FileInputStream; import java.io.IOException; import org.apache.p

  • 简单的java读取文件示例分享

    可以作如下理解: 首先获得一个文件句柄.File file = new File(); file即为文件句柄.两人之间连通电话网络了.接下来可以开始打电话了 通过这条线路读取甲方的信息:new FileInputStream(file) 目前这个信息已经读进来内存当中了.接下来需要解读成乙方可以理解的东西 既然你使用了FileInputStream().那么对应的需要使用InputStreamReader()这个方法进行解读刚才装进来内存当中的数据 解读完成后要输出呀.那当然要转换成IO可以识别

  • Java读取文件及基于正则表达式的获取电话号码功能详解

    本文实例讲述了Java读取文件及基于正则表达式的获取电话号码功能.分享给大家供大家参考,具体如下: 1.正则表达式 正则表达式,又称 正规表示法 . 常规表示法 (英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表达式使用单个字符串来描述.匹配一系列符合某个句法规则的字符串.在很多文本编辑器里,正则表达式通常被用来检索.替换那些符合某个模式的文本. 用到的一些特殊构造正则表达式的意义解析: ? 当该字符 紧跟在任何一个其他限

  • java读取txt文件代码片段

    本文实例为大家分享了java读取txt文件的具体代码,供大家参考,具体内容如下 学习小记: 1.首先要根据路径获取你的 txt 文本文件.File file = new File(path); 2.将获取到的这个字节码流读进缓存.new FileInputStream(file) ; 3.然后对刚才读进缓存的输入流进行解读,生成对应字节流.InputStreamReader(readIn) 4.再然后通过 BufferedReader 这个类进行一行一行的输出.bufferedReader.re

  • Java读取txt文件的方法

    java读取txt文件内容.可以作如下理解: 首先获得一个文件句柄.File file = new File(); file即为文件句柄.两人之间连通电话网络了.接下来可以开始打电话了. 通过这条线路读取甲方的信息:new FileInputStream(file) 目前这个信息已经读进来内存当中了.接下来需要解读成乙方可以理解的东西 既然你使用了FileInputStream().那么对应的需要使用InputStreamReader()这个方法进行解读刚才装进来内存当中的数据 解读完成后要输出

随机推荐