一.数字签名:
数字签名(又称
公钥数字签名、
电子签章)
是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术实现,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。
数字签名,就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。
二.常用数字签名算法:RSA、DSA、ECDSA
三.RSA 算法:RSA算法包括MD、SHA经典算法两类如下
四.模型:
五.具体的实现(java):
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.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.apache.commons.codec.binary.Base64;
public class RSA_2 {
static String src = "欧阳草帽";
public static void main(String[] args) throws Exception {
// 获取公钥、私钥
KeyPair keyPair = getKeyPair();
RSAPublicKey rsaPublicKey = getRSPublicKey(keyPair);
RSAPrivateKey rsaPrivateKey = getESAPrivateKey(keyPair);
byte [] publicKeyEnc = rsaPublicKey.getEncoded(); // 公钥
byte [] privateKeyEnc = rsaPrivateKey.getEncoded(); //私钥
//执行签名
byte[] result = sign(privateKeyEnc);
System.out.println("签名后的数据:"+Base64.encodeBase64String(result));
//验证签名
boolean ok = verify(publicKeyEnc, result);
System.out.println("签名验证的结果:" + ok);
}
/**
* 验证签名
* @param publicKeyEnc
* @param result
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws InvalidKeyException
* @throws SignatureException
*/
public static boolean verify(byte[] publicKeyEnc, byte[] result)
throws NoSuchAlgorithmException, InvalidKeySpecException,
InvalidKeyException, SignatureException {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyEnc);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(publicKey);
signature.update(src.getBytes());
boolean ok = signature.verify(result); // 验证结果
return ok;
}
/**
* 执行签名
* @param privateKeyEnc
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws InvalidKeyException
* @throws SignatureException
*/
public static byte[] sign(byte[] privateKeyEnc)
throws NoSuchAlgorithmException, InvalidKeySpecException,
InvalidKeyException, SignatureException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyEnc);
PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//构建签名
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(priKey);
signature.update(src.getBytes());
byte [] result = signature.sign(); // 签名后的数据信息
return result;
}
/**
* 生成私钥
* @param keyPair
* @return
*/
public static RSAPrivateKey getESAPrivateKey(KeyPair keyPair) {
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
return rsaPrivateKey;
}
/**
* 生成公钥
* @param keyPair
* @return
*/
public static RSAPublicKey getRSPublicKey(KeyPair keyPair) {
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
return rsaPublicKey;
}
/**
* 生成秘钥对的材料
* @return
* @throws NoSuchAlgorithmException
*/
private static KeyPair getKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
}
}
输出结果:
签名后的数据:A9/cZUNyVX9q4fJvderwdwUI8T6a/UmEjGM6e5yiS68OmjdSOx3tx0oWjkECnpF/X1QDCsphCwZo8CAbgDmItA==
签名验证的结果:true