① jsencrypt實現前端RSA非對稱加密解密(vue項目)
最近一個vue項目要求所有密碼數據需要使用RSA非對稱加密傳輸,以為挺簡單,結果開發過程中還是遇到了些問題,簡單做個筆記。同時也希望可以幫助到遇到同樣問題的道友門。
重點來了:使用jsencrypt實現RSA非對稱加解密
因為這里直接在前端加解密,所以需要一對現成的密鑰,我們通過 密鑰在線生成器 得到:
然後在需要使用的文件中引入JSEncrypt,我是將所有工具函數都封裝在一個js文件的,我就直接在該文件中引入,我看也有人是在main.js中引入的。
到這里我們的加密解密方法就完成了,在需要的地方直接拿過來用就好了!
大功告成!這樣就完了?我以為這樣就ok了。
當然,如果沒有遇到這個bug,就可以忽略下面的內容了。
從上面截圖可以看到,重啟項目的時候報錯: navigator is not defined
而且這個bug有點奇葩,先啟動項目再引入jsencrypt就什麼問題都沒有,但是先引入jsencrypt再啟動項目就報錯。這也是我前面能順利執行的原因所在。
通過好一通折騰,用了網上的各種方法,比如在main.js引入jsencrypt、引入jsdom之類的,都沒能解決這個問題,最終還是在jsencrypt的git相關 issue 下找到了這個問題的解決方案。
到這里問題就算基本解決了,但是由於項目組不止我一個前端,我不能要求每個同事或者以後接手維護項目的同事都要在node_moles中去替換文件。
所以就採用了另外一種方案:將jsencrypt.js通過在線js壓縮器壓縮至jsencrypt.min.js中,然後把jsencrypt.min.js放到src/assets/jsencrypt文件夾中,就不用npm install的方式了。
換了種方式,jsencrypt的引用方式需要做出相應的調整:
參考鏈接: RSA非對稱加密傳輸---前端加密&解密(VUE項目)
https://github.com/travist/jsencrypt/issues/144
PS:才疏學淺,如果有考慮不周之處或者有更好的解決方案,歡迎指正探討!
② RSA 加密演算法(原理篇)
前幾天看到一句話,「我們中的很多人把一生中最燦爛的笑容大部分都獻給了手機和電腦屏幕」。心中一驚,這說明了什麼?手機和電腦已經成為了我們生活中的一部分,所以才會有最懂你的不是你,也不是你男朋友,而是大數據。
如此重要的個人數據,怎樣才能保證其在互聯網上的安全傳輸呢?當然要靠各種加密演算法。說起加密演算法,大家都知道有哈希、對稱加密和非對稱加密了。哈希是一個散列函數,具有不可逆操作;對稱加密即加密和解密使用同一個密鑰,而非對稱加密加密和解密自然就是兩個密鑰了。稍微深入一些的,還要說出非對稱加密演算法有DES、3DES、RC4等,非對稱加密演算法自然就是RSA了。那麼當我們聊起RSA時,我們又在聊些什麼呢?今天筆者和大家一起探討一下,有不足的地方,還望各位朋友多多提意見,共同進步。
RSA簡介:1976年由麻省理工學院三位數學家共同提出的,為了紀念這一里程碑式的成就,就用他們三個人的名字首字母作為演算法的命名。即 羅納德·李維斯特 (Ron Rivest)、 阿迪·薩莫爾 (Adi Shamir)和 倫納德·阿德曼 (Leonard Adleman)。
公鑰:用於加密,驗簽。
私鑰:解密,加簽。
通常知道了公鑰和私鑰的用途以後,即可滿足基本的聊天需求了。但是我們今天的主要任務是來探究一下RSA加解密的原理。
說起加密演算法的原理部分,肯定與數學知識脫不了關系。
我們先來回憶幾個數學知識:
φn = φ(A*B)=φ(A)*φ(B)=(A-1)*(B-1)。
這個公式主要是用來計算給定一個任意的正整數n,在小於等於n的正整數中,有多少個與n構成互質的關系。
其中n=A*B,A與B互為質數,但A與B本身並不要求為質數,可以繼續展開,直至都為質數。
在最終分解完成後,即 φ(N) = φ(p1)*φ(p2)*φ(p3)... 之後,p1,p2,p3都是質數。又用到了歐拉函數的另一個特點,即當p是質數的時候,φp = p - 1。所以有了上面給出的歐拉定理公式。
舉例看一下:
計算15的歐拉函數,因為15比較小,我們可以直接看一下,小於15的正整數有 1、2、3、4、5、6、7、8、9、10、11、12、13、14。和15互質的數有1、2、4、7、8、11、13、14一共四個。
對照我們剛才的歐拉定理: 。
其他感興趣的,大家可以自己驗證。
之所以要在這里介紹歐拉函數,我們在計算公鑰和私鑰時候,會用到。
如果兩個正整數m 和 n 互質,那麼m 的 φn 次方減1,可以被n整除。
其中 .
其中當n為質數時,那麼 上面看到的公式就變成了
mod n 1.
這個公式也就是著名的 費馬小定理 了。
如果兩個正整數e和x互為質數,那麼一定存在一個整數d,不止一個,使得 e*d - 1 可以被x整除,即 e * d mode x 1。則稱 d 是 e 相對於 x的模反元素。
了解了上面所講的歐拉函數、歐拉定理和模反元素後,就要來一些化學反應了,請看圖:
上面這幅圖的公式變化有沒有沒看明白的,沒看明白的咱們評論區見哈。
最終我們得到了最重要的第5個公式的變形,即紅色箭頭後面的:
mod n m。
其中有幾個關系,需要搞明白,m 與 n 互為質數,φn = x,d 是e相對於x的模反元素。
有沒有看到一些加解密的雛形。
從 m 到 m。 這中間涵蓋了從加密到解密的整個過程,但是缺少了我們想要的密文整個過程。
OK,下面引入本文的第四個數學公式:
我們來看一下整個交換流程:
1、客戶端有一個數字13,服務端有一個數字15;
2、客戶端通過計算 3的13次方 對 17 取余,得到數字12; 將12發送給服務端;同時服務端通過計算3的15次方,對17取余,得到數字6,將6發送給客戶端。至此,整個交換過程完成。
3、服務端收到數字12以後,繼續計算,12的15次方 對 17取余,得到 數字10。
4、客戶端收到數字 6以後,繼續計算,6的13次方 對 17 取余,得到數字 10。
有沒有發現雙方,最終得到了相同的內容10。但是這個數字10從來沒有在網路過程中出現過。
好,講到這里,可能有些人已經恍然大悟,這就是加密過程了,但是也有人會產生疑問,為什麼要取數字3 和 17 呢,這里還牽涉到另一個數學知識,原根的問題。即3是17的原根。看圖
有沒有發現規律,3的1~16次方,對17取余,得到的整數是從1~16。這時我們稱3為17的原根。也就是說上面的計算過程中有一組原根的關系。這是最早的迪菲赫爾曼秘鑰交換演算法。
解決了為什麼取3和17的問題後,下面繼續來看最終的RSA是如何產生的:
還記得我們上面提到的歐拉定理嗎,其中 m 與 n 互為質數,n為質數,d 是 e 相對於 φn的模反元素。
當迪菲赫爾曼密鑰交換演算法碰上歐拉定理會產生什麼呢?
我們得到下面的推論:
好,到這里我們是不是已經看到了整個的加密和解密過程了。
其中 m 是明文;c 是密文; n 和 e 為公鑰;d 和 n 為私鑰 。
其中幾組數字的關系一定要明確:
1、d是e 相對於 φn 的模反元素,φn = n-1,即 e * d mod n = 1.
2、m 小於 n,上面在講迪菲赫爾曼密鑰交換演算法時,提到原根的問題,在RSA加密演算法中,對m和n並沒有原根條件的約束。只要滿足m與n互為質數,n為質數,且m < n就可以了。
OK,上面就是RSA加密演算法的原理了,經過上面幾個數學公式的狂轟亂炸,是不是有點迷亂了,給大家一些時間理一下,後面會和大家一起來驗證RSA演算法以及RSA為什麼安全。
③ 如何使用RSA 和 DES 演算法 對數據加密
一、混合加密的理由
a、前面提及了RSA加解密演算法和DES加解密演算法這兩種加解密演算法,由於隨著計算機系統能力的不斷發展,DES的安全性比它剛出現時會弱得多,追溯歷史破解DES的案例層出不窮,一台實際的機器可以在數天內破解DES是讓某些人相信他們不能依賴DES的安全性的唯一方法。而相對於DES,RSA的安全性則相對高些,雖然破解RSA的案例也有,但其所付出的代價是相對大的(相對DES),如今RSA的密鑰也在升級,這說明破解RSA的難度也在增大。
b、在RSA加解密演算法中提及到RSA加密明文會受密鑰的長度限制,這就說明用RSA加密的話明文長度是有限制的,而在實際情況我們要進行加密的明文長度或許會大於密鑰長度,這樣一來我們就不得不捨去RSA加密了。對此,DES加密則沒有此限制。
鑒於以上兩點(個人觀點),單獨的使用DES或RSA加密可能沒有辦法滿足實際需求,所以就採用了RSA和DES加密方法相結合的方式來實現數據的加密。
其實現方式即:
1、信息(明文)採用DES密鑰加密。
2、使用RSA加密前面的DES密鑰信息。
最終將混合信息進行傳遞。
而接收方接收到信息後:
1、用RSA解密DES密鑰信息。
2、再用RSA解密獲取到的密鑰信息解密密文信息。
最終就可以得到我們要的信息(明文)。
二、實現例子:
結合前面RSA和DES加密:
/// <summary>
/// RSA和DES混合加密
/// </summary>
/// <param name="data">待加密數據</param>
/// <param name="publicKey">RSA公鑰</param>
/// <returns></returns>
public Param Encrypt(string data, string publicKey)
{
//加密數據
DESSecurity DES = new DESSecurity();
string DESKey = DES.GenerateKey();
string encryptData = DES.Encrypt(data, DESKey);
//加密DESkey
RSASecurity RSA = new RSASecurity();
string encryptDESKey = RSA.Encrypt(DESKey, publicKey);
Param mixParam = new Param();
mixParam.DESKey = encryptDESKey;
mixParam.Data = encryptData;
return mixParam;
}
/// <summary>
/// RSA和DES混合解密
/// </summary>
/// <param name="data">待解密數據</param>
/// <param name="key">帶解密的DESKey</param>
/// <param name="privateKey">RSA私鑰</param>
/// <returns></returns>
public string Decrypt(string data, string key, string privateKey)
{
//解密DESKey
RSASecurity RSA = new RSASecurity();
string DESKey = RSA.Decrypt(key, privateKey);
//解密數據
DESSecurity DES = new DESSecurity();
return DES.Decrypt(data, DESKey);
④ java rsa私鑰加密
java rsa私鑰加密是什麼?讓我們一起來了解一下吧!
java rsa私鑰加密是一種加密演算法。私鑰加密演算法是用私鑰來進行加密與解密信息。私鑰加密也被稱作對稱加密,原因是加密與解密使用的秘鑰是同一個。
RSA加密需要注意的事項如下:
1. 首先產生公鑰與私鑰
2. 設計加密與解密的演算法
3. 私鑰加密的數據信息只能由公鑰可以解密
4. 公鑰加密的數據信息只能由私鑰可以解密
實戰演練,具體步驟如下: public class RsaCryptTools { private static final String CHARSET = "utf-8"; private static final Base64.Decoder decoder64 = Base64.getDecoder(); private static final Base64.Encoder encoder64 = Base64.getEncoder(); /** * 生成公私鑰 * @param keySize * @return * @throws NoSuchAlgorithmException */ public static SecretKey generateSecretKey(int keySize) throws NoSuchAlgorithmException { //生成密鑰對 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(keySize, new SecureRandom()); KeyPair pair = keyGen.generateKeyPair(); PrivateKey privateKey = pair.getPrivate(); PublicKey publicKey = pair.getPublic(); //這里可以將密鑰對保存到本地 return new SecretKey(encoder64.encodeToString(publicKey.getEncoded()), encoder64.encodeToString(privateKey.getEncoded())); } /** * 私鑰加密 * @param data * @param privateInfoStr * @return * @throws IOException * @throws InvalidCipherTextException */ public static String encryptData(String data, String privateInfoStr) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(privateInfoStr)); return encoder64.encodeToString(cipher.doFinal(data.getBytes(CHARSET))); } /** * 公鑰解密 * @param data * @param publicInfoStr * @return */ public static String decryptData(String data, String publicInfoStr) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException { byte[] encryptDataBytes=decoder64.decode(data.getBytes(CHARSET)); //解密 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, getPublicKey(publicInfoStr)); return new String(cipher.doFinal(encryptDataBytes), CHARSET); } private static PublicKey getPublicKey(String base64PublicKey) throws NoSuchAlgorithmException, InvalidKeySpecException { X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes())); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(keySpec); } private static PrivateKey getPrivateKey(String base64PrivateKey) throws NoSuchAlgorithmException, InvalidKeySpecException { PrivateKey privateKey = null; PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes())); KeyFactory keyFactory = null; keyFactory = KeyFactory.getInstance("RSA"); privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } /** * 密鑰實體 * @author hank * @since 2020/2/28 0028 下午 16:27 */ public static class SecretKey { /** * 公鑰 */ private String publicKey; /** * 私鑰 */ private String privateKey; public SecretKey(String publicKey, String privateKey) { this.publicKey = publicKey; this.privateKey = privateKey; } public String getPublicKey() { return publicKey; } public void setPublicKey(String publicKey) { this.publicKey = publicKey; } public String getPrivateKey() { return privateKey; } public void setPrivateKey(String privateKey) { this.privateKey = privateKey; } @Override public String toString() { return "SecretKey{" + "publicKey='" + publicKey + '\'' + ", privateKey='" + privateKey + '\'' + '}'; } } private static void writeToFile(String path, byte[] key) throws IOException { File f = new File(path); f.getParentFile().mkdirs(); try(FileOutputStream fos = new FileOutputStream(f)) { fos.write(key); fos.flush(); } } public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException { SecretKey secretKey = generateSecretKey(2048); System.out.println(secretKey); String enStr = encryptData("你好測試測試", secretKey.getPrivateKey()); System.out.println(enStr); String deStr = decryptData(enStr, secretKey.getPublicKey()); System.out.println(deStr); enStr = encryptData("你好測試測試hello", secretKey.getPrivateKey()); System.out.println(enStr); deStr = decryptData(enStr, secretKey.getPublicKey()); System.out.println(deStr); } }
⑤ uniapp rsa 加密,簽名,aes加密使用
rsa 加密
如果需要兼容微信小程序參考文檔:
https://blog.csdn.net/qq_38318589/article/details/115371454
rsa 簽名jsrsasign
rsa 加密,簽名使用創建rsa.js,在需要使用的地方導入即可。內容如下
aes加密
創建aestool.js ,內容如下
⑥ 7 Go密碼學(四) 非對稱加密之RSA
對稱加舉鉛密有非常好的安全性,其加解密計算的性能也較高,但其有兩個重要缺點:
在如今開放的信息社會,秘鑰的管理愈加困難,非公開的秘鑰機制雖然破解較難,但還是有遭到攻擊的可能性,由於對稱加密需要加解密雙方共同握有私鑰,所有生成秘鑰的一方必須分發給含轎另一方才能進行安全通行,這就難免秘鑰在網路中傳輸,網路是不可靠的,其有可能被攔截或篡改。於是就產生了公開秘鑰體制,即服務方根據特定演算法產生一對鑰匙串,自己持有私鑰小心保存,而公鑰公開分發,在通信中,由公鑰加密進行網路傳輸,而傳輸的信息只正老好能由私鑰解密,這就解決了秘鑰分發的問。公開秘鑰體制就是非對稱加密,非對稱加密一般有兩種用途:
如今的非對稱加密比較可靠的有RSA演算法和ECC演算法(橢圓曲線演算法),RSA的受眾最多,但近年來隨著比特幣、區塊鏈的興起,ECC加密演算法也越來越受到青睞。下面我們先介紹一下RSA加密演算法的使用,ECC我們下一講展開。
公鑰密碼體系都是要基於一個困難問題來保證其安全性的,RSA是基於大數分解,將一個即使是計算機也無能為力的數學問題作為安全壁壘是現代密碼學的實現原理。講述這類數學問題需要龐雜的數論基礎,此相關部分在此不再展開,感興趣的請出門右拐搜索歐幾里得證明、歐拉函數等數論部分知識。
Go標准庫中crypto/rsa包實現了RSA加解密演算法,並通過crypto/x509包實現私鑰序列化為ASN.1的DER編碼字元串的方法,我們還使用編解碼包encoding/pem(實現了PEM數據編碼,該格式源自保密增強郵件協議,目前PEM編碼主要用於TLS密鑰和證書。)將公私鑰數據編碼為pem格式的證書文件。
使用以上加解密方法: