数字签名技术 - RSA数字签名技术
RSA算法不仅是非对称加密算法,也是数字签名算法中的主力军,和MD、SHA系列算法结合,产生数字签名算法。
算法系列
RSA数字签名技术可以分为MD和SHA系列量大类,数字签名技术本身就是信息摘要和非对称加密技术的结合。
- MD系列包括:
MD2withRSA
、MD5withRSA
- SHA系列包括:
SHA1withRSA
、SHA224withRSA
、SHA256withRSA
、SHA384withRSA
、SHA512withRSA
五种。
这些算法的密钥长度都在512-65535位之间,必须是64的倍数。产生的签名长度和密钥长度一致。
算法基本过程
- 将数据使用
摘要算法
计算摘要
(hash值); - 使用
私钥
对摘要
进行加密; - 将加密数据和原始数据一起传输;
- 接收方对原始数据(要保持原始数据的序列一致性,约定好)计算
摘要
; - 使用
公钥
解密签名串
,比较二者Hash值
是否一致;
Java中的算法实现
Java中不仅仅实现了RSA算法,还实现了RSA数字签名算法,JDK仅提供了MD2withRSA
、MD5withRSA
和SHA1withRSA
三种数字签名算法。
JDK中对三种算法的默认密钥长度为1024
示例代码:
public class SignatureTest {
public static final String SIGN_ALGORITHM = "MD5withRSA";
private static final String KEY_ALGORITHM = "RSA";
private static final int KEY_SIZE = 512;
public static void main(String[] args) throws Exception {
KeyPair keyPair = initKey();
String input = "Sign Me";
byte[] sign = sign(input.getBytes(), keyPair.getPrivate().getEncoded());
boolean verify = verify(input.getBytes(), sign, keyPair.getPublic().getEncoded());
String msg = String.format("原始数据: %s , Sign : %s , Verify : %s", input, toBase64(sign), verify);
System.out.println(msg);
// 从二进制位角度看,sign的长度和密钥长度一致
System.out.println("Sign Size : " + (sign.length * 8) + " Key Size : " + KEY_SIZE);
}
public static KeyPair initKey() throws Exception {
KeyPairGenerator keyPairGr = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGr.initialize(KEY_SIZE);
KeyPair keyPair = keyPairGr.generateKeyPair();
return keyPair;
}
public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
// 将byte[]的key格式化回来
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 获取算法实例并初始化
Signature signature = Signature.getInstance(SIGN_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
byte[] sign = signature.sign();
return sign;
}
public static boolean verify(byte[] data, byte[] sign, byte[] publicKey) throws Exception {
// 获取算法实例并初始化
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
Signature signature = Signature.getInstance(SIGN_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
// 验证数据和签名是否一致,放否认,放篡改
boolean verify = signature.verify(sign);
return verify;
}
public static String toBase64(byte[] data) {
return new String(Base64.getEncoder().encode(data));
}
}