數字簽名– RSA、DSA、ECDSA

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;
	}

}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章