SHA1WithRSA-数字签名

版权声明:转发请注明,谢谢配合 https://blog.csdn.net/qq_31289187/article/details/84973338

网上的文档很多,但是不够全面,最重要有些代码不能用!!!

参考文档:

      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、引入依赖

 <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.11</version>
</dependency>

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 {
            //获取privatekey
            byte[] 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 < bytes.length; ++i) {
            stringBuffer.append(Integer.toHexString(0x0100 + (bytes[i] & 0x00FF)).substring(1).toUpperCase());
        }
        return stringBuffer.toString();
    }
    /**
     * 十六进制字符串转成byte数组
     * @param hexStr   十六进制字符串
     * @return          返回byte数组
     * */
    private static byte[] hexStrToBytes(String hexStr) {
        byte[] bytes = new byte[hexStr.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt(hexStr.substring(2 * i, 2 * i + 2), 16);
        }
        return bytes;
    }

    public static void main(String[] args) {
        String param = "yanshao";
        String sign = sign(privateKey,param);
        System.out.println("签名后的参数>>>"+sign);
        System.out.println("验证结果>>>"+verifyRes(param,sign,publicKey));
    }

}

3、运行结果

签名后的参数>>>27D167B2B5C0DB4ABBCA38ADBAB56648C372E4306DAF0D815AFD2092CD8F354D280D0F5C9E9FFAD0643C6833255B0FDDFCD366246744ECB079A26046215EEA887836E403A4DC7604F6B1EFE0A2131E2741CFB14DCE1E8BEB40F28D369B1AF19D20295D520620196F3822F2DBA94DFCFC6A7282F74A6B65DB56DFD522894C0C0E1C138CE3BC4EDCD0E47B62E81F857E881045F7EA62D9B9E10678C36183F9350E35BE2221F982AA4ABB4133137827080C35373DC563C0E08190433F012F575979627F91F45EA0A3244DA034A87931042F33EDB60CF7903D595D5C9A1C03B6FCE63A37B26C17EE319E5870EF4E6EFA44CFAA0E6E98CCC9158E0826BE87B4CFC6E1
验证结果>>>true

猜你喜欢

转载自blog.csdn.net/qq_31289187/article/details/84973338