java讀取證書公鑰的實(shí)現(xiàn)
方式1:
使用javax.security.cert.X509Certificate進(jìn)行解析
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進(jìn)行解析
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("-----------------公鑰--------------------");
說明:
因?yàn)橹蛔鍪纠瑳]有進(jìn)行異常處理和流的釋放,方式1的代碼可能少點(diǎn),方式2需要強(qiáng)轉(zhuǎn),美觀上可能方式1更好看點(diǎn),但方式1的實(shí)質(zhì)還是調(diào)用的方式2,方式2內(nèi)部有實(shí)現(xiàn)緩存策略。更多可以參考下api文檔,文檔上有提供示例。
補(bǔ)充:JAVA生成RSA公鑰和私鑰及RSA對數(shù)據(jù)的加簽和驗(yàn)簽
背景:
最近來到了新的公司,公司做的是保險(xiǎn)支付相關(guān)業(yè)務(wù),對接渠道的時候經(jīng)常會用到數(shù)據(jù)的加簽和驗(yàn)簽,初次涉及RSA加簽驗(yàn)簽,通過網(wǎng)站生成了RSA公鑰和私鑰,用私鑰將我要傳送的數(shù)據(jù)進(jìn)行了加簽,并將我的公鑰提供給了渠道方進(jìn)行驗(yàn)簽,結(jié)果在聯(lián)調(diào)的時候,驗(yàn)簽總是錯誤,渠道方用自己的私鑰對數(shù)據(jù)加簽后再用自己的公鑰對數(shù)據(jù)進(jìn)行驗(yàn)簽卻能通過,于是我也用自己的私鑰對數(shù)據(jù)進(jìn)行加簽后再用自己的公鑰對數(shù)據(jù)進(jìn)行驗(yàn)簽,結(jié)果讓我驚訝,居然沒有通過!
到了這里,產(chǎn)生錯誤的原因基本上已經(jīng)一目了然了,我通過網(wǎng)站生成的公私鑰是無法配對的,這當(dāng)中可能涉及到了網(wǎng)站生成公私鑰的時候已經(jīng)對公私鑰進(jìn)行了處理,比如說PKCS8的處理,所以決定自己用Java來生成RSA公鑰和私鑰進(jìn)行驗(yàn)證測試,文檔寫出來了,測試結(jié)果自然已經(jīng)知道了,是通過的。
以下為完整的驗(yàn)簽過程:
啟動類: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", "傭金發(fā)放");
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);
//私鑰內(nèi)容
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("驗(yàn)簽sign為:{}", sign);
jsonObject.put("sign", sign);
String message = responseController.returnMsg(jsonObject.toJSONString());
return message;
}
}
響應(yīng)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("接受請求內(nèi)容為:{}", 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:", "驗(yàn)簽成功");
}else {
object.put("code", "400");
object.put("status", "failure");
object.put("message:", "驗(yàn)簽失敗");
}
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格式的內(nèi)容加簽
* @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("加簽對象內(nèi)容為:{}", 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格式的內(nèi)容驗(yàn)簽
* @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中的公鑰對象 轉(zhuǎn)為key對象
Key key = (Key) keyMap.get(PUBLIC_KEY);
//編碼返回字符串
return encryptBASE64(key.getEncoded());
}
//獲得私鑰字符串
public static String getPrivateKeyStr(Map<String, Object> keyMap) {
//獲得map中的私鑰對象 轉(zhuǎn)為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);
}
}
注意:
本文中請求和響應(yīng)類中的私鑰和公鑰均是不完整的,在請求和響應(yīng)類中的私鑰和公鑰由RSASignUtils工具類生成后,再替代入請求和響應(yīng)類中,請求類中使用私鑰加簽,響應(yīng)類中使用公鑰驗(yàn)簽。
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
springboot rabbitmq整合rabbitmq之消息持久化存儲問題
這篇文章主要介紹了springboot rabbitmq整合rabbitmq之消息持久化存儲問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09
springcloud整合到項(xiàng)目中無法啟動報(bào)錯Failed to start bean&n
這篇文章主要介紹了springcloud整合到項(xiàng)目中無法啟動報(bào)錯Failed to start bean 'eurekaAutoServiceRegistration'問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
詳解Java中NullPointerException異常的原因和解決辦法
本文主要介紹了詳解Java中NullPointerException異常的原因和解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
SpringBoot實(shí)現(xiàn)Server-Sent Events(SSE)的使用完整指南
使用SpringBoot實(shí)現(xiàn)Server-Sent Events(SSE)可以有效處理實(shí)時數(shù)據(jù)推送需求,具有單向通信、輕量級和高實(shí)時性等優(yōu)勢,本文詳細(xì)介紹了在SpringBoot中創(chuàng)建SSE端點(diǎn)的步驟,并通過代碼示例展示了客戶端如何接收數(shù)據(jù),適用于實(shí)時通知、數(shù)據(jù)展示和在線聊天等場景2024-09-09

