Java加密算法 DSA 和 数字签名

x33g5p2x  于2021-12-25 转载在 其他  
字(4.7k)|赞(0)|评价(0)|浏览(275)
package com.stone.security;

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
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;

/**
 * DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。
 * 简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。
 * 如果数据和签名不匹配则认为验证失败!即 传输中的数据 可以不再加密,接收方获得数据后,拿到公钥与签名 验证数据是否有效
 * 
 * @author stone
 * @date 2014-03-11 09:50:51
 */
public class DSA {
	//不仅可以使用DSA算法,同样也可以使用RSA算法做数字签名
	/*public static final String KEY_ALGORITHM = "RSA";
	public static final String SIGNATURE_ALGORITHM = "MD5withRSA";*/
	
	public static final String KEY_ALGORITHM = "DSA";
	public static final String SIGNATURE_ALGORITHM = "DSA";
	
	public static final String DEFAULT_SEED = "$%^*%^()(HJG8awfjas7"; //默认种子
	public static final String PUBLIC_KEY = "DSAPublicKey";
	public static final String PRIVATE_KEY = "DSAPrivateKey";
	
	public static void main(String[] args) throws Exception {
		String str = "!@#$!#^$#&ZXVDF呆军工路爱着你*()_+";
		byte[] data = str.getBytes();
		
		Map<String, Object> keyMap = initKey();// 构建密钥
		PublicKey publicKey = (PublicKey) keyMap.get(PUBLIC_KEY);
		PrivateKey privateKey = (PrivateKey) keyMap.get(PRIVATE_KEY);
		System.out.println("私钥format:" + privateKey.getFormat());
		System.out.println("公钥format:" + publicKey.getFormat());
		
		
		// 产生签名
		String sign = sign(data, getPrivateKey(keyMap));
		
		// 验证签名 
		boolean verify1 = verify("aaa".getBytes(), getPublicKey(keyMap), sign);
		System.err.println("经验证 数据和签名匹配:" + verify1);   
		
		boolean verify = verify(data, getPublicKey(keyMap), sign);
		System.err.println("经验证 数据和签名匹配:" + verify);   
	}
	
    /**  
     * 生成密钥  
     *   
     * @param seed 种子  
     * @return 密钥对象  
     * @throws Exception  
     */
	public static Map<String, Object> initKey(String seed) throws Exception {
		System.out.println("生成密钥");
		
		KeyPairGenerator keygen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
		SecureRandom secureRandom = new SecureRandom();   
        secureRandom.setSeed(seed.getBytes()); 
        //Modulus size must range from 512 to 1024 and be a multiple of 64
        keygen.initialize(640, secureRandom);  
        
        KeyPair keys = keygen.genKeyPair();
        PrivateKey privateKey = keys.getPrivate();
        PublicKey publicKey = keys.getPublic();
        
        Map<String, Object> map = new HashMap<String, Object>(2);
        map.put(PUBLIC_KEY, publicKey);   
        map.put(PRIVATE_KEY, privateKey);
        return map;
	}
	
	/**  
     * 生成默认密钥  
     *   
     * @return 密钥对象  
     * @throws Exception  
     */  
    public static Map<String, Object> initKey() throws Exception {   
        return initKey(DEFAULT_SEED);   
    }
    
    /**  
     * 取得私钥  
     *   
     * @param keyMap  
     * @return  
     * @throws Exception  
     */  
    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {   
        Key key = (Key) keyMap.get(PRIVATE_KEY);   
        return encryptBASE64(key.getEncoded()); //base64加密私钥
    }   
  
    /**  
     * 取得公钥  
     *   
     * @param keyMap  
     * @return  
     * @throws Exception  
     */  
    public static String getPublicKey(Map<String, Object> keyMap) throws Exception {   
        Key key = (Key) keyMap.get(PUBLIC_KEY);   
        return encryptBASE64(key.getEncoded()); //base64加密公钥
    }   
	
	/**
	 *  用私钥对信息进行数字签名
	 * @param data	加密数据
	 * @param privateKey 私钥-base64加密的
	 * @return 
	 * @throws Exception
	 */
	public static String sign(byte[] data, String privateKey) throws Exception {
		System.out.println("用私钥对信息进行数字签名");
		
		byte[] keyBytes = decryptBASE64(privateKey);
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
		PrivateKey priKey = factory.generatePrivate(keySpec);//生成 私钥
		
		//用私钥对信息进行数字签名
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initSign(priKey);
		signature.update(data);
		return encryptBASE64(signature.sign());
	}
	
	/**
	 * BASE64Encoder 加密
	 * @param data 要加密的数据
	 * @return 加密后的字符串
	 */
	private static String encryptBASE64(byte[] data) {
		BASE64Encoder encoder = new BASE64Encoder();
		String encode = encoder.encode(data);
		return encode;
	}
	
	/**
	 * BASE64Decoder 解密
	 * @param data 要解密的字符串
	 * @return 解密后的byte[]
	 * @throws Exception 
	 */
	private static byte[] decryptBASE64(String data) throws Exception {
		BASE64Decoder decoder = new BASE64Decoder();
		byte[] buffer = decoder.decodeBuffer(data);
		return buffer;
	}
	
	/**
	 * 校验数字签名
	 * @param data 加密数据
	 * @param publicKey
	 * @param sign 数字签名
	 * @return
	 * @throws Exception
	 */
	public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
		byte[] keyBytes = decryptBASE64(publicKey); 
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
		PublicKey pubKey = keyFactory.generatePublic(keySpec);
		
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);   
        signature.initVerify(pubKey); 
        signature.update(data);
        
        return signature.verify(decryptBASE64(sign)); //验证签名
	}
	
}

参考地址:http://63938525.iteye.com/blog/1051565

http://www.iteye.com/topic/1122076 

相关文章