1、  什么是数字签名

数字签名,就是只有信息发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息发送者发送信息真实性的一个有效证明。

数字签名是带有密钥的消息摘要算法。数字签名实际上是一个工具,一次性生成秘钥后,将秘钥信息用于固定的交互中。

2、  数字签名的功能

保证信息传输的完整性、发送者的身份认证、防止交易中的抵赖发生。

首先由发送方构建密钥对,公布密钥对;发送方使用私钥根据摘要生成数字签名,将数字签名和数据报文一起发送给接收方;接收方使用公布的公钥对数字签名验证,验证通过则说明数据传输中没有被修改过,可正常接收,否则说明数据被修改过,可拒绝接收报文信息。

3、  数字签名测试代码

RSA、DSA、ECDSA 的代码编写近乎相同;全部粘贴出来,可以直接运行测试。

 1)RSA CODE

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 org.apache.commons.codec.binary.Base64;

public class test {

	//摘要
	private static final String strMsg = "hold on";
	
	public static void main(String[] args) throws Exception {
		jdkRSA();
	}
	
	/**
	 * RSA 使用最为广泛的数字签名算法(MD、SHA两类)
	 * @throws Exception
	 */
	public static void jdkRSA() throws Exception{
		//1.初始化密钥
		KeyPair keyPair = initKey();
		
		//2.执行签名(用私钥签名)
		RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
		byte[] sign = privateKeySign(strMsg, rsaPrivateKey);
		String signStr = Base64.encodeBase64String(sign);  
		System.out.println("sign String :"+signStr);//数字签名格式转换,以便报文传输用
		
		RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
		String publicKeyStr =  Base64.encodeBase64String(rsaPublicKey.getEncoded());
		System.out.println("publicKeyStr String :"+publicKeyStr);//提供给对端,以便于对端使用公钥验证签名
		
		
		//3.验证签名(公钥验证签名)
		boolean result = publicKeyVerify(Base64.decodeBase64(signStr), Base64.decodeBase64(publicKeyStr));
		System.out.println("JDK RSA verify:"+result);
	}
	
	/**
	 * 1.初始化密钥,采用RSA
	 * @return
	 * @throws Exception 
	 */
	public static KeyPair initKey() throws Exception{
		KeyPairGenerator  keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(512); //key长度设置
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		
		return keyPair;
	}
	
	
	/**
	 * 2.执行签名(用私钥签名)
	 * @return
	 * @throws Exception 
	 */
	public static byte[] privateKeySign(String data,RSAPrivateKey rsaPrivateKey) throws Exception{
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		Signature signature = Signature.getInstance("MD5withRSA");
		signature.initSign(privateKey);
		signature.update(strMsg.getBytes());
		byte[] sign = signature.sign();
		
		return sign;
	}
	
	/**
	 * 3.公钥验证签名(摘要+签名串+公钥)
	 * @throws Exception 
	 */
	public static boolean publicKeyVerify(byte[] sign,byte[] rsaPublicKey) throws Exception{
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		Signature signature = Signature.getInstance("MD5withRSA");
		signature.initVerify(publicKey);
		signature.update(strMsg.getBytes());
		boolean result = signature.verify(sign);
		
		return result;
	}

}

 2)DSA CODE

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.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.apache.commons.codec.binary.Base64;

public class test {

	//摘要
	private static final String strMsg = "hold on";
	
	public static void main(String[] args) throws Exception {
		jdkDSA();
	}
	
	/**
	 *  DSA code的编写与RSA近乎相同
	 * @throws Exception
	 */
	public static void jdkDSA() throws Exception{
		//1.初始化密钥
		KeyPair keyPair = initKey();
		
		//2.执行签名(用私钥签名)
		DSAPrivateKey dsaPrivateKey = (DSAPrivateKey) keyPair.getPrivate();
		byte[] sign = privateKeySign(strMsg, dsaPrivateKey);
		String signStr = Base64.encodeBase64String(sign);  
		System.out.println("sign String :"+signStr);//数字签名格式转换,以便报文传输用
		
		DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic();
		String publicKeyStr =  Base64.encodeBase64String(dsaPublicKey.getEncoded());
		System.out.println("publicKeyStr String :"+publicKeyStr);//提供给对端,以便于对端使用公钥验证签名
		
		
		//3.验证签名(公钥验证签名)
		boolean result = publicKeyVerify(Base64.decodeBase64(signStr), Base64.decodeBase64(publicKeyStr));
		System.out.println("JDK DSA verify:"+result);
	}
	
	/**
	 * 1.初始化密钥,采用DSA
	 * @return
	 * @throws Exception 
	 */
	public static KeyPair initKey() throws Exception{
		KeyPairGenerator  keyPairGenerator = KeyPairGenerator.getInstance("DSA");
		keyPairGenerator.initialize(512); //key长度设置
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		
		return keyPair;
	}
	
	
	/**
	 * 2.执行签名(用私钥签名)
	 * @return
	 * @throws Exception 
	 */
	public static byte[] privateKeySign(String data,DSAPrivateKey dsaPrivateKey) throws Exception{
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dsaPrivateKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("DSA");
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		Signature signature = Signature.getInstance("SHA1withDSA");
		signature.initSign(privateKey);
		signature.update(strMsg.getBytes());
		byte[] sign = signature.sign();
		
		return sign;
	}
	
	/**
	 * 3.公钥验证签名(摘要+签名串+公钥)
	 * @throws Exception 
	 */
	public static boolean publicKeyVerify(byte[] sign,byte[] dsaPublicKey) throws Exception{
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey);
		KeyFactory keyFactory = KeyFactory.getInstance("DSA");
		PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		Signature signature = Signature.getInstance("SHA1withDSA");
		signature.initVerify(publicKey);
		signature.update(strMsg.getBytes());
		boolean result = signature.verify(sign);
		
		return result;
	}

}

 3)ECDSA  CODE

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.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.apache.commons.codec.binary.Base64;

public class test {

	//摘要
	private static final String strMsg = "hold on";
	
	public static void main(String[] args) throws Exception {
		jdkECDSA();
	}
	
	/**
	 * ECDSA 微软的椭圆曲线算法 jdk1.7以后引入的算法
	 * @throws Exception
	 */
	public static void jdkECDSA() throws Exception{
		//1.初始化密钥
		KeyPair keyPair = initKey();
		
		//2.执行签名(用私钥签名)
		ECPrivateKey ecPrivateKey = (ECPrivateKey) keyPair.getPrivate();
		byte[] sign = privateKeySign(strMsg,ecPrivateKey);
		String signStr = Base64.encodeBase64String(sign);  
		System.out.println("sign String :"+signStr);//数字签名格式转换,以便报文传输用
		
		ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic();
		String publicKeyStr =  Base64.encodeBase64String(ecPublicKey.getEncoded());
		System.out.println("publicKeyStr String :"+publicKeyStr);//提供给对端,以便于对端使用公钥验证签名
		
		
		//3.验证签名(公钥验证签名)
		boolean result = publicKeyVerify(Base64.decodeBase64(signStr), Base64.decodeBase64(publicKeyStr));
		System.out.println("JDK DSA verify:"+result);
	}
	
	/**
	 * 1.初始化密钥,采用ECDSA
	 * @return
	 * @throws Exception 
	 */
	public static KeyPair initKey() throws Exception{
		KeyPairGenerator  keyPairGenerator = KeyPairGenerator.getInstance("EC");
		keyPairGenerator.initialize(256); //key长度设置
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		
		return keyPair;
	}
	
	
	/**
	 * 2.执行签名(用私钥签名)
	 * @return
	 * @throws Exception 
	 */
	public static byte[] privateKeySign(String data,ECPrivateKey ecPrivateKey) throws Exception{
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("EC");
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		Signature signature = Signature.getInstance("SHA1withECDSA");
		signature.initSign(privateKey);
		signature.update(strMsg.getBytes());
		byte[] sign = signature.sign();
		
		return sign;
	}
	
	/**
	 * 3.公钥验证签名(摘要+签名串+公钥)
	 * @throws Exception 
	 */
	public static boolean publicKeyVerify(byte[] sign,byte[] dsaPublicKey) throws Exception{
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey);
		KeyFactory keyFactory = KeyFactory.getInstance("EC");
		PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		Signature signature = Signature.getInstance("SHA1withECDSA");
		signature.initVerify(publicKey);
		signature.update(strMsg.getBytes());
		boolean result = signature.verify(sign);
		
		return result;
	}

}