數(shù)字簽名技術(shù) - RSA數(shù)字簽名技術(shù)
RSA算法不僅是非對稱加密算法,也是數(shù)字簽名算法中的主力軍,和MD、SHA系列算法結(jié)合,產(chǎn)生數(shù)字簽名算法。
算法系列
RSA數(shù)字簽名技術(shù)可以分為MD和SHA系列量大類,數(shù)字簽名技術(shù)本身就是信息摘要和非對稱加密技術(shù)的結(jié)合。
- MD系列包括:
MD2withRSA、MD5withRSA - SHA系列包括:
SHA1withRSA、SHA224withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA五種。
這些算法的密鑰長度都在512-65535位之間,必須是64的倍數(shù)。產(chǎn)生的簽名長度和密鑰長度一致。
算法基本過程
- 將數(shù)據(jù)使用
摘要算法計算摘要(hash值); - 使用
私鑰對摘要進行加密; - 將加密數(shù)據(jù)和原始數(shù)據(jù)一起傳輸;
- 接收方對原始數(shù)據(jù)(要保持原始數(shù)據(jù)的序列一致性,約定好)計算
摘要; - 使用
公鑰解密簽名串,比較二者Hash值是否一致;
Java中的算法實現(xiàn)
Java中不僅僅實現(xiàn)了RSA算法,還實現(xiàn)了RSA數(shù)字簽名算法,JDK僅提供了MD2withRSA、MD5withRSA和SHA1withRSA三種數(shù)字簽名算法。
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("原始數(shù)據(jù): %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);
// 驗證數(shù)據(jù)和簽名是否一致,放否認,放篡改
boolean verify = signature.verify(sign);
return verify;
}
public static String toBase64(byte[] data) {
return new String(Base64.getEncoder().encode(data));
}
}