作者:Carol卍_932 | 来源:互联网 | 2023-08-30 11:47
网上的文档很多,但是不够全面,最重要有些代码不能用!!!
参考文档:
java实现(RSA非对称加密) SHA1WithRSA加签验签 及openssl生成公私钥 感谢博主!!
使用 openssl 生成证书(含openssl详解)
一、数字签名流程
本地发送请求时(本地已对请求根据私钥进行加签) 接收方平台根据公钥进行验签 判断是否合法 接收来自平台的响应时(平台已根据私钥进行加签) 需要根据本地公钥对响应进行验签 判断是否合法 |
二、生成公钥和私钥
1、在Linxu上输入命令: openssl
2、输入命令:genrsa -out rsa_oo_private_key.pem 2048
3、私钥转换成PKCS8格式再做签名使用,输入命令:pkcs8 -topk8 -inform PEM -in rsa_oo_private_key.pem -outform PEM -nocrypt
注意:私钥就是输入pkcs8 -topk8 -inform PEM -in rsa_oo_private_key.pem -outform PEM -nocrypt打印出来的这块内容:
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCqrpUHZx/NSRsK
jQc9i/gCGzU9Q3qRf44pm0lML9FfJf+m9mo9qdAEsMl3N0Y/nVcdGWb8VBry+dyl
mKNR4VPfFNGQKWW8OtvUlT9l3I9/MTd/ZsoVt2dQdBvOp7+9hrClS+rmw/HFz81l
RCFcku8HIIIcFxPQylRgSxHI8PMVJEodBsQSRvOzGtzWTfhTfG0Y0sgZPt75hKjd
J1rTo4264AG3YzlxHlmqrrQxxmYEKEnNplmNVga2bXvPICZ2VPbl9w/52mlSobg3
6VPKMzdlhTUgFsADPMaG2Pf3GqOa2GTSupzgTyz/54LyF6gCbXcAknRFgH5eyAv5
tPqV9CsrAgMBAAECggEAAXIHCxABgfCLjRRSql/EEuh+E+29XPwSjSGmhkGlaUPe
HWDa13jXrSJ+IkdSjflcIn/zklF4BPS+vJxFTc01s57ug2UGWoi5EdzNs6Qhhvc4
vBh3v6VU96Z0EdTz17wLROsWqyufoYg3+hKQocMQySOqVmiPn2YHPuWD2grIVDZ9
68mC1FykGEcv9De0m6yVEsfZDXNUxm3cz1758iBqakvyOVxGsI+V+e7/iSxJiwIB
6f3NSGQVtEsqwyhnl6dZRYDtnq5iUiwUOshl5Z2CYBfBcyTpMKC2RuHp3u9THHpc
3TFE4I1Li5HkiFy+ai6QKl2M85ce3GCXmjyw7n2vmQKBgQDTHihNX6uu6YlVFcRa
XhhGigyLrIP8LbLd4r/dKMXuGa8XqkLPlDtXelh2n565Lo5DPGlpANi3Jp495Hzn
bL+YnHJs7boVOGtORB0XHUbiMaTlT85snpvVjwFngHvY/ZxtXclpsnX563AvzCyl
amrKEhV17BFZbRQOTEL1UNp57QKBgQDO98AyfVgs1tCdtLOsFSFiWrAsJJimBS7b
ec+W/UPGDAl3hFzQzJ2SUvF4EneatYVOEDdHLUzVnT7XXeA/eMZL56N8BTSffh8q
XK0E21K8tW4hRbze6CIjbsJ1x7ZLZaoM4Ub2YAvkulF0PcasX0kWl+bv/DnkI09x
/n3vgbO2dwKBgQCoAnj6UmeztEDJiKARdo6FHHmtciY7Ozb8Y+Zin38c5C22fJXc
0k+DZ2cdSBwtrQIkOeB9YuIUp1QJV1ubZKz5S4+4ZlvPZW3oBEbOTUtK2U0r/J3/
TR4hD0SD1Pk6j2G8m4Wdaxt+P8KxFyB0p8LCey++/5Yy/56VXlVvGuAzZQKBgQCU
VfcXeMTIplGwpkGcFSzvLCZWDQim/NH/lYdWJUD84cWrNl+7ett4cyADueClLnJT
Z8Xmqq4F8ASJIQxHEY21+1gt3CFCKoe1ueR7taHQBIzhJfVfIarOEGUpOzEJSt0d
DBzrGh2MGomksV4CTuy4V7i5yeHIBBK9lfO2xBQEswKBgQCIzYO53kTFl6YGjmWO
qUJsT+5WegR4GdxtqYpQGPC1RmU7ig1TZzen+X3xB+lIHqgA1HvTr6M+tPkmnMwU
iARPOgjXY0zmsStXaHQYKruT3EjZRs2GnmVpVOAj1asqi+/2t0NgLgB5gPLYMXS+
BGf01OehvUt5Ge+OChDBXSW5Bw==
4、生成公钥,输入命令:rsa -in rsa_oo_private_key.pem -pubout -out rsa_public_key.pem
接下来输入命令:cd ~/.ssh/,more rsa_public_key.pem ,得到公钥
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqq6VB2cfzUkbCo0HPYv4
Ahs1PUN6kX+OKZtJTC/RXyX/pvZqPanQBLDJdzdGP51XHRlm/FQa8vncpZijUeFT
3xTRkCllvDrb1JU/ZdyPfzE3f2bKFbdnUHQbzqe/vYawpUvq5sPxxc/NZUQhXJLv
ByCCHBcT0MpUYEsRyPDzFSRKHQbEEkbzsxrc1k34U3xtGNLIGT7e+YSo3Sda06ON
uuABt2M5cR5Zqq60McZmBChJzaZZjVYGtm17zyAmdlT25fcP+dppUqG4N+lTyjM3
ZYU1IBbAAzzGhtj39xqjmthk0rqc4E8s/+eC8heoAm13AJJ0RYB+XsgL+bT6lfQr
KwIDAQAB
三、代码实现
1、引入依赖
commons-codeccommons-codec1.11
2、具体代码
package com.cn.dl;import org.apache.commons.codec.binary.Base64;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;/*** SHA1WithRSA-数字签名* Created by yanshao on 2018/12/12.*/
// TODO: 2018/12/12 数字签名就发现这个能用
// TODO: 2018/12/12 原文地址:https://blog.csdn.net/qq_23974323/article/details/77678491
public class RSATest2 {//加密算法public static final String SIGN_ALGORITHMS = "SHA1WithRSA";//私钥private static final String privateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCqrpUHZx/NSRsK" +"jQc9i/gCGzU9Q3qRf44pm0lML9FfJf+m9mo9qdAEsMl3N0Y/nVcdGWb8VBry+dyl" +"mKNR4VPfFNGQKWW8OtvUlT9l3I9/MTd/ZsoVt2dQdBvOp7+9hrClS+rmw/HFz81l" +"RCFcku8HIIIcFxPQylRgSxHI8PMVJEodBsQSRvOzGtzWTfhTfG0Y0sgZPt75hKjd" +"J1rTo4264AG3YzlxHlmqrrQxxmYEKEnNplmNVga2bXvPICZ2VPbl9w/52mlSobg3" +"6VPKMzdlhTUgFsADPMaG2Pf3GqOa2GTSupzgTyz/54LyF6gCbXcAknRFgH5eyAv5" +"tPqV9CsrAgMBAAECggEAAXIHCxABgfCLjRRSql/EEuh+E+29XPwSjSGmhkGlaUPe" +"HWDa13jXrSJ+IkdSjflcIn/zklF4BPS+vJxFTc01s57ug2UGWoi5EdzNs6Qhhvc4" +"vBh3v6VU96Z0EdTz17wLROsWqyufoYg3+hKQocMQySOqVmiPn2YHPuWD2grIVDZ9" +"68mC1FykGEcv9De0m6yVEsfZDXNUxm3cz1758iBqakvyOVxGsI+V+e7/iSxJiwIB" +"6f3NSGQVtEsqwyhnl6dZRYDtnq5iUiwUOshl5Z2CYBfBcyTpMKC2RuHp3u9THHpc" +"3TFE4I1Li5HkiFy+ai6QKl2M85ce3GCXmjyw7n2vmQKBgQDTHihNX6uu6YlVFcRa" +"XhhGigyLrIP8LbLd4r/dKMXuGa8XqkLPlDtXelh2n565Lo5DPGlpANi3Jp495Hzn" +"bL+YnHJs7boVOGtORB0XHUbiMaTlT85snpvVjwFngHvY/ZxtXclpsnX563AvzCyl" +"amrKEhV17BFZbRQOTEL1UNp57QKBgQDO98AyfVgs1tCdtLOsFSFiWrAsJJimBS7b" +"ec+W/UPGDAl3hFzQzJ2SUvF4EneatYVOEDdHLUzVnT7XXeA/eMZL56N8BTSffh8q" +"XK0E21K8tW4hRbze6CIjbsJ1x7ZLZaoM4Ub2YAvkulF0PcasX0kWl+bv/DnkI09x" +"/n3vgbO2dwKBgQCoAnj6UmeztEDJiKARdo6FHHmtciY7Ozb8Y+Zin38c5C22fJXc" +"0k+DZ2cdSBwtrQIkOeB9YuIUp1QJV1ubZKz5S4+4ZlvPZW3oBEbOTUtK2U0r/J3/" +"TR4hD0SD1Pk6j2G8m4Wdaxt+P8KxFyB0p8LCey++/5Yy/56VXlVvGuAzZQKBgQCU" +"VfcXeMTIplGwpkGcFSzvLCZWDQim/NH/lYdWJUD84cWrNl+7ett4cyADueClLnJT" +"Z8Xmqq4F8ASJIQxHEY21+1gt3CFCKoe1ueR7taHQBIzhJfVfIarOEGUpOzEJSt0d" +"DBzrGh2MGomksV4CTuy4V7i5yeHIBBK9lfO2xBQEswKBgQCIzYO53kTFl6YGjmWO" +"qUJsT+5WegR4GdxtqYpQGPC1RmU7ig1TZzen+X3xB+lIHqgA1HvTr6M+tPkmnMwU" +"iARPOgjXY0zmsStXaHQYKruT3EjZRs2GnmVpVOAj1asqi+/2t0NgLgB5gPLYMXS+" +"BGf01OehvUt5Ge+OChDBXSW5Bw==";//公钥private static final String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqq6VB2cfzUkbCo0HPYv4" +"Ahs1PUN6kX+OKZtJTC/RXyX/pvZqPanQBLDJdzdGP51XHRlm/FQa8vncpZijUeFT" +"3xTRkCllvDrb1JU/ZdyPfzE3f2bKFbdnUHQbzqe/vYawpUvq5sPxxc/NZUQhXJLv" +"ByCCHBcT0MpUYEsRyPDzFSRKHQbEEkbzsxrc1k34U3xtGNLIGT7e+YSo3Sda06ON" +"uuABt2M5cR5Zqq60McZmBChJzaZZjVYGtm17zyAmdlT25fcP+dppUqG4N+lTyjM3" +"ZYU1IBbAAzzGhtj39xqjmthk0rqc4E8s/+eC8heoAm13AJJ0RYB+XsgL+bT6lfQr" +"KwIDAQAB";/*** 使用私钥给入参签名* @param privateKey 私钥* @param param 签名的数据* @return 返回入参签名16进制字符串* */public static String sign(String privateKey, String param) {try {//获取privatekeybyte[] privateKeyByte = new Base64().decode(privateKey);KeyFactory keyfactory = KeyFactory.getInstance("RSA");PKCS8EncodedKeySpec encoderule = new PKCS8EncodedKeySpec(privateKeyByte);PrivateKey key = keyfactory.generatePrivate(encoderule);//用私钥给入参加签Signature sign = Signature.getInstance(SIGN_ALGORITHMS);sign.initSign(key);sign.update(param.getBytes());byte[] signature = sign.sign();//将签名的入参转换成16进制字符串return bytesToHexStr(signature);} catch (Exception e) {e.printStackTrace();}return null;}/*** 用公钥验证签名* @param param 入参* @param signature 使用私钥签名的入参字符串* @param publicKey 公钥* @return 返回验证结果* */public static boolean verifyRes(String param,String signature,String publicKey){try {//获取公钥KeyFactory keyFactory=KeyFactory.getInstance("RSA");byte[] publicKeyByte= new Base64().decode(publicKey);X509EncodedKeySpec encodeRule=new X509EncodedKeySpec(publicKeyByte);PublicKey key= keyFactory.generatePublic(encodeRule);//用获取到的公钥对 入参中未加签参数param 与 入参中的加签之后的参数signature 进行验签Signature sign=Signature.getInstance(SIGN_ALGORITHMS);sign.initVerify(key);sign.update(param.getBytes());//将16进制码转成字符数组byte[] hexByte = hexStrToBytes(signature);//验证签名return sign.verify(hexByte);} catch (Exception e) {e.printStackTrace();}return false;}/*** byte数组转换成十六进制字符串* @param bytes byte数组* @return 返回十六进制字符串*/private static String bytesToHexStr(byte[] bytes) {StringBuffer stringBuffer = new StringBuffer("");for (int i = 0; i >>"+sign);System.out.println("验证结果>>>"+verifyRes(param,sign,publicKey));}}
3、运行结果
签名后的参数>>>27D167B2B5C0DB4ABBCA38ADBAB56648C372E4306DAF0D815AFD2092CD8F354D280D0F5C9E9FFAD0643C6833255B0FDDFCD366246744ECB079A26046215EEA887836E403A4DC7604F6B1EFE0A2131E2741CFB14DCE1E8BEB40F28D369B1AF19D20295D520620196F3822F2DBA94DFCFC6A7282F74A6B65DB56DFD522894C0C0E1C138CE3BC4EDCD0E47B62E81F857E881045F7EA62D9B9E10678C36183F9350E35BE2221F982AA4ABB4133137827080C35373DC563C0E08190433F012F575979627F91F45EA0A3244DA034A87931042F33EDB60CF7903D595D5C9A1C03B6FCE63A37B26C17EE319E5870EF4E6EFA44CFAA0E6E98CCC9158E0826BE87B4CFC6E1
验证结果>>>true