Rsa签名算法详解

Rsa签名算法详解


签名生成规则与验证签名规则如下:

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

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



具体的实现代码如下

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为对方的签名,还有对方的公钥我已经将其写成静态常量了
	}
}

猜你喜欢

转载自patronli.iteye.com/blog/2326107