數(shù)字簽名技術(shù) - RSA數(shù)字簽名技術(shù)
RSA算法不僅是非對(duì)稱加密算法朋其,也是數(shù)字簽名算法中的主力軍澄阳,和MD括授、SHA系列算法結(jié)合坞笙,產(chǎn)生數(shù)字簽名算法。
算法系列
RSA數(shù)字簽名技術(shù)可以分為MD和SHA系列量大類荚虚,數(shù)字簽名技術(shù)本身就是信息摘要和非對(duì)稱加密技術(shù)的結(jié)合薛夜。
- MD系列包括:
MD2withRSA
、MD5withRSA
- SHA系列包括:
SHA1withRSA
版述、SHA224withRSA
梯澜、SHA256withRSA
、SHA384withRSA
渴析、SHA512withRSA
五種腊徙。
這些算法的密鑰長度都在512-65535位之間简十,必須是64的倍數(shù)。產(chǎn)生的簽名長度和密鑰長度一致撬腾。
算法基本過程
- 將數(shù)據(jù)使用
摘要算法
計(jì)算摘要
(hash值); - 使用
私鑰
對(duì)摘要
進(jìn)行加密恢恼; - 將加密數(shù)據(jù)和原始數(shù)據(jù)一起傳輸民傻;
- 接收方對(duì)原始數(shù)據(jù)(要保持原始數(shù)據(jù)的序列一致性,約定好)計(jì)算
摘要
; - 使用
公鑰
解密簽名串
场斑,比較二者Hash值
是否一致漓踢;
Java中的算法實(shí)現(xiàn)
Java中不僅僅實(shí)現(xiàn)了RSA算法,還實(shí)現(xiàn)了RSA數(shù)字簽名算法漏隐,JDK僅提供了MD2withRSA
喧半、MD5withRSA
和SHA1withRSA
三種數(shù)字簽名算法。
JDK中對(duì)三種算法的默認(rèn)密鑰長度為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("原始數(shù)據(jù): %s , Sign : %s , Verify : %s", input, toBase64(sign), verify);
System.out.println(msg);
// 從二進(jìn)制位角度看,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);
// 獲取算法實(shí)例并初始化
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 {
// 獲取算法實(shí)例并初始化
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);
// 驗(yàn)證數(shù)據(jù)和簽名是否一致,放否認(rèn),放篡改
boolean verify = signature.verify(sign);
return verify;
}
public static String toBase64(byte[] data) {
return new String(Base64.getEncoder().encode(data));
}
}