0
点赞
收藏
分享

微信扫一扫

5、【java数据安全】数字签名的三种算法(RSA、DSA和ECDSA)使用示例

java数据安全 系列文章

1、【java数据安全】数据安全之加密解密(base64、MD、SHA、DES、AES、IDEA、PBE、DH、RSA、EIGamal)、数字签名(DSA、ECDSA)和数字证书介绍、应用示例详细介绍 2、【java数据安全】base64与报文摘要MD(md5、sha、mac)简单介绍及应用场景、示例 3、【java数据安全】对称加密的5种(DES/3DES、AES、IDEA、PBE)常见算法的使用示例 4、【java数据安全】非对称加密算法(DH、RSA、EIGamal/DSA)的介绍、应用场景和示例 5、【java数据安全】数字签名的三种算法(RSA、DSA和ECDSA)使用示例 6、【java数据安全】数字信封介绍及实现流程 7、【java数据安全】国家商用密码介绍及对称加密、非对称加密使用示例(一) 8、【java数据安全】国家商用密码介绍及数字签名、密钥交换、密钥编码格式使用示例(二)

(文章目录)

本文简单介绍了数字签名常用的三种算法以及具体使用示例。

一、maven依赖

		<dependency>
			<groupId>org.testng</groupId>
			<artifactId>testng</artifactId>
			<version>6.9.10</version>
		</dependency>

二、数字签名算法介绍、应用场景和示例

1、介绍

数字签名算法是一种带有密钥的消息摘要算法,使用的是非对称加密算法与消息摘要算法的结合。 数字签名算法要求能够验证数据的完整性、数据的来源以及防抵赖。消息摘要算法是验证数据完整性的最佳算法;防抵赖靠签名来确保,也是基于消息摘要的。 数字签名算法包含签名和验证两个重要步骤,遵循“私钥签名,公钥验证”的签名验证方式。签名时需要私钥和待签名的数据;验证时需要公钥、签名值和待签名数据,其核心就是消息摘要信息,签名值与消息摘要值一样,通常以十六进制字符串来表示。简单来说先对原始数据做摘要处理,然后使用私钥对摘要值签名;验证时使用公钥验证消息的摘要值。 数字签名常用算法有RSA、DSA、ECDSA,其中RSA是基于整数因子分解问题,DSA和ECDSA则是基于离散对数问题。RSA是目前数字签名应用最广泛的算法。

2、RSA签名

1)、介绍

RSA数字签名算法与加密算法一致,统称RSA。RSA数字签名算法分为MD和SHA两个系列,MD系列主要包含MD2withRSA和MD5withRSA;SHA系列包含SHA1withRSA、SHA224withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA。

2)、jdk示例

1、实现源码

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

/**
 * @author alan 2018年11月20日
 */
public class RSACoder {
	/**
	 * 数字签名 密钥算法
	 */
	public static final String KEY_ALGORITHM = "RSA";

	/**
	 * 数字签名 签名/验证算法
	 */
	public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";

	/**
	 * 公钥
	 */
	private static final String PUBLIC_KEY = "RSAPublicKey";

	/**
	 * 私钥
	 */
	private static final String PRIVATE_KEY = "RSAPrivateKey";

	/**
	 * RSA密钥长度 默认1024位, 密钥长度必须是64的倍数, 范围在512至65536位之间。
	 */
	private static final int KEY_SIZE = 512;

	/**
	 * 签名
	 * 
	 * @param data
	 *            待签名数据
	 * @param privateKey
	 *            私钥
	 * @return byte[] 数字签名
	 * @throws Exception
	 */
	public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
		// 转换私钥材料
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
		// 实例化密钥工厂
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		// 取私钥匙对象
		PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
		// 实例化Signature
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		// 初始化Signature
		signature.initSign(priKey);
		// 更新
		signature.update(data);
		// 签名
		return signature.sign();
	}

	/**
	 * 校验
	 * 
	 * @param data
	 *            待校验数据
	 * @param publicKey
	 *            公钥
	 * @param sign
	 *            数字签名
	 * 
	 * @return boolean 校验成功返回true 失败返回false
	 * @throws Exception
	 * 
	 */
	public static boolean verify(byte[] data, byte[] publicKey, byte[] sign) throws Exception {
		// 转换公钥材料
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
		// 实例化密钥工厂
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		// 生成公钥
		PublicKey pubKey = keyFactory.generatePublic(keySpec);
		// 实例化Signature
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		// 初始化Signature
		signature.initVerify(pubKey);
		// 更新
		signature.update(data);
		// 验证
		return signature.verify(sign);
	}

	/**
	 * 取得私钥
	 * 
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static byte[] getPrivateKey(Map<String, Object> keyMap) throws Exception {
		Key key = (Key) keyMap.get(PRIVATE_KEY);
		return key.getEncoded();
	}

	/**
	 * 取得公钥
	 * 
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception {
		Key key = (Key) keyMap.get(PUBLIC_KEY);
		return key.getEncoded();
	}

	/**
	 * 初始化密钥
	 * 
	 * @return Map 密钥对儿 Map
	 * @throws Exception
	 */
	public static Map<String, Object> initKey() throws Exception {
		// 实例化密钥对儿生成器
		KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
		// 初始化密钥对儿生成器
		keyPairGen.initialize(KEY_SIZE);
		// 生成密钥对儿
		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(PUBLIC_KEY, publicKey);
		keyMap.put(PRIVATE_KEY, privateKey);

		return keyMap;
	}
}

2、testNG测试

import static org.testng.Assert.assertTrue;

import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

/**
 * @author alan 2018年11月20日
 */
public class RSACoderTest {
	/**
	 * 公钥
	 */
	private byte[] publicKey;

	/**
	 * 私钥
	 */
	private byte[] privateKey;

	/**
	 * 初始化密钥
	 * 
	 * @throws Exception
	 */
	@BeforeMethod
	public void initKey() throws Exception {
		Map<String, Object> keyMap = RSACoder.initKey();
		publicKey = RSACoder.getPublicKey(keyMap);
		privateKey = RSACoder.getPrivateKey(keyMap);

		System.err.println("公钥: \n" + Base64.encodeBase64String(publicKey));
		System.err.println("私钥: \n" + Base64.encodeBase64String(privateKey));
	}

	/**
	 * 校验
	 * 
	 * @throws Exception
	 */
	@Test
	public void testSign() throws Exception {
		String inputStr = "RSA数字签名";
		byte[] data = inputStr.getBytes();

		// 产生签名
		byte[] sign = RSACoder.sign(data, privateKey);
		System.err.println("签名:\n" + Hex.encodeHexString(sign));

		// 验证签名
		boolean status = RSACoder.verify(data, publicKey, sign);
		System.err.println("状态:\n" + status);
		assertTrue(status);

	}
}

3、DSA签名

1)、介绍

DSA本质上是EIGamal数字签名算法,与RSA算法是数字证书中两种常见的算法,与RSA不同的是DSA仅仅包含数字签名算法,使用DSA算法的数字证书无法进行加密通信,而RSA算法即可加密也可签名。 DSA算法签名长度与密钥长度无关。

2)、jdk示例

1、实现源码

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

/**
 * @author alan 2018年11月20日
 */
public class DSACoder {
	/**
	 * 数字签名密钥算法
	 */
	public static final String ALGORITHM = "DSA";

	/**
	 * 数字签名 签名/验证算法
	 */
	public static final String SIGNATURE_ALGORITHM = "SHA1withDSA";

	/**
	 * 公钥
	 */
	private static final String PUBLIC_KEY = "DSAPublicKey";

	/**
	 * 私钥
	 */
	private static final String PRIVATE_KEY = "DSAPrivateKey";

	/**
	 * DSA密钥长度 默认1024位, 密钥长度必须是64的倍数, 范围在512至1024位之间(含)
	 */
	private static final int KEY_SIZE = 1024;

	/**
	 * 签名
	 * 
	 * @param data
	 *            待签名数据
	 * @param privateKey
	 *            私钥
	 * @return byte[] 数字签名
	 * @throws Exception
	 */
	public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {

		// 还原私钥
		// 转换私钥材料
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);

		// 实例化密钥工厂
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);

		// 生成私钥对象
		PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);

		// 实例化Signature
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

		// 初始化Signature
		signature.initSign(priKey);

		// 更新
		signature.update(data);

		// 签名
		return signature.sign();
	}

	/**
	 * 校验
	 * 
	 * @param data
	 *            待校验数据
	 * @param publicKey
	 *            公钥
	 * @param sign
	 *            数字签名
	 * 
	 * @return boolean 校验成功返回true 失败返回false
	 * @throws Exception
	 * 
	 */
	public static boolean verify(byte[] data, byte[] publicKey, byte[] sign) throws Exception {

		// 还原公钥
		// 转换公钥材料
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);

		// 实例化密钥工厂
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);

		// 取公钥匙对象
		PublicKey pubKey = keyFactory.generatePublic(keySpec);

		// 实例话Signature
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

		// 初始化Signature
		signature.initVerify(pubKey);

		// 更新
		signature.update(data);

		// 验证
		return signature.verify(sign);
	}

	/**
	 * 生成密钥
	 * 
	 * @return 密钥对象
	 * @throws Exception
	 */
	public static Map<String, Object> initKey() throws Exception {

		// 初始化密钥对儿生成器
		KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM);

		// 实例化密钥对儿生成器
		keygen.initialize(KEY_SIZE, new SecureRandom());

		// 实例化密钥对儿
		KeyPair keys = keygen.genKeyPair();

		DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();

		DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();

		// 封装密钥
		Map<String, Object> map = new HashMap<String, Object>(2);

		map.put(PUBLIC_KEY, publicKey);
		map.put(PRIVATE_KEY, privateKey);

		return map;
	}

	/**
	 * 取得私钥
	 * 
	 * @param keyMap
	 *            密钥Map
	 * @return byte[] 私钥
	 * @throws Exception
	 */
	public static byte[] getPrivateKey(Map<String, Object> keyMap) throws Exception {

		Key key = (Key) keyMap.get(PRIVATE_KEY);

		return key.getEncoded();
	}

	/**
	 * 取得公钥
	 * 
	 * @param keyMap
	 *            密钥Map
	 * @return byte[] 公钥
	 * @throws Exception
	 */
	public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception {

		Key key = (Key) keyMap.get(PUBLIC_KEY);

		return key.getEncoded();
	}
}

2、testNG测试

import static org.testng.Assert.assertTrue;

import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

/**
 * @author alan
 * 2018年11月20日
 */
public class DSACoderTest {
	/**
	 * 公钥
	 */
	private byte[] publicKey;

	/**
	 * 私钥
	 */
	private byte[] privateKey;

	/**
	 * 初始化密钥
	 * 
	 * @throws Exception
	 */
	@BeforeMethod
	public void initKey() throws Exception {
		Map<String, Object> keyMap = DSACoder.initKey();

		publicKey = DSACoder.getPublicKey(keyMap);
		privateKey = DSACoder.getPrivateKey(keyMap);

		System.err.println("公钥: \n" + Base64.encodeBase64String(publicKey));
		System.err.println("私钥: \n" + Base64.encodeBase64String(privateKey));
	}

	/**
	 * 校验签名
	 * 
	 * @throws Exception
	 */
	@Test
	public void test() throws Exception {
		String inputStr = "DSA数字签名";
		byte[] data = inputStr.getBytes();

		// 产生签名
		byte[] sign = DSACoder.sign(data, privateKey);
		System.err.println("签名:\r" + Hex.encodeHexString(sign));

		// 验证签名
		boolean status = DSACoder.verify(data, publicKey, sign);
		System.err.println("状态:\r" + status);
		assertTrue(status);

	}
}

4、ECDSA签名

1)、介绍

ECDSA相对于传统的签名算法,速度更快、强度更高、签名更短优点,其用途越来越广泛。

2)、jdk示例

1、实现源码

import java.math.BigInteger;
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.Security;
import java.security.Signature;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECFieldFp;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * @author alan 2018年11月20日
 */
public class ECDSACoder {
	/**
	 * 数字签名 密钥算法
	 */
	private static final String KEY_ALGORITHM = "ECDSA";

	/**
	 * 数字签名 签名/验证算法
	 * 
	 * Bouncy Castle支持以下7种算法 NONEwithECDSA RIPEMD160withECDSA SHA1withECDSA
	 * SHA224withECDSA SHA256withECDSA SHA384withECDSA SHA512withECDSA
	 */
	private static final String SIGNATURE_ALGORITHM = "SHA512withECDSA";

	/**
	 * 公钥
	 */
	private static final String PUBLIC_KEY = "ECDSAPublicKey";

	/**
	 * 私钥
	 */
	private static final String PRIVATE_KEY = "ECDSAPrivateKey";

	/**
	 * 初始化密钥
	 * 
	 * @return Map 密钥Map
	 * @throws Exception
	 */
	public static Map<String, Object> initKey() throws Exception {

		// 加入BouncyCastleProvider支持
		Security.addProvider(new BouncyCastleProvider());

		BigInteger p = new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839");

		ECFieldFp ecFieldFp = new ECFieldFp(p);

		BigInteger a = new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16);

		BigInteger b = new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16);

		EllipticCurve ellipticCurve = new EllipticCurve(ecFieldFp, a, b);

		BigInteger x = new BigInteger("110282003749548856476348533541186204577905061504881242240149511594420911");

		BigInteger y = new BigInteger("869078407435509378747351873793058868500210384946040694651368759217025454");

		ECPoint g = new ECPoint(x, y);

		BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");

		ECParameterSpec ecParameterSpec = new ECParameterSpec(ellipticCurve, g, n, 1);

		// 实例化密钥对儿生成器
		KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_ALGORITHM);

		// 初始化密钥对儿生成器
		kpg.initialize(ecParameterSpec, new SecureRandom());

		// 生成密钥对儿
		KeyPair keypair = kpg.generateKeyPair();

		ECPublicKey publicKey = (ECPublicKey) keypair.getPublic();

		ECPrivateKey privateKey = (ECPrivateKey) keypair.getPrivate();

		// 封装密钥
		Map<String, Object> map = new HashMap<String, Object>(2);

		map.put(PUBLIC_KEY, publicKey);
		map.put(PRIVATE_KEY, privateKey);

		return map;
	}

	/**
	 * 取得私钥
	 * 
	 * @param keyMap
	 *            密钥Map
	 * @return byte[] 私钥
	 * @throws Exception
	 */
	public static byte[] getPrivateKey(Map<String, Object> keyMap) throws Exception {

		Key key = (Key) keyMap.get(PRIVATE_KEY);

		return key.getEncoded();
	}

	/**
	 * 取得公钥
	 * 
	 * @param keyMap
	 *            密钥Map
	 * @return byte[] 公钥
	 * @throws Exception
	 */
	public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception {

		Key key = (Key) keyMap.get(PUBLIC_KEY);

		return key.getEncoded();
	}

	/**
	 * 签名
	 * 
	 * @param data
	 *            待签名数据
	 * @param privateKey
	 *            私钥
	 * @return byte[] 数字签名
	 * @throws Exception
	 */
	public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {

		// 加入BouncyCastleProvider支持
		Security.addProvider(new BouncyCastleProvider());

		// 转换私钥材料
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);

		// 实例化密钥工厂
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

		// 取私钥匙对象
		PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);

		// 实例化Signature
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

		// 初始化Signature
		signature.initSign(priKey);

		// 更新
		signature.update(data);

		// 签名
		return signature.sign();
	}

	/**
	 * 校验
	 * 
	 * @param data
	 *            待校验数据
	 * @param publicKey
	 *            公钥
	 * @param sign
	 *            数字签名
	 * @return boolean 校验成功返回true 失败返回false
	 * @throws Exception
	 * 
	 */
	public static boolean verify(byte[] data, byte[] publicKey, byte[] sign) throws Exception {

		// 加入BouncyCastleProvider支持
		Security.addProvider(new BouncyCastleProvider());

		// 转换公钥材料
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);

		// 实例化密钥工厂
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

		// 生成公钥
		PublicKey pubKey = keyFactory.generatePublic(keySpec);

		// 实例化Signature
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

		// 初始化Signature
		signature.initVerify(pubKey);

		// 更新
		signature.update(data);

		// 验证
		return signature.verify(sign);
	}
}

2、testNG测试

import static org.testng.Assert.assertTrue;

import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

/**
 * @author alan 2018年11月20日
 */
public class ECDSACoderTest {
	/**
	 * 公钥
	 */
	private byte[] publicKey;

	/**
	 * 私钥
	 */
	private byte[] privateKey;

	/**
	 * 初始化密钥
	 * 
	 * @throws Exception
	 */
	@BeforeMethod
	public void initKey() throws Exception {

		Map<String, Object> keyMap = ECDSACoder.initKey();

		publicKey = ECDSACoder.getPublicKey(keyMap);

		privateKey = ECDSACoder.getPrivateKey(keyMap);

		System.err.println("公钥: \n" + Base64.encodeBase64String(publicKey));
		System.err.println("私钥: \n" + Base64.encodeBase64String(privateKey));
	}

	/**
	 * 校验
	 * 
	 * @throws Exception
	 */
	@Test
	public void test() throws Exception {

		String inputStr = "ECDSA 数字签名";
		byte[] data = inputStr.getBytes();

		// 产生签名
		byte[] sign = ECDSACoder.sign(data, privateKey);
		System.err.println("签名:\r" + Hex.encodeHexString(sign));

		// 验证签名
		boolean status = ECDSACoder.verify(data, publicKey, sign);
		System.err.println("状态:\r" + status);
		assertTrue(status);

	}
}

3、签名服务实现


import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

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


/**
 * @author alan
 * 2018年11月20日
 */
public class ECDSASignatrueService {
	private Map<String, Object> key = null;
	private String PRIVATEKEY = "privatekey";
	private String PUBLICKEY = "publickey";
	private String ECAlGORIYTHMS = "EC";
	// ECDSA: 椭圆曲线数字签名算法
	private String SIGNATUREALGORIYTHMS = "SHA1withECDSA";

	public Map<String, Object> getKey() {
		return key;
	}

	/**
	 * 通过构造函数生成密钥对
	 */
	private ECDSASignatrueService() {
		key = new HashMap<String, Object>();
		try {
			KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ECAlGORIYTHMS);
			SecureRandom secrand = new SecureRandom();
			secrand.setSeed("www.okcard.com".getBytes()); // 初始化随机产生器
			keyPairGenerator.initialize(256, secrand);
			KeyPair keyPair = keyPairGenerator.generateKeyPair();
			ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic();
			ECPrivateKey ecPrivateKey = (ECPrivateKey) keyPair.getPrivate();
			key.put(PUBLICKEY, ecPublicKey);
			key.put(PRIVATEKEY, ecPrivateKey);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 针对需要签名的字符进行签名
	 * 
	 * @param message
	 * @return
	 */
	public byte[] doSignature(String message) {
		byte[] result = null;
		ECPrivateKey ecPrivateKey = (ECPrivateKey) key.get(PRIVATEKEY);
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());

		try {
			KeyFactory keyFactory = KeyFactory.getInstance(ECAlGORIYTHMS);
			PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
			
			
			Signature signature = Signature.getInstance(SIGNATUREALGORIYTHMS);
			signature.initSign(privateKey);
			signature.update(message.getBytes());
			result = signature.sign();
			
			
			System.out.println("jdk 加密结果 : " + Hex.encodeHexString(result));
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (SignatureException e) {
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * 针对签名的字符使用公钥进行验证
	 * 
	 * @param message
	 * @param signatureMessage
	 * @param eCPublicKey
	 * @return
	 */
	public boolean verify(String message, byte[] signatureMessage, ECPublicKey eCPublicKey) {
		boolean flag = true;
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(eCPublicKey.getEncoded());

		try {
			KeyFactory keyFactory = KeyFactory.getInstance(ECAlGORIYTHMS);
			PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
			
			Signature signature = Signature.getInstance(SIGNATUREALGORIYTHMS);
			signature.initVerify(publicKey);
			signature.update(message.getBytes());
			flag = signature.verify(signatureMessage);
			System.out.println("jdk 签名验证结果 : " + flag);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (SignatureException e) {
			e.printStackTrace();
		}

		return flag;
	}

	public static void main(String[] args) {
		ECDSASignatrueService eCDSASignatrueService = new ECDSASignatrueService();
		String message = "test a signatrue string";
		eCDSASignatrueService.verify(message, eCDSASignatrueService.doSignature(message),
				(ECPublicKey) eCDSASignatrueService.getKey().get(eCDSASignatrueService.PUBLICKEY));
	}
}

以上,简单介绍了数字签名常用的三种算法以及具体使用示例。

举报

相关推荐

0 条评论