数字签名介绍
1.数字签名
数字签名(又称公钥数字签名、电子签章)是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术实现,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。
2.数字签名模型
3.什么是数字签名
带有密钥(公钥和私钥)的消息摘要算法,是非对称加密算法和消息摘要算法结合体
4.数字签名的特点
(1)用于签名的信息私有,用于验证的信息公有,且这两种信息必须成对出现
(2)签名时使用原始数据和私钥,验证时需要原始数据、公钥和签名值
(3)私钥仅用于签名,公钥仅用于验证
(4)实际使用时,通常对原始数据先做摘要处理,再用私钥进行签名
5.常用数字签名算法:
(1)RSA Signature(JDK)
(2)DSA Signature(JDK)
(3)ECDSA Signature(需要 Bouncy Castle 支持)
6.数字签名作用
1.验证数据完整性
2.认证数据来源
3.抗否认
RSASignature 算法的编程使用
1.RSA 签名算法概念
将 RSA 公钥密码算法按照数字签名的方式运用
2.RSA 签名算法分类(JDK实现)
(1)MD (MD2withRSA、MD5withRSA)
(2)SHA (SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA)
3.编程实例
package key.base64;
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;
public class RSASigatureUtil {
public static final String KEY_ALGORITHM="RSA";
public static final String RSA_PUBLIC_KEY="RSA_PUBLIC_KEY";
public static final String RSA_PRIVATE_KEY="RSA_PRIVATE_KEY";
public static final String SIGNATURE_ALGRITHM="SHA1withRSA";
/**
* 生成公私秘钥对
*/
public static Map initKey() throws Exception{
KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA");
KeyPair keyPair=keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey=(RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();
Map keyMap=new HashMap<>();
keyMap.put(RSA_PUBLIC_KEY, publicKey);
keyMap.put(RSA_PRIVATE_KEY, privateKey);
return keyMap;
}
public static byte[] getPublicKey(Map keyMap) {
RSAPublicKey publicKey=(RSAPublicKey) keyMap.get(RSA_PUBLIC_KEY);
return publicKey.getEncoded();
}
public static byte[] getPrivateKey(Map keyMap) {
RSAPrivateKey privateKey=(RSAPrivateKey) keyMap.get(RSA_PRIVATE_KEY);
return privateKey.getEncoded();
}
/**
* 对原始数据用私钥进行数字签名
*/
public static byte[] sign(byte[] data,byte[] privateKey) throws Exception{
PKCS8EncodedKeySpec keySpec=new PKCS8EncodedKeySpec(privateKey);
KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey priKey=keyFactory.generatePrivate(keySpec);
Signature signature=Signature.getInstance(SIGNATURE_ALGRITHM);
signature.initSign(priKey);
signature.update(data);
return signature.sign();
}
/**
* 根据原始的数据、公钥、签名进行验证
*/
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.getInstance(SIGNATURE_ALGRITHM);
signature.initVerify(pubKey);
signature.update(data);
boolean isValid=signature.verify(sign);
return isValid;
}
public static void main(Stringp[] args){
//Test RSASiganture
//初始化秘钥对
Map keyMap=RSASigatureUtil.initKey();
byte[] rsaPublicKey=RSASigatureUtil.getPublicKey(keyMap);
byte[] rsaPrivateKey=RSASigatureUtil.getPrivateKey(keyMap);
System.out.println("RSASignature PublicKey:"+BytesToHex.fromBytesToHex(rsaPublicKey));
System.out.println("RSASignature PrivateKey:"+BytesToHex.fromBytesToHex(rsaPrivateKey));
//Sign
byte[] sign=RSASigatureUtil.sign(DATA.getBytes(), rsaPrivateKey);
System.out.println("RSA Sign:"+BytesToHex.fromBytesToHex(sign));
//Verify
boolean isValid=RSASigatureUtil.verify(DATA.getBytes(), rsaPublicKey, sign);
System.out.println("RSA Verify:"+isValid);
}
}
DSASignature 算法的编程使用
1.DSA 签名算法概念
DSA 算法实现就是 RSA 数字签名算法实现的简装版,仅支持 SHA 系列算法
2.DSA 签名算法分类(JDK实现)
SHA1withDSA
3.编程实现
package key.base64;
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 java.util.HashMap;
import java.util.Map;
public class DSASignatureUtil {
public static final String KEY_ALGORITHM="DSA";
public static final int KEY_SIZE=1024;
public static final String DSA_PUBLIC_KEY="DSA_PUBLIC_KEY";
public static final String DSA_PRIVATE_KEY="DSA_PRIVATE_KEY";
public static final String SIGNATURE_ALGORITHM="SHA1withDSA";
/**
* 生成公私钥秘钥对
*/
public static Map initKey() throws Exception {
KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
KeyPair keyPair=keyPairGenerator.generateKeyPair();
DSAPublicKey publicKeyp=(DSAPublicKey) keyPair.getPublic();
DSAPrivateKey privateKey=(DSAPrivateKey) keyPair.getPrivate();
Map keyMap=new HashMap<>();
keyMap.put(DSA_PUBLIC_KEY, publicKeyp);
keyMap.put(DSA_PRIVATE_KEY, privateKey);
return keyMap;
}
public static byte[] getPublicKey(Map keyMap) {
DSAPublicKey key=(DSAPublicKey) keyMap.get(DSA_PUBLIC_KEY);
return key.getEncoded();
}
public static byte[] getPrivateKey(Map keyMap) {
DSAPrivateKey key=(DSAPrivateKey) keyMap.get(DSA_PRIVATE_KEY);
return key.getEncoded();
}
/**
* 对原始数据用私钥进行签名
*/
public static byte[] sign(byte[] data,byte[] privateKey) throws Exception{
PKCS8EncodedKeySpec keySpec=new PKCS8EncodedKeySpec(privateKey);
KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey prikey=keyFactory.generatePrivate(keySpec);
Signature signature=Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(prikey);
signature.update(data);
return signature.sign();
}
/**
* 根据原始数据、公钥、签名值进行验证
*/
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.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
boolean isValid=signature.verify(sign);
return isValid;
}
public static void main(String[] args){
//初始化秘钥对
Map keyMap=DSASignatureUtil.initKey();
byte[] dsaPublicKey=DSASignatureUtil.getPublicKey(keyMap);
byte[] dsaPrivateKey=DSASignatureUtil.getPrivateKey(keyMap);
System.out.println("DSASignature PublicKey:"+BytesToHex.fromBytesToHex(dsaPublicKey));;
System.out.println("DSASignature PrivateKey:"+BytesToHex.fromBytesToHex(dsaPrivateKey));;
//Sign
byte[] sign=DSASignatureUtil.sign(DATA.getBytes(), dsaPrivateKey);
System.out.println("DSA Sign:"+BytesToHex.fromBytesToHex(sign));;
//Verify
boolean isValid=DSASignatureUtil.verify(DATA.getBytes(), dsaPublicKey, sign);
System.out.println("DSA Sign:"+isValid);
}
}