数字签名– RSA、DSA、ECDSA

原创 2016年08月30日 18:49:05

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

}



RSA、DSA和ECDSA三者的签名

数字签名就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。一般是非对称密钥加密技术与数字摘要技术的结合应用,目前主流的三种非对称算法...

在 SSH 中使用 RSA 和 DSA 认证(详解)

[原贴]http://weblog.kreny.com/archives/2005/10/rsadsa_authenti.html  [作者]:kreny一直想把自己的服务器的 SSH 认证的模式从用...
  • scottsiu
  • scottsiu
  • 2006年09月23日 09:51
  • 13622

RSA与ECC的选择

数字签名技术已经广泛使用于网络安全协议或分布式系统中,目前比较流行的数字签名算法有RSA和ECDSA。很多同学在产品设计中往往都难以区分RSA和ECDSA的优劣,所以笔者将基于自己的实践,来给出一些初...

强制将 SSH 的host key type由 ECDSA替换为RSA

ssh -o HostKeyAlgorithms=ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@...

数字签名加密算法(RSA、DSA、ECDSA)

RSA的例子:import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGe...
  • sx5273
  • sx5273
  • 2016年01月17日 17:24
  • 1315

消息摘要算法--RSA,DSA,ECDSA

数字签名算法: 签名 数字签名---带有密钥(公钥,私钥)的消息摘要算法 验证数据完整性,认证数据来源,抗否认 OSI参考模型 私钥签名,公钥验证 RSA,DSA,ECDSA 1.j...

DSA和ECDSA算法

关键词: DSA:Digital Signature Algorithm (DSA) ECDSA:The Elliptic Curve Digital Signature Algorithm (E...

SHA-1算法c语言实现

安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准 (Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signatu...

数字签名的编程使用

数字签名介绍 1.数字签名 数字签名(又称公钥数字签名、电子签章)是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术实现,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,...

关于ECDSA/ECC(密钥加密传输)和ECDSA/ECDH(密钥磋商)

最近项目中用到了ECC的相关算法,恶补了一下相关知识 ECC:Elliptic Curves Cryptography,椭圆曲线密码编码学 ECDSA:用于数字签名,是ECC与DSA的结合,整个签...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:数字签名– RSA、DSA、ECDSA
举报原因:
原因补充:

(最多只允许输入30个字)