RSA签名算法 - Java加密与安全
生活随笔
收集整理的這篇文章主要介紹了
RSA签名算法 - Java加密与安全
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
RSA簽名算法在非對稱加密中我們可以看到,甲乙雙方要進行通信,用publicKey進行加密,用priavteKey解密,這個時候會出現(xiàn)一個問題,如果黑客用你的publicKey對消息進行加密,然后冒充甲發(fā)送給乙,乙怎么確定這個消息是甲發(fā)送,還是有人偽造甲發(fā)送的呢,所以我們就需要數(shù)字簽證算法,發(fā)送加密消息的時候同時需要發(fā)送簽名,而這個簽名是需要甲的privateKey計算的,而乙要驗證這個簽名,是否是合法的,它會用甲的publicKey進行驗證,如果驗證成功,證明這個消息確實是甲發(fā)送的
數(shù)字簽名就是發(fā)送方用自己的私鑰對消息進行簽名,然后接受方用發(fā)送方的私鑰來驗證簽名是否有效,我們可以把數(shù)字簽名混入了公鑰和私鑰的一種摘要,publicKey和原始簽名和message著三個中的任何一個被修改了,簽名都是無效的數(shù)字簽名的目的是:1. 確認信息是某個發(fā)送方發(fā)送的,因為只有他用自己的privateKey簽名,其他人才能用它的publicKey去驗證這個簽名2. 發(fā)送方還不能抵賴他發(fā)送了消息,因為用誰的publicKey成功驗證的簽名,就一定是誰用privateKey簽名的,所以privateKey就相當于用戶的身份3. 最后數(shù)字簽名保證在傳輸過程中沒有被修改常用的數(shù)字簽名算法有:1. MD5WithRSA2. SHA1WithRSA3. SHA256WithRSA
package com.learn.securl;import java.security.GeneralSecurityException;
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.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;/*** 使用RSA簽名算法的時候* 我們同樣要生成privateKey和publicKey* @author Leon.Sun**/
public class SecRSASignature {PrivateKey sk;PublicKey pk;/*** 生成公鑰/私鑰對* @throws GeneralSecurityException*/public SecRSASignature() throws GeneralSecurityException{/*** 生成KeyPair的方法和使用RSA加密是一樣的*/KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");kpGen.initialize(1024);KeyPair kp = kpGen.generateKeyPair();this.sk = kp.getPrivate();this.pk = kp.getPublic();}/*** 從以保存的字節(jié)中(例如:讀取文件)恢復公鑰/私鑰* @param pk* @param sk* @throws GeneralSecurityException*/public SecRSASignature(byte[] pk, byte[] sk) throws GeneralSecurityException{KeyFactory kf = KeyFactory.getInstance("RSA");X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(pk);this.pk = kf.generatePublic(pkSpec);PKCS8EncodedKeySpec skSpec = new PKCS8EncodedKeySpec(sk);this.sk = kf.generatePrivate(skSpec);}/*** 把私鑰導出為字節(jié)* @return*/public byte[] getProvateKey(){return this.sk.getEncoded();}/*** 把公鑰導出為字節(jié)* @return*/public byte[] getPublicKey(){return this.pk.getEncoded();}/*** sign by sk* 然后我們定義一個sign方法* 用于對數(shù)據(jù)進行簽名* 當我們使用簽名算法的時候* @param message* @return* @throws GeneralSecurityException*/public byte[] sign(byte[] message) throws GeneralSecurityException{/*** 我們首先通過Signature.getInstance* 然后傳入簽名算法的算法名稱* 這里我們使用SHA1withRSA* 我們就得到一個Signature對象*/Signature signature = Signature.getInstance("SHA1withRSA");/*** 然后我們調(diào)用initSign* 傳入我們的privateKey* 初始化一個簽名*/signature.initSign(this.sk);/*** 緊接著我們用update方法傳入一個消息* 表示這個消息進行簽名*/signature.update(message);/*** 接著我們用signature的sign方法* 就可以獲得簽名以后的字節(jié)*/return signature.sign();}/*** sign by pk* 我們再定義一個verify方法來驗證簽名* 驗證簽名的時候* 我們需要傳入原始信息和簽名信息* @param message* @param sign* @return* @throws GeneralSecurityException*/public boolean verify(byte[] message, byte[] sign) throws GeneralSecurityException{/*** 同樣我們調(diào)用Signature.getInstance* 然后傳入SHA1withRSA* 獲得一個Signature對象*/Signature signature = Signature.getInstance("SHA1withRSA");/*** 這個時候我們要調(diào)用initVerify* 然后傳入publicKey* 表示我們要驗證的簽名* 驗證簽名只能使用publicKey*/signature.initVerify(this.pk);/*** 然后我們傳入原始的信息*/signature.update(message);/*** 最后我們調(diào)用verigy并傳入簽名信息* 表示對簽名進行驗證* 簽名的結果為true或者false*/return signature.verify(sign);}/*** 現(xiàn)在我們用main來對RSA簽名進行測試* @param args* @throws Exception*/public static void main(String[] args) throws Exception{byte[] message = "Hello, 使用SHA1withRSA算法進行數(shù)字簽名!".getBytes();SecRSASignature rsas = new SecRSASignature();/*** 我們首先通過sign方法對信息進行簽名*/byte[] sign = rsas.sign(message);/*** 然后打印出簽名的結果*/System.out.println("sign: " + Base64.getEncoder().encodeToString(sign));/*** 然后我們通過verify方法對信息和簽名進行驗證*/boolean verified = rsas.verify(message, sign);/*** 然后打印出簽名的結果* * verify: true* 我們用原始的公鑰進行的簽名結果為true,*/System.out.println("verify: " + verified);// 用另一個公鑰驗證:/*** 如果我們創(chuàng)建另一個Signature對象* 然后用另一個公鑰去驗證*/boolean verified2 = new SecRSASignature().verify(message, sign);/*** 我們可以看到驗證的結果為false* * verify with another public key: false* 我們用另一個publicKey進行的簽名結果為false*/System.out.println("verify with another public key: " + verified2);// 修改原始信息:/*** 當我們把原始信息修改為一個字節(jié)的時候*/message[0] = 100;/*** 我們再對信息和簽名進行驗證* 我們可以看到改正過的信息驗證的結果也應該為false* * verify changed message: false* 我們對原始信息進行的改動結果為false*/boolean verified3 = rsas.verify(message, sign);System.out.println("verify changed message: " + verified3);}
}
現(xiàn)在我們總結一下:1. 數(shù)字前面就是用發(fā)送方的私鑰對原始數(shù)據(jù)進行簽名2. 只有用發(fā)送方的公鑰才能通過簽名驗證,這樣做的目的是為了防止偽造發(fā)送方,防止抵賴發(fā)送過信息,防止發(fā)送信息發(fā)送過程中被修改3. 常用的算法有:MD5withRSA,SHA1withRSA,SHA256withRSA
?
總結
以上是生活随笔為你收集整理的RSA签名算法 - Java加密与安全的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 非对称加密算法 - Java加密与安全
- 下一篇: DSA签名算法 - Java加密与安全