Rsa签名算法详解

[align=center][size=large][color=red][b]Rsa签名算法详解
[/b][/color][/size][/align]

[align=left][color=darkblue][b]签名生成规则与验证签名规则如下:[/b][/color]

[b]①[/b]每次生成签名时该算法都会生成一对对应的公钥和私钥对,
[b]②[/b]所以在应用中一般都会采取使用同一对密钥对进行签名与验签(建议使用静态变量)保证对方验证签名时用的公钥是与你生成签名用的是同一对,否则就不能通过验证
[b]③[/b]将自己生成的秘钥对中的公钥交给对方用来验证你的签名,私钥用来生成签名
[b]④[/b]同样的对方也会选定一组密钥对将公钥给你用来验证签名,用他的私钥来生成签名
[b]⑤[/b]备注:一般对安全性要求比较高的企业,不仅仅限与用rsa签名来保证安全,还会对rsa签名再次加密,比如本案例就使用了base64来加密和解密,同样大家也可以采取其他的措施来增加安全性比如:aes等

[color=darkblue][b]注意事项:[/b][/color]
①在获取对方的签名的时候注意是否有[color=darkred][b]系统会自动生成空格[/b][/color](尤其是签名串在换行的时候)
②在拼装对方的加密串转换成byte类型时注意是否跟对方的[b][color=darkred]字符编码保持一致[/color][/b]
[/align]

[color=darkblue][b]
具体的实现代码如下[/b][/color]

package com.xxx.web.util;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
* @Description: (签名工具类)
* @author keguan_li
* @date 2016年9月22日
*/
public class RSAUtils {

/** */
/**
* 加密算法RSA
*/
public static final String KEY_ALGORITHM = "RSA";

/** */
/**
* 签名算法
*/
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";//有几种算法MD5withRSA是其中一种

public static final String CHARSET = "UTF-8";

/**
* initKey()生成公钥与私钥
* 将生成的公钥与对方互换
* 因为每次生成签名的时候公钥和私钥都会随机变化(一对密钥对)
* 所以要将自己的私钥和对方的公钥设成静态变量
* 保证每次生成签名用的都是同一个私钥
*/

public static final String privateKey="MIICeAIB2QcCQQCvpSVi/IElHyzvvPxRKsTYz/Z";

public static final String publicKey="MIGfMA0GCSqGSvcuK3QJ3i9ZhBpOoyd4JOwIDAQAB";
/**
* 生成签名
* @param retSignPacket
* @param strPriKey
* @return
* @throws Exception
*/
public static String addSign(String retSignPacket) throws Exception{
byte[] bytesKey = decryptBASE64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(bytesKey);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(retSignPacket.getBytes(CHARSET));
String sign = encryptBASE64(signature.sign());
return sign;
}

/**
* 校验数字签名
*
* @param data
* 加密数据
* @param publicKey
* 公钥
* @param sign
* 数字签名
*
* @return 校验成功返回true 失败返回false
* @throws Exception
*
*/
public static boolean verify(byte[] data, String sign)
throws Exception {

// 解密由base64编码的公钥
byte[] keyBytes = decryptBASE64(publicKey);
// 构造X509EncodedKeySpec对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取公钥匙对象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
// 验证签名是否正常
boolean ret = signature.verify(decryptBASE64(sign));
System.out.println("验签结果:" + ret);
return ret;
}

public static Map<String, Object> initKey() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
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("RSAPublicKey", encryptBASE64(publicKey.getEncoded()));
keyMap.put("RSAPrivateKey", encryptBASE64(privateKey.getEncoded()));

System.out.println("私钥为(生成签名用) : ");
String priKey = encryptBASE64(privateKey.getEncoded());
System.out.println(priKey);
System.out.println("*****************");
System.out.println("公钥为(验证签名用) : ");
String pubKey = encryptBASE64(publicKey.getEncoded());
System.out.println(pubKey);
return keyMap;
}


/**
* BASE64解密
*
* @param key
* @return
* @throws Exception
*/
@SuppressWarnings("restriction")
public static byte[] decryptBASE64(String key) throws Exception {
return (new BASE64Decoder()).decodeBuffer(key);
}

/**
* BASE64加密
*
* @param key
* @return
* @throws Exception
*/
@SuppressWarnings("restriction")
public static String encryptBASE64(byte[] key) throws Exception {
return (new BASE64Encoder()).encodeBuffer(key);
}


public static void main(String[] args) throws Exception {
initKey();//该方法生成签名,私钥本地用于本地签名,公钥交给对方用于验证你的签名
addSign("a");//生成签名的方法,a为你要生成签名的签名串,还有用于生成签名的私钥,已写成静态常量
verify("a".getBytes(),"b");//验证签名的方法,a为你拼接的对方的加密串(在转成byte时字符集编码要与对方的字符集编码保持一致),b为对方的签名,还有对方的公钥我已经将其写成静态常量了
}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值