RSA算法加密解密与签名验签

RSA算法加密解密与签名验签

rsa有一对公钥和私钥,具体生成过程可以造网上找
1.加密解密:加密使用公钥加密,私钥解密
2.签名验签:使用私钥签名,公钥验签
举例说明:
A向B发消息,A有一对公钥和私钥,B也有一对公钥和私钥,各自保留自己的私钥,把公钥交给对方。
加密解密:A用B的公钥把信息加密发给B,B用自己的私钥解密信息。但是这其中存在一个问题,B的公钥是公开的,假如被C知道了,C假冒A给B发消息,这个时候B是不能区分的,此时就有了签名
签名验签:A先按照一定的规则对信息提取摘要,然后用A的私钥加密摘要,再将信息与摘要一起用B的公钥加密发送给B。B再接收到A的消息后,先用自己的私钥解密A发过来的密文,拿出信息,用和A同样的规则提取摘要,再用A的公钥解密A发过来的摘要,再和自己提取出来的摘要对比,如果一样说明此消息是从A发过来的,验签通过。

生成秘钥对


```java
package com.toonyoo.tool;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;

/**
 * @ClassName GeneratorRSAKey
 * @Description
 * @Author Administrator
 * @Date 2020-06-03 10:41
 **/
public class GeneratorRSAKey {
    private static final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCazYW17+RwTJlXVxd8vBfPO+ORVKp3nl2UNV+C1MCJP5oXBmcarQ6yqkbgfs72GFuRekdgQQzbtmCj+E9BLWJ7Lsc/SjZ6zHo6e0XfAJySJAstuO27H33dU0jeFQk8bt+GhSjIECSmruLoZVqYe2vV/oRkSa16s9HagI2LMhMXbwIDAQAB";
    private static final String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJrNhbXv5HBMmVdXF3y8F88745FUqneeXZQ1X4LUwIk/mhcGZxqtDrKqRuB+zvYYW5F6R2BBDNu2YKP4T0EtYnsuxz9KNnrMejp7Rd8AnJIkCy247bsffd1TSN4VCTxu34aFKMgQJKau4uhlWph7a9X+hGRJrXqz0dqAjYsyExdvAgMBAAECgYEAiKXhYR/Y29SSC4oifoYe0l0AXdqJ+7t8yYZvwDKDnuPY5nhNbTvUXJx4olTt5kjME9gHx4zEh/Iuzq8zbspcQg5GkCifyMxplUBhSBSePGbfq6gOwY3BZ55SYk5Ib0FX2Wq//4WCf2+aCJNrGRiG/c+rHfdpQI47bqd8quMcqOkCQQD5M1T2lFGqpyH0Fh3WZgy8f7v1qP3rS1TefH1rRHiv94gtTjQKodossdESUkNMyW7AZ38l7gXtvwlGo2Eydm1LAkEAnwbSUuPoaKpRxsu+bjsQz1GfdUub0FSeTxQJLwHGwFtycYf8XVUlC/eSc9QwVMG7YBOIdg4OVoPnHQoCohsb7QJAECUpPgiB+gJ2CrBcIoXeEWBdNx9JxDLPPtLl9UssXoo1AmpsqLuvvPGQUBWQUqtCR6js7fIr5ClaWn8/TtupXQJAAsajtT61N96BPu8fi90MFhJerjV7qs9PVCINZvyo84KlJMYy6Y4q72KK8+qoTVJ0auDsaOMl7OywhBlAooPGoQJAJpWA1vwsSO6F5ZhO1ATgTmAEaW8cYAeO0ZvyjrN+l9NM3D9EONUq7OuEnc58pKcW71dzYirjA4UPOuNl4r/x1A==";
//    public static void main(String[] args) {
//        jdkRSA();
//    }

    public static void jdkRSA() {
        GeneratorRSAKey generatorKey = new GeneratorRSAKey();

        try {
            // 初始化密钥,产生公钥私钥对
            Object[] keyPairArr = generatorKey.initSecretkey();
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPairArr[0];
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPairArr[1];

            System.out.println("------------------PublicKey------------------");
            System.out.println(Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded()));

            System.out.println("\n------------------PrivateKey------------------");
            System.out.println(Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化密钥,生成公钥私钥对
     *
     * @return Object[]
     * @throws NoSuchAlgorithmException NoSuchAlgorithmException
     */
    private Object[] initSecretkey() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

        Object[] keyPairArr = new Object[2];
        keyPairArr[0] = rsaPublicKey;
        keyPairArr[1] = rsaPrivateKey;

        return keyPairArr;
    }
}

提取信息摘要并且对其加密
public void sender(CheckCodeDTO checkCodeDTO){

   Map condition = new HashMap();
   condition.put("configType","0");
   condition.put("configKey",checkCodeDTO.getShopId());
   condition.put("configStatus",1);
   Config config = configService.queryConfig(condition);
   if(config == null || StringUtils.isBlank(config.getConfigValue())){
      log.error("新电子码核销时调用第三方接口失败:未查询对应门店映射关系.shopId:>>>>>>>>>>>>>>>>>>>>>>>>>>",checkCodeDTO.getShopId());
      return;
   }

   Map<String, Object> body = new HashMap<>();
   body.put("source",1);//核销来源 (0线上,1线下)
   body.put("code",checkCodeDTO.getCode());
   body.put("outerType",1);//外部券码类型(1:外部导入券码, 2:微信代金券)
   body.put("storeId",config.getConfigValue());//门店ID
   body.put("orderNo",UUID.randomUUID().toString());//批次号(渠道唯一,限长40

   Map<String, Object> headerParam = new HashMap<>();
   headerParam.put("appId",appId);
   headerParam.put("timestamp",String.valueOf(new Date().getTime()));
   headerParam.put("bizContent",JSONUtil.toStr(body));

   StringBuilder sb = new StringBuilder();
   headerParam.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEach(entry ->
         sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&")
   );
   String paramStr = sb.toString().substring(0, sb.length() - 1);

   // 使用私钥生成签名字符串
   String sign = JdkSignatureUtil.executeSignature(privateKey, paramStr);
   if(sign == null){
       log.error("加签后sign为null");
       return;
       }
   // 请求参数中需带上签名字符串
   headerParam.put("sign", sign);
   headerParam.remove("bizContent");
   // 发送请求
   postJson(thirdPartUrl, headerParam,body);
}


私钥加签
package com.toonyoo.tool;

import lombok.extern.slf4j.Slf4j;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @author 01
 * @program demo
 * @description RSA签名工具类
 * @create 2018-12-15 21:26
 * @since 1.0
 **/
@Slf4j
public class JdkSignatureUtil {

    private final static String RSA = "RSA";

    private final static String SHA1_With_RSA = "SHA1WithRSA";

    /**
     * 执行签名
     *
     * @param rsaPrivateKey 私钥
     * @param src           参数内容
     * @return 签名后的内容,base64后的字符串
     */
    public static String executeSignature(String rsaPrivateKey, String src) {
        // base64解码私钥
        byte[] decodePrivateKey = Base64.getDecoder().decode(rsaPrivateKey.replace("\r\n", ""));
        String content = null;
        try {
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decodePrivateKey);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Signature signature = Signature.getInstance(SHA1_With_RSA);
            signature.initSign(privateKey);
            signature.update(src.getBytes());
            // 生成签名并base64编码签名为字符串
            content = Base64.getEncoder().encodeToString(signature.sign());
        } catch (Exception e) {
            log.error("新电子码对接万达小程序加签失败",e);
        }
        return content;
    }

    /**
     * 验证签名
     *
     * @param rsaPublicKey 公钥
     * @param sign         签名
     * @param src          参数内容
     * @return 验证结果
     * @throws NoSuchAlgorithmException NoSuchAlgorithmException
     * @throws InvalidKeySpecException  InvalidKeySpecException
     * @throws InvalidKeyException      InvalidKeyException
     * @throws SignatureException       SignatureException
     */
    public static boolean verifySignature(String rsaPublicKey, String sign, String src) throws NoSuchAlgorithmException,
            InvalidKeySpecException, InvalidKeyException, SignatureException {
        // base64解码公钥
        byte[] decodePublicKey = Base64.getDecoder().decode(rsaPublicKey.replace("\r\n", ""));

        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decodePublicKey);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Signature signature = Signature.getInstance(SHA1_With_RSA);
        signature.initVerify(publicKey);
        signature.update(src.getBytes());
        // base64解码签名为字节数组
        byte[] decodeSign = Base64.getDecoder().decode(sign);

        // 验证签名
        return signature.verify(decodeSign);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值