RSA加签解签方法

1 篇文章 0 订阅

一、RSA签名的过程

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。

(2)A用自己的私钥对消息加签,形成签名,并将加签的消息和消息本身一起传递给B。

(3)B收到消息后,在获取A的公钥进行验签,如果验签出来的内容与消息本身一致,证明消息是A回复的。

  在这个过程中,只有2次传递过程,第一次是A传递加签的消息和消息本身给B,第二次是B获取A的公钥,即使都被敌方截获,也没有危险性,因为只有A的私钥才能对消息进行签名,即使知道了消息内容,也无法伪造带签名的回复给B,防止了消息内容的篡改。

二、具体使用方法

1.通过RSA秘钥生成工具生成一对公钥和私钥

 

2.定义加密解密和加签验签方法名

//加密解密算法
private static final String ALGORITHM_RSA = "RSA";
​
//加签验签算法
private static final String ALGORITHM_SHA1WITHRSA = "SHA1withRSA";
​
private static final String CHARSET = "UTF-8";

 

3.加密解密方法

(1)初始化公钥私钥

/**
 * 初始化公钥私钥,将公钥私钥放入map中
 * @return
 * @throws NoSuchAlgorithmException
 */
public static Map<String, Object> initKey() throws NoSuchAlgorithmException {
   //获得对象 KeyPairGenerator 参数 RSA 1024个字节
   KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM_RSA);
   keyPairGenerator.initialize(1024);
   KeyPair keyPair = keyPairGenerator.generateKeyPair();
   RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
   RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
   //将公私钥对象存入map中,PUBLIC_KEY和PRIVATE_KEY为你自动生成的公私钥
   Map<String, Object> keyMap = new HashMap<>(2);
   keyMap.put(PUBLIC_KEY,rsaPublicKey);
   keyMap.put(PRIVATE_KEY,rsaPrivateKey);
   return keyMap;
}

(2)获取规范公钥和规范私钥

public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
   Key key = (Key) keyMap.get(PUBLIC_KEY);
   return Base64.encodeBase64String(key.getEncoded());
}
​
/**
 * 将原始私钥进行处理,获取规范私钥
 * @param keyMap
 * @return 返回规范私钥
 * @throws Exception
 */
public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
   Key key = (Key) keyMap.get(PRIVATE_KEY);
​
   return Base64.encodeBase64String(key.getEncoded());
}

(3)键值对转换成url方法

加签过程中需要通过formatSignContent()函数进行格斯转换,将键值对格式转换为url参数格式

/**
 * 格式转换,将map中键值对转换为url参数格式
 * @param params 传递参数的键值对,用map保存
 * @return 参数的url表示方法,例如:key1=111&key2=222
 */
private static String formatSignContent(Map<String, String> params) {
   //利用TreeMap将键值对排序
   Map<String, String> sortedParams = new TreeMap<String, String>();
   sortedParams.putAll(params);
   StringBuilder content = new StringBuilder();
   int index = 0;
   for (Object key : sortedParams.keySet()){
      Object value = sortedParams.get(key.toString());
      if (value != null && StringUtils.isNotBlank(value.toString())) {
         content.append(index == 0 ? "" : "&").append(key).append("=").append(value);
         index++;
      }
   }
   return content.toString();
}

(4)加签方法

A通过自己的私钥对原始数据进行加签,生成加签数据sign,期间需要格式转换

/**
 * RSA加签方法
 * @param paramsMap 原始数据键值对格式
 * @param privateKey 私钥
 * @return 返回加签数据
 * @throws Exception
 */
private static String signWithRSA(Map<String,String> paramsMap, String privateKey) throws Exception {
   //将Map键值对转换为url参数格式
   String content = formatSignContent(paramsMap);
   //指定加签算法
   Signature signature = Signature.getInstance(ALGORITHM_SHA1WITHRSA);
   signature.initSign(getPrivateKey(privateKey));
   signature.update(content.getBytes("utf-8"));
   byte[] signed = signature.sign();
   return Base64.encodeBase64String(signed);
}

(5)验签方法

B通过A的公钥和加签数据sign以及传递的参数map进行解签

/**
 * RSA验签方法
 * 将传递的Map键值对转换为url参数形式
 * @param paramsMap 传递过来的键值对
 * @param publicKey 规范公钥
 * @param sign 加签后的数据
 * @return 验签结果
 * @throws Exception
 */
private static boolean checkSignWithRSA(Map<String,String> paramsMap, String publicKey, String sign) throws Exception {
   String content = formatSignContent(paramsMap);
   Signature signature = Signature.getInstance("SHA1WithRSA");
   signature.initVerify(getPublicKey(publicKey));
   signature.update(content.getBytes("utf-8"));
   return signature.verify(Base64.decodeBase64(sign));
}

(6)实际使用示例

/**验证加签验签流程
 * 1.A通过自己的私钥对原数据map进行加签,加签后的数据sign
 * 2.A将加签数据sign和原始数据map发送给另外一方B
 * 3.B通过加签数据sign和传递过来的数据map进行通过A的公钥进行解签
 * RSA加签验签方法
 * @return 是否正确
 * @throws Exception
 */
public static boolean verifySingCheck() throws Exception {
   Map<String, Object> keyMap = initKey();//得到原始公钥、私钥存储的map
   String publicKey = getPublicKey(keyMap);//获取规范公钥
   String privateKey = getPrivateKey(keyMap);//获取规范私钥
​
   Map<String,String> map = new HashMap<>();
   map.put("key1","111");
   map.put("key2","222");
​
   //传递过程发生了改变
   Map<String,String> map2 = new HashMap<>();
   map2.put("key1","111222");
   map2.put("key2","222");
​
   String sign = signWithRSA(map,privateKey);
   boolean check = checkSignWithRSA(map,publicKey,sign);
   //boolean check = checkSignWithRSA(map2,publicKey,sign);//传递过程发生了改变
   System.out.println("签名结果,sign:"+sign);
   System.out.println("验签结果,result:"+check);
   return check;
}

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值