欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

RSA签名与验签

程序员文章站 2022-03-05 19:19:55
...

RSA签名与验签

RSA算法除了可以进行加解密以外,还可以用来签名与验签。RSA用来进行签名与验签时是使用私钥进行签名,公钥进行验签的。这点与加解密的时候刚好相反。加解密时使用公钥加密,私钥解密。签名和验签是通过Signature对象进行的。

签名

以下是一个使用Signature进行签名的示例。初始化Signature时指定将使用的签名算法是MD5withRSA,除了该算法外,Signature还支持很多其它的算法,如SHA256withRSA,更多的算法可以参考官方文档

	/**
	 * 测试签名
	 * @throws Exception
	 */
	@Test
	public void testSign() throws Exception {
		byte[] sign = this.sign("Hello World");
		String result = Base64.getEncoder().encodeToString(sign);
		System.out.println(result);
	}
	
	/**
	 * 私钥签名
	 * @param data
	 * @return
	 * @throws Exception
	 */
	private byte[] sign(String data) throws Exception {
		//读取储存的私钥字节数组
		byte[] privateKeyCode = Files.readAllBytes(Paths.get(PRIVATE_KEY_PATH));
		//包装私钥字节数组为一个KeySpec
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyCode);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		//通过KeyFactory生成私钥
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		Signature signature = Signature.getInstance("MD5withRSA");//签名的算法
		//通过私钥初始化Signature,签名时用
		signature.initSign(privateKey);
		//指定需要进行签名的内容
		signature.update(data.getBytes());
		//签名
		byte[] result = signature.sign();
		return result;
	}

验签

以下是一个利用Signature进行验签的示例。验签时使用的是公钥。在初始化Signature时使用的是initVerify,而签名时使用的是initSign,这跟Cipher进行加解密有点类似。

	/**
	 * 测试公钥验签
	 * @throws Exception
	 */
	@Test
	public void testVerifySign() throws Exception {
		String data = "Hello World";
		byte[] sign = this.sign(data);
		Signature signature = Signature.getInstance("MD5withRSA");
		byte[] publicKeyCode = Files.readAllBytes(Paths.get(PUBLIC_KEY_PATH));
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyCode);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		PublicKey publicKey = keyFactory.generatePublic(keySpec);
		//以验签的方式初始化Signature
		signature.initVerify(publicKey);
		//指定需要验证的签名
		signature.update(data.getBytes());
		//进行验签,返回验签结果
		boolean result = signature.verify(sign);
		Assert.assertTrue(result);
	}

完整代码 以下是上述示例的完整代码。

public class RSATest {

	private static final String ALGORITHM = "RSA";
	private static final String PRIVATE_KEY_PATH = "D:\\rsa_private.isa";
	private static final String PUBLIC_KEY_PATH = "D:\\rsa_public.isa";
	
	/**
	 * 测试签名
	 * @throws Exception
	 */
	@Test
	public void testSign() throws Exception {
		byte[] sign = this.sign("Hello World");
		String result = Base64.getEncoder().encodeToString(sign);
		System.out.println(result);
	}
	
	/**
	 * 私钥签名
	 * @param data
	 * @return
	 * @throws Exception
	 */
	private byte[] sign(String data) throws Exception {
		//读取储存的私钥字节数组
		byte[] privateKeyCode = Files.readAllBytes(Paths.get(PRIVATE_KEY_PATH));
		//包装私钥字节数组为一个KeySpec
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyCode);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		//通过KeyFactory生成私钥
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		Signature signature = Signature.getInstance("MD5withRSA");//签名的算法
		//通过私钥初始化Signature,签名时用
		signature.initSign(privateKey);
		//指定需要进行签名的内容
		signature.update(data.getBytes());
		//签名
		byte[] result = signature.sign();
		return result;
	}
	
	/**
	 * 测试公钥验签
	 * @throws Exception
	 */
	@Test
	public void testVerifySign() throws Exception {
		String data = "Hello World";
		byte[] sign = this.sign(data);
		Signature signature = Signature.getInstance("MD5withRSA");
		byte[] publicKeyCode = Files.readAllBytes(Paths.get(PUBLIC_KEY_PATH));
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyCode);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		PublicKey publicKey = keyFactory.generatePublic(keySpec);
		//以验签的方式初始化Signature
		signature.initVerify(publicKey);
		//指定需要验证的签名
		signature.update(data.getBytes());
		//进行验签,返回验签结果
		boolean result = signature.verify(sign);
		Assert.assertTrue(result);
	}
	
}

(注:本文由Elim写于2017年5月22日)