java读取证书公钥的实现

方式1:

使用javax.security.cert.X509Certificate进行解析

URL url = Demo.class.getClassLoader().getResource("C000024.crt");  //证书路径
System.out.println("公钥所在路径:"+url.getFile());
X509Certificate cert = X509Certificate.getInstance(new FileInputStream(url.getFile()));
PublicKey publicKey = cert.getPublicKey();
BASE64Encoder base64Encoder=new BASE64Encoder();
String publicKeyString = base64Encoder.encode(publicKey.getEncoded());
System.out.println("-----------------公钥--------------------");
System.out.println(publicKeyString);
System.out.println("-----------------公钥--------------------");

方式2:

使用java.security.cert.X509Certificate进行解析

URL url = Demo.class.getClassLoader().getResource("C000024.crt");  //证书路径
System.out.println("公钥所在路径:"+url.getFile());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(new FileInputStream(url.getFile()));
PublicKey publicKey = cert.getPublicKey();
BASE64Encoder base64Encoder=new BASE64Encoder();
String publicKeyString = base64Encoder.encode(publicKey.getEncoded());
System.out.println("-----------------公钥--------------------");
System.out.println(publicKeyString);
System.out.println("-----------------公钥--------------------");

说明:

因为只做示例,没有进行异常处理和流的释放,方式1的代码可能少点,方式2需要强转,美观上可能方式1更好看点,但方式1的实质还是调用的方式2,方式2内部有实现缓存策略。更多可以参考下api文档,文档上有提供示例。

补充:JAVA生成RSA公钥和私钥及RSA对数据的加签和验签

背景:

最近来到了新的公司,公司做的是保险支付相关业务,对接渠道的时候经常会用到数据的加签和验签,初次涉及RSA加签验签,通过网站生成了RSA公钥和私钥,用私钥将我要传送的数据进行了加签,并将我的公钥提供给了渠道方进行验签,结果在联调的时候,验签总是错误,渠道方用自己的私钥对数据加签后再用自己的公钥对数据进行验签却能通过,于是我也用自己的私钥对数据进行加签后再用自己的公钥对数据进行验签,结果让我惊讶,居然没有通过!

到了这里,产生错误的原因基本上已经一目了然了,我通过网站生成的公私钥是无法配对的,这当中可能涉及到了网站生成公私钥的时候已经对公私钥进行了处理,比如说PKCS8的处理,所以决定自己用Java来生成RSA公钥和私钥进行验证测试,文档写出来了,测试结果自然已经知道了,是通过的。

以下为完整的验签过程:

启动类:ZhongbaohuiApplication.java

package com.test.zhongbaohui;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ZhongbaohuiApplication {

  public static void main(String[] args) {
    SpringApplication.run(ZhongbaohuiApplication.class, args);
  }
}

请求Controller:RequestController.java

package com.test.zhongbaohui.controller;
import com.alibaba.fastjson.JSONObject;
import com.test.zhongbaohui.utils.RSASignUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: zhongbaohui
 * @package: com.test.zhongbaohui.controller
 * @description:
 * @auther: chengjunyu
 * @createDate: 2019/12/6 22:05
 */
@RestController
@RequestMapping(value="/test")
@Slf4j
public class RequestController {

  @Autowired
  private ResponseController responseController;
  @PostMapping("/getJsonObject")
  private String getJsonObject(HttpServletRequest request, HttpServletResponse response) {

    JSONObject jsonObject = new JSONObject();
    jsonObject.put("signType", "RSA");
    jsonObject.put("enterpriseId", "201975538583911110");
    jsonObject.put("nonce", "b0eed33073664f5fa983c5b774dbd4b6");
    jsonObject.put("timestamp", "2019-12-07 01:19:25");
    Map<String, Object> map = new HashMap<>();
    map.put("bankCode", "其他");
    map.put("batchNo", "201975538583911110b1084fa29f6c");
    map.put("bankCardNumber", "6217856100077026406");
    map.put("paymentNote", "佣金发放");
    map.put("idCardNumber", "320123199103104650");
    map.put("mobile", "15365176555");
    map.put("bankName", "中国银行");
    map.put("outEnterpriseOrderNo", "T20191207011545663692017");
    map.put("realPayment", "1.00");
    map.put("serviceId", "201968613430727001");
    map.put("userName", "程俊予");
    jsonObject.put("data", map);
    //私钥内容
    String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgFnOID56YNquwenrgnW1Ud+GBcSFojPOY00+TYq/qHVaprGPeuKlAcBebkyj4+G3H4t7e1DTOblQtZk/yi+2VcbDnhHQl3UVdkLkVMRXXCBPBJtjSo3RMMJFC6OCiKfzhujhhio7MJWWrMYLtAgMBAAECgYBplZud/CZv1KLzIA5bdbF2yk36FYoc3hl3iXLeiyp91NGc6hqhFSEyXPhvrZP0aAym9IC824Bjq4Gg7pkkHzYT3IGDCqqyodBYcdof8Jsk9t0G0Ll7G1dlQwl9R6+SAvauF5RUbwz5Byos6cnFbybfqAdRUdF96yH0Hw0QF1u8XQJBAPrpHvZpeOZNSY/M1wlJZv5gV1OoI9s+PZgJQHgWbT7FaiPDkZiAa7B6hGNBgUa7m4vEzGJNAOHxhdl1QMtlTjMCQQD3VInIf9EjKZn7LNcPQsl1AkXbwuXjtMceeuX43lcdapgQ+4Y6G5QU3fhwZxwsdZnUbLqJWzFgXw/F2E2DxopfAkBxGErgfsID7KpPquDySqel2P8DsjIXTIKu2Ny6REGRnaIt5KTnvFrN/StXIduHamC+K0KEvHi9XwQZ9IP0KgGJAkEA3hUzzywuP3OYhzhhN5vRx1YuIkGkKU3nSdAy9b+323seZoljooOm+QHDljKP0sAaS+sBqFqRQKa7Q/yQxdWd4wJBAIUXethFnMr3U9FetKHmWKwOPh23EHM0xPdVzMcb24WwK7QAXCMo71ugG6qqmBA+wYCrjPwbMu5XysB5+d5ZNC0=";
    String sign = RSASignUtils.sign(jsonObject, privateKey);
    log.info("验签sign为:{}", sign);
    jsonObject.put("sign", sign);
    String message = responseController.returnMsg(jsonObject.toJSONString());
    return message;
  }
}

响应Controller:ResponseController.java

package com.test.zhongbaohui.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.test.zhongbaohui.utils.RSASignUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @program: zhongbaohui
 * @package: com.test.zhongbaohui.controller
 * @description:
 * @auther: chengjunyu
 * @createDate: 2019/12/7 20:46
 */
@RestController
@Slf4j
public class ResponseController {
  @PostMapping("/returnMsg")
  public String returnMsg(String message) {
    JSONObject jsonObject = JSONObject.parseObject(message);
    log.info("接受请求内容为:{}", jsonObject.toJSONString());
    String sign = jsonObject.getString("sign");
    jsonObject.remove("sign");
    String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD5gn/eAnLyf6xZziA+emDarsHp64J1tVHfhgXEhaIzzmNNPk2Kv6h1Wqaxj3ripQHAXm5Mo+Phtx+Le3tQ0zm5ULWZP8ovtlXGw54R0Jd1FXZC5FTEV1wgTwSbY0qN0TDCRQujgoin84bo4YYqOzCVlqzGC7QIDAQAB";
    boolean flag = RSASignUtils.verify(jsonObject, publicKey, sign);
    JSONObject object = new JSONObject();
    if(flag) {
      object.put("code", "200");
      object.put("status", "success");
      object.put("message:", "验签成功");
    }else {
      object.put("code", "400");
      object.put("status", "failure");
      object.put("message:", "验签失败");
    }
    return object.toJSONString();
  }
}

RSA工具类:RSASignUtils.java

package com.test.zhongbaohui.utils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: zhongbaohui
 * @package: com.test.zhongbaohui.controller
 * @description:
 * @auther: chengjunyu
 * @createDate: 2019/12/6 23:03
 */
@Slf4j
@Component
public class RSASignUtils {
  public static final String KEY_ALGORITHM = "RSA";
  private static final String PUBLIC_KEY = "RSAPublicKey";
  private static final String PRIVATE_KEY = "RSAPrivateKey";
  public static final String SIGNATURE_ALGORITHM="MD5withRSA";
  public static final Integer RSA_KEY_SIZE = 1024;

  /*
   * @function: 使用字符串格式的私钥为JSONObject格式的内容加签
   * @param: [jsonObject, privateKey]
   * @return: java.lang.String
   * @auther: chengjunyu
   * @date: 2019/12/7 21:06
   */
  public static String sign(JSONObject jsonObject, String privateKey) {
    String signMsg = "";
    String data = jsonObject.toString();
    log.info("加签对象内容为:{}", data);
    try {
      byte[] keyBytes = decryptBASE64(privateKey);
      PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      PrivateKey key = keyFactory.generatePrivate(keySpec);
      Signature signature = Signature.getInstance("MD5withRSA");
      signature.initSign(key);
      signature.update(data.getBytes("ISO-8859-1"));
      signMsg = Base64.encodeBase64String(signature.sign());
    } catch (Exception var8) {
      var8.printStackTrace();
    }
    return signMsg;
  }

  /*
   * @function: 使用字符串格式的公钥为JSONObject格式的内容验签
   * @param: [jsonObject, publicKey, sign]
   * @return: boolean
   * @auther: chengjunyu
   * @date: 2019/12/8 14:56
   */
  public static boolean verify(JSONObject jsonObject, String publicKey, String sign) {
    String s = jsonObject.toJSONString();
    log.info("s:{}",s);
    boolean rs = false;
    try {
      byte[] keyBytes = decryptBASE64(publicKey);
      X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      PublicKey key = keyFactory.generatePublic(keySpec);
      Signature signature = Signature.getInstance("MD5withRSA");
      signature.initVerify(key);
      signature.update(s.getBytes("ISO-8859-1"));
      return signature.verify(Base64.decodeBase64(sign.getBytes()));
    } catch (Exception var9) {
      var9.printStackTrace();
      return rs;
    }
  }

  /*
   * @function: 获取PublicKey格式的公钥,本例中未使用
   * @param: [key]
   * @return: java.security.PublicKey
   * @auther: chengjunyu
   * @date: 2019/12/8 16:10
   */
  public static PublicKey getPublicKey(String key) {
    PublicKey publicKey = null;
    try {
      byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key);
      X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
      // RSA对称加密算法
      KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
      // 取公钥匙对象
      publicKey = keyFactory.generatePublic(keySpec);
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (InvalidKeySpecException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return publicKey;
  } 

  /*
   * @function: 获取PublicKey格式的私钥,本例中未使用
   * @param: [key]
   * @return: java.security.PrivateKey
   * @auther: chengjunyu
   * @date: 2019/12/8 16:10
   */
  public static PrivateKey getPrivateKey(String key) {
    PrivateKey privateKey = null;
    try {
      byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key);
      PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
      KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
      privateKey = keyFactory.generatePrivate(keySpec);
    } catch (IOException e) {
      e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (InvalidKeySpecException e) {
      e.printStackTrace();
    }
    return privateKey;
  }

  /*
   * @function: 初始化公钥和私钥
   * @param: []
   * @return: java.util.Map<java.lang.String,java.lang.Object>
   * @auther: chengjunyu
   * @date: 2019/12/8 14:34
   */
  public static Map<String, Object> initKey() {
    KeyPairGenerator keyPairGen = null;
    try {
      keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    }
    keyPairGen.initialize(RSA_KEY_SIZE);
    KeyPair keyPair = keyPairGen.generateKeyPair();
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    Map<String, Object> keyMap = new HashMap<String, Object>(2);
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;
  }

  //获得公钥字符串
  public static String getPublicKeyStr(Map<String, Object> keyMap) {
    //获得map中的公钥对象 转为key对象
    Key key = (Key) keyMap.get(PUBLIC_KEY);
    //编码返回字符串
    return encryptBASE64(key.getEncoded());
  }

  //获得私钥字符串
  public static String getPrivateKeyStr(Map<String, Object> keyMap) {
    //获得map中的私钥对象 转为key对象
    Key key = (Key) keyMap.get(PRIVATE_KEY);
    //编码返回字符串
    return encryptBASE64(key.getEncoded());
  }

  //编码返回字符串
  public static String encryptBASE64(byte[] key) {
    return (new BASE64Encoder()).encodeBuffer(key);
  }

  //解码返回byte
  public static byte[] decryptBASE64(String key) {
    byte[] bytes = null;
    try {
      return (new BASE64Decoder()).decodeBuffer(key);
    } catch (IOException e) {
      return bytes;
    }
  }

  public static void main(String[] args) {
    Map<String, Object> keyMap = initKey();
    String publicKey = getPublicKeyStr(keyMap);
    log.info("JAVA生成RSA公钥:{}", publicKey);
    String privateKey = getPrivateKeyStr(keyMap);
    log.info("JAVA生成RSA私钥:{}", privateKey);
  }
}

注意:

本文中请求和响应类中的私钥和公钥均是不完整的,在请求和响应类中的私钥和公钥由RSASignUtils工具类生成后,再替代入请求和响应类中,请求类中使用私钥加签,响应类中使用公钥验签。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • Java 自动安装校验TLS/SSL证书

    前言 最近实现Socks5 proxy与HTTP proxy中遇到了SSLSocket隧道的问题,当然,最终问题经过自动证书校验安装管理器实现了证书的管理,也解决了SSLSocket,但是目前的问题是浏览器对Socks5和HTTP proxy还有很多不足,目前实现的两个代理工具只能在程序中使用.当然,我们今天的主要话题如下: Java 实现TLS/SSL证书的自动安装校验,主要经过ssl/tls握手,密钥交换,证书校验机制实现.我们这里模拟浏览器,实现自动校验和证书的检测. 主要实现如下功能:

  • 纯Java实现数字证书生成签名的简单实例

    package com.ylsoft.cert; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator;

  • Java如何跳过https的ssl证书验证详解

    打开我们首页,明显看到链接是https打头,https和http的通信协议差别,在于https安全性更高: http和https的差别 很明显,二者最大的区别在于https多了一个ssl证书验证,可以说https是身披SSL外壳的http.因为http存在如下缺陷: 1)通信使用明文,内容可能被窃听(重要密码泄露) 2)不验证通信方身份,有可能遭遇伪装(跨站点请求伪造) 3)无法证明报文的完整性,有可能已遭篡改(运营商劫持) 而https是利用SSL/TLS建立全信道,加密数据包.HTTPS使用

  • 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读取证书公钥的实现

    方式1: 使用javax.security.cert.X509Certificate进行解析 URL url = Demo.class.getClassLoader().getResource("C000024.crt"); //证书路径 System.out.println("公钥所在路径:"+url.getFile()); X509Certificate cert = X509Certificate.getInstance(new FileInputStream

  • 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制作证书的工具keytool用法详解

    目录 一.keytool的概念 二.keytool的用法 三.创建证书 四.查看密钥库里面的证书 五.导出到证书文件 六.导入证书 七.查看证书信息 八.删除密钥库中的条目 九.修改证书条目的口令 一.keytool的概念 keytool 是个密钥和证书管理工具.它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务.在JDK 1.4以后的版本中都包含了这一工具,它的位置为%JAVA_HOME%\bin\keytool.

  • Java读取Properties文件的七种方法的总结

    Java读取Properties文件的方法总结 读取.properties配置文件在实际的开发中使用的很多,总结了一下,有以下几种方法: 其实很多都是大同小异,概括起来就2种: 先构造出一个InputStream来,然后调用Properties#load() 利用ResourceBundle,这个主要在做国际化的时候用的比较多. 例如:它能根据系统语言环境自动读取下面三个properties文件中的一个: resource_en_US.properties resource_zh_CN.prop

  • Java读取txt文件和写入txt文件的简单实例

    写Java程序时经常碰到要读如txt或写入txt文件的情况,但是由于要定义好多变量,经常记不住,每次都要查,特此整理一下,简单易用,方便好懂! package edu.thu.keyword.test; import java.io.File; import java.io.InputStreamReader; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream;

  • Java读取Map的两种方法与对比

    前言 在java中遍历Map有不少的方法.这篇文章我们就来看一下Java读取Map的两种方法以及这两种方法的对比. 一. 遍历Map方法A Map map = new HashMap(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); Object key = entry.getKey(); Object val = en

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

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

  • java读取resource目录下文件的方法示例

    本文主要介绍的是java读取resource目录下文件的方法,比如这是你的src目录的结构 ├── main │ ├── java │ │ └── com │ │ └── test │ │ └── core │ │ ├── bean │ │ ├── Test.java │ └── resources │ └── test │ ├── test.txt └── test └── java 我们希望在Test.java中读取test.txt文件中的内容,那么我们可以借助Guava库的Resource

  • Java 读取外部资源的方法详解及实例代码

    Java 读取外部资源的方法详解 在Java代码中经常有读取外部资源的要求:如配置文件等等,通常会把配置文件放在classpath下或者在web项目中放在web-inf下. 1.从当前的工作目录中读取: try { BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("wkdir.txt"))); String str; while ((str = in.readLine())

  • java读取properties配置文件的方法

    本文实例讲述了java读取properties配置文件的方法.分享给大家供大家参考.具体分析如下: 这两天做java项目,用到属性文件,到网上查资料,好半天也没有找到一个满意的方法能让我读取到.properties文件中属性值,很是郁闷,网上讲的获取属性值大概有以下方法,以下三种方法逐渐优化,以达到最好的效果以下都以date.properties文件为例,该文件放在src目录下,文件内容为: startdate=2011-02-07 totalweek=25 方法一: public class

随机推荐