基于RSA算法的数字签名技术的实现原理

一、数字签名的原理

发 送报文时,发送方由报文文本计算生成报文摘要,然后用自己的私钥对这个摘要进行加密,这个加密后的摘要将作为报文的数字签名和报文一起发送给接收方。接收 到报文之后,接收方使用发送方的公钥对报文附加的数字签名进行解密,然后由接收到的原始报文计算出报文摘要,如果两个摘要相同,那么接收方就能确定该数字 签名是发送方的。

二、数字签名的实现

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;

public class RSAUtil {
        /**
        * 生成指定密钥长度的密钥对
        */
	public static KeyPair generateKeyPair(int keysize) throws Exception {

		KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
		generator.initialize(keysize, new SecureRandom());
		KeyPair keyPair = generator.generateKeyPair();
		return keyPair;
	}
        /**
        * 签名
        */
    public static byte[] sign(String algorithm, byte[] data,
			PrivateKey privateKey) throws Exception {

		Signature signature = Signature.getInstance(algorithm);
		signature.initSign(privateKey);
		signature.update(data);
		return signature.sign();
	}
        /**
        * 签名验证
        */
	public static boolean verify(String algorithm, byte[] signature,
			byte[] data, PublicKey publicKey) throws Exception {

		Signature s = Signature.getInstance(algorithm);
		s.initVerify(publicKey);
		s.update(data);
		return s.verify(signature);
	}
}

三、数字签名的过程模拟

import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Arrays;

import javax.crypto.Cipher;

import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;

public class RSAFake {

	public static byte[] sign(String algorithm, byte[] data,
			PrivateKey privateKey) throws Exception {

		MessageDigest digest = MessageDigest.getInstance("SHA1");
		byte[] md = digest.digest(data);

		ASN1EncodableVector algVector = new ASN1EncodableVector();
		algVector.add(new ASN1ObjectIdentifier("1.3.14.3.2.26"));
		algVector.add(DERNull.INSTANCE);
		DERSequence algSequence = new DERSequence(algVector);

		DEROctetString mdString = new DEROctetString(md);

		ASN1EncodableVector mdVector = new ASN1EncodableVector();
		mdVector.add(algSequence);
		mdVector.add(mdString);
		DERSequence mdSequence = new DERSequence(mdVector);

		byte[] mdEncode = mdSequence.getEncoded();

		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		cipher.update(mdEncode);
		return cipher.doFinal();
	}

	public static boolean verify(String algorithm, byte[] signature,
			byte[] data, PublicKey publicKey) throws Exception {

		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher.init(Cipher.DECRYPT_MODE, publicKey);
		cipher.update(signature);
		byte[] plain = cipher.doFinal();

		ASN1Sequence sequence = ASN1Parser.toSequence(plain);
		// ASN1Sequence algSeq = (ASN1Sequence) sequence.getObjectAt(0);
		// ASN1ObjectIdentifier algId = (ASN1ObjectIdentifier) algSeq
		// .getObjectAt(0);
		// System.out.println(algId.getId());

		DEROctetString hashString = (DEROctetString) sequence.getObjectAt(1);
		byte[] hash = hashString.getOctets();

		MessageDigest md = MessageDigest.getInstance("SHA1");
		byte[] calHash = md.digest(data);

		return Arrays.equals(hash, calHash);
	}

}
import java.io.IOException;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;

public class ASN1Parser {

	public static ASN1Sequence toSequence(byte[] der) throws IOException {
		return (ASN1Sequence) toObject(der);
	}

	private static ASN1Primitive toObject(byte[] der) throws IOException {
		ASN1Primitive obj = null;
		ASN1InputStream asnIn = new ASN1InputStream(der);
		obj = asnIn.readObject();
		asnIn.close();
		return obj;
	}
}

四、测试验证

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class Client {

	byte[] data = null;
	PublicKey publicKey = null;
	PrivateKey privateKey = null;
	String algorithm = "SHA1WithRSA";

	@Before
	public void init() throws Exception {

		data = "apple".getBytes();
		KeyPair keyPair = RSAUtil.generateKeyPair(1024);
		publicKey = keyPair.getPublic();
		privateKey = keyPair.getPrivate();
	}

	@Test
	public void test1() throws Exception {

		byte[] signature = RSAUtil.sign(algorithm, data, privateKey);
		boolean result = RSAUtil.verify(algorithm, signature, data, publicKey);
		Assert.assertEquals(true, result);
	}

	@Test
	public void test2() throws Exception {

		byte[] signature = RSAFake.sign(algorithm, data, privateKey);
		boolean result = RSAFake.verify(algorithm, signature, data, publicKey);
		Assert.assertEquals(true, result);
	}

	@Test
	public void test3() throws Exception {

		byte[] signature = RSAUtil.sign(algorithm, data, privateKey);
		boolean result = RSAFake.verify(algorithm, signature, data, publicKey);
		Assert.assertEquals(true, result);
	}

	@Test
	public void test4() throws Exception {

		byte[] signature = RSAFake.sign(algorithm, data, privateKey);
		boolean result = RSAUtil.verify(algorithm, signature, data, publicKey);
		Assert.assertEquals(true, result);
	}
}

测试结果:

  1. da shang
    donate-alipay
               donate-weixin weixinpay

发表评论↓↓