整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          原創|RSA加密詳解,京東登錄頁面都在用的加密有什么好?

          在以前的一個項目中,覺得登錄注冊的加密方式不安全,需要改造一下,就用到了RSA加密。網上都說它是最安全的,現有的技術是無法破解的。我知道的京東的登錄和國壽的登錄都是用的這個加密。我想整理一下,肯定會有人用的到的。

          • RSA加密的介紹
          • RSA加密的好處
          • RSA加密和解密的講解
          • RSA簽名和驗簽的講解
          • RSA測試
          • RSA加密的應用

          一、RSA加密的介紹

          RSA加密算法是一種非對稱加密算法。在公開密鑰加密和電子商業中RSA被廣泛使用。RSA是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當時他們三人都在麻省理工學院工作。RSA就是他們三人姓氏開頭字母拼在一起組成的。

          對極大整數做因數分解的難度決定了RSA算法的可靠性。換言之,對一極大整數做因數分解愈困難,RSA算法愈可靠。假如有人找到一種快速因數分解的算法的話,那么用RSA加密的信息的可靠性就肯定會極度下降。但找到這樣的算法的可能性是非常小的。今天只有短的RSA鑰匙才可能被強力方式解破。到目前為止,世界上還沒有任何可靠的攻擊RSA算法的方式。只要其鑰匙的長度足夠長,用RSA加密的信息實際上是不能被解破的。

          二、RSA加密的好處

          要說它的好處,覺得有必要先說一下常用的幾種加密的方式的劣勢。

          MD5加密在開發中用的比較多,一般應用在登錄密碼的加密或者接口的驗簽。同樣的參數,它的加密結果是一樣的,如果密碼相對簡單,被盜取的話,通過大數據是可以查詢的你的銘文密碼的。因為它是不可解密的,所以在接口也只能作為驗簽使用,而不能對數據進行加密傳輸。

          base64加密因為是可以反解密的,所以它就談不上安全了。

          AES加密是我們接口對接一直在用的,它是對稱加密,要求key是一樣的,容易造成key的泄露。沒有RES加密顯的安全。

          RSA加密,它是非對稱的加密算法,也就是加密的秘鑰(公鑰)和解密的秘鑰(私鑰)是不一樣的。并且相同的參數每次加密的結果都不一樣,這樣可以保證你的數據即使被盜取了,也沒有辦法通過大數據的方法到你的明文數據。在對接的過程中,暴露的永遠是你的公鑰,所以數據是絕對安全的。

          三、RSA加密的講解

          加密是為了防止信息泄露。

          RSA加密的公鑰和私鑰的長度是可以定義的,目前是沒有上限。主流密鑰長度至少都是1024bits以上,也就是最少128個字節(Bytes),少于這個長度會有安全問題。

          RSA加密明文的長度不能大于秘鑰的長度,但是由于明文長度小于秘鑰長度的時候,需要進行填充(padding)占用11字節,所以0<加密明文的長度<秘鑰長度-1

          這里我們定義秘鑰的長度為1024bits

          //RSA最大加密明文大小
          private static final int MAX_ENCRYPT_BLOCK = 117;
          // RSA最大解密密文大小
          private static final int MAX_DECRYPT_BLOCK = 128;
          // 獲取密鑰對
          public static KeyPair getKeyPair() throws Exception {
           KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
           generator.initialize(1024);//定義秘鑰長度為1024
           return generator.generateKeyPair();
          }
           
          // 獲取私鑰
          public static PrivateKey getPrivateKey(String privateKey) throws Exception {
           KeyFactory keyFactory = KeyFactory.getInstance("RSA");
           byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
           PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
           return keyFactory.generatePrivate(keySpec);
           }
           
          //獲取公鑰
          public static PublicKey getPublicKey(String publicKey) throws Exception {
           KeyFactory keyFactory = KeyFactory.getInstance("RSA");
           byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
           X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
           return keyFactory.generatePublic(keySpec);
           }
          

          因為加密的明文長度不能大于117,所以長度大于117的明文,可以分段加密和解密。

          //RSA加密
           public static String encrypt(String data, PublicKey publicKey) throws Exception {
           Cipher cipher = Cipher.getInstance("RSA");
           cipher.init(Cipher.ENCRYPT_MODE, publicKey);
           int inputLen = data.getBytes().length;
           ByteArrayOutputStream out = new ByteArrayOutputStream();
           int offset = 0;
           byte[] cache;
           int i = 0;
           // 對數據分段加密
           while (inputLen - offset > 0) {
           if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
           cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
           } else {
           cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
           }
           out.write(cache, 0, cache.length);
           i++;
           offset = i * MAX_ENCRYPT_BLOCK;
           }
           byte[] encryptedData = out.toByteArray();
           out.close();
           // 獲取加密內容使用base64進行編碼,并以UTF-8為標準轉化成字符串
           // 加密后的字符串
           return new String(Base64.encodeBase64String(encryptedData));
          }
           
           //RSA解密
           public static String decrypt(String data, PrivateKey privateKey) throws Exception {
           Cipher cipher = Cipher.getInstance("RSA");
           cipher.init(Cipher.DECRYPT_MODE, privateKey);
           byte[] dataBytes = Base64.decodeBase64(data);
           int inputLen = dataBytes.length;
           ByteArrayOutputStream out = new ByteArrayOutputStream();
           int offset = 0;
           byte[] cache;
           int i = 0;
           // 對數據分段解密
           while (inputLen - offset > 0) {
           if (inputLen - offset > MAX_DECRYPT_BLOCK) {
           cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
           } else {
           cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
           }
           out.write(cache, 0, cache.length);
           i++;
           offset = i * MAX_DECRYPT_BLOCK;
           }
           byte[] decryptedData = out.toByteArray();
           out.close();
           // 解密后的內容 
           return new String(decryptedData, "UTF-8");
           }
          

          四、RSA簽名的講解

          簽名是為了防止信息被串改。簽名的的公鑰的公開的。

          A給B傳遞消息,A通過私鑰把對數據加簽,形成簽名,把簽名和數據給B。

          B獲取簽名和數據,通過公鑰驗簽,如果為true,表示是A發送的消息,否則不是。


          //簽名
           public static String sign(String data, PrivateKey privateKey) throws Exception {
           byte[] keyBytes = privateKey.getEncoded();
           PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
           KeyFactory keyFactory = KeyFactory.getInstance("RSA");
           PrivateKey key = keyFactory.generatePrivate(keySpec);
           Signature signature = Signature.getInstance("MD5withRSA");
           signature.initSign(key);
           signature.update(data.getBytes());
           return new String(Base64.encodeBase64(signature.sign()));
           }
           
          //驗簽
           public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
           byte[] keyBytes = publicKey.getEncoded();
           X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
           KeyFactory keyFactory = KeyFactory.getInstance("RSA");
           PublicKey key = keyFactory.generatePublic(keySpec);
           Signature signature = Signature.getInstance("MD5withRSA");
           signature.initVerify(key);
           signature.update(srcData.getBytes());
           return signature.verify(Base64.decodeBase64(sign.getBytes()));
           }
          

          注意:修改秘鑰長度,需要同步修改最大解密密文大小

          五、RSA測試

          public static void main(String[] args) {
           try {
           // 生成密鑰對
           KeyPair keyPair = getKeyPair();
           String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
           System.out.println("私鑰:" + privateKey);
           String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
           System.out.println("公鑰:" + publicKey);
           // RSA加密
           String data = "小名登錄密碼";
           String encryptData = encrypt(data, getPublicKey(publicKey));
           System.out.println("加密后內容:" + encryptData);
           // RSA解密
           String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
           System.out.println("解密后內容:" + decryptData);
           
           // RSA簽名
           String sign = sign(data, getPrivateKey(privateKey));
           // RSA驗簽
           boolean result = verify(data, getPublicKey(publicKey), sign);
           System.out.print("驗簽結果:" + result);
           } catch (Exception e) {
           e.printStackTrace();
           System.out.print("加解密異常");
           }
           }
          

          結果

          六、RSA加密的應用

          因為jsencrypt.min.js對RSA作了很好的封裝,我們可以在前端頁面直接引用使用。

          前端js加密


          <script src="/Resource/js/jsencrypt.min.js"></script>
          <script type="text/javascript">
          function to_login(){
           var userAccount = $('#userAccount').val();
           var password = $('#password').val();
           if(userAccount==""||password==""){
           alert("用戶名或者密碼不能為空!");
           return;
           }
           $.ajax({
           type : 'POST',
           dataType : 'json',
           url : ' ${contextPath}/customer/to/loginTest',
           data : {
           userAccount :userAccount,
           password :getEntryptPwd(password)
           },
           success: function(data){
           if(data.result == -1){ 
           alert(data.msg);
           }else if(data.result == 2){
           alert("驗證成功");
           return;
           }
           }
           });
          }
          function getEntryptPwd(pwd){
           var pubKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC50/mvgdowH3nC5XOYQya'+
           'G78kYmws4b/1KJCb9zG85IJf2cmZ+9sJS80jYLRjuqFQfwwixhibLjshp4bZirvR8jIkf9yti9'+
           'HSGF1pHqNVag2HNyEbFFJ13c7lI+3LN5/0dByoIB3g/80R6kVMhAShzYRE6EfhBCoap6fzZfJu3QIDAQAB';
           var encrypt = new JSEncrypt();
           encrypt.setPublicKey(pubKey);
           return encrypt.encrypt(pwd);
          }
          </script>
          

          解密參考上面的解密就可以了

          京東的登錄頁面



          搞定!!!

          錄接口用了RSA加密,但在JMeter中實現時遇到問題。開發提供了JavaScript文件含有RSA公鑰,但使用腳本和公鑰無法成功加密密碼。解決步驟包括確認公鑰正確性,檢查腳本實現,考慮使用JMeter插件,模擬瀏覽器行為,查看加密庫和算法,處理測試環境問題,逐步調試,考慮使用其他工具,以及使用預處理器和后處理器。與開發人員保持溝通,耐心嘗試和調整是解決問題的關鍵。

          如果你正在使用 JMeter 進行登錄接口測試,而登錄接口使用了 RSA 加密,你需要確保在 JMeter 中正確地實現 RSA 加密過程。以下是一些步驟和注意事項,希望能夠幫助你解決問題:

          1. 確保使用正確的公鑰: 確保你使用的是開發人員提供的正確的 RSA 公鑰。可能有一些格式轉換或者復制粘貼的問題,導致公鑰不正確。你可以仔細檢查一下公鑰是否與開發人員提供的一致。
          2. 檢查腳本是否正確: 你提到開發人員給了一個 JavaScript 文件,這可能包含了加密的邏輯。確保你正確地將這個邏輯轉換為 JMeter 腳本。可能需要了解 JavaScript 中的 RSA 加密算法,并在 JMeter 中模擬相同的操作。
          3. 使用適當的 JMeter 插件: 如果默認的 JMeter 不支持 RSA 加密,你可能需要考慮使用一些第三方的 JMeter 插件。有一些插件專門用于處理加密和安全性問題,例如 "jp@gc - SSH Protocol Support" 或 "UBIK LOAD PACK - JSR223 RSA Sampler"。
          4. 了解服務器端要求: 有時候,服務器可能對請求有一些特殊的要求,比如要求在請求頭中包含某些信息。確保你的請求符合服務器的要求。
          5. 日志和錯誤消息: 查看 JMeter 的日志和錯誤消息,看是否有任何有用的信息,可以幫助你找出問題所在。
          6. 與開發人員溝通: 如果以上步驟都沒有解決問題,最好的方法是與開發人員溝通。他們可能能夠提供更多的信息,幫助你找到問題的根本原因。
          7. 模擬瀏覽器行為: 在進行登錄接口測試時,盡量模擬真實的用戶行為。使用瀏覽器開發者工具觀察網絡請求,尤其是登錄請求,以確保你的 JMeter 腳本與瀏覽器行為一致。這有助于排除可能的差異。
          8. 查看加密庫和算法: 如果開發人員提供的 JavaScript 文件中包含了使用特定的加密庫或算法,確保在 JMeter 中使用相同的加密庫或算法。如果有可能,嘗試在 JMeter 中引入相應的 JavaScript 庫或邏輯,以確保一致性。
          9. 測試環境問題: 確保你的測試環境與實際生產環境一致。有時候,測試環境與生產環境可能存在差異,可能是配置、版本或其他方面的問題。
          10. 考慮使用其他工具: 如果在 JMeter 中無法解決問題,可以考慮使用其他工具,如 Postman 或 Gatling,這些工具可能對特定的加密算法有更好的支持。
          11. 逐步調試: 可以逐步調試你的腳本,觀察每一步的輸出和請求,找出問題發生的具體步驟。這樣可以縮小排查范圍,更容易找到問題所在。
          12. 考慮使用預處理器和后處理器: 在 JMeter 中,你可以使用預處理器和后處理器來處理請求和響應。這些組件可以用于在發送請求之前或之后執行一些自定義邏輯,可能有助于解決加密相關的問題。

          優點:

          1. 安全性提高: 使用RSA加密可以提高數據傳輸的安全性,特別是在敏感信息(如密碼)傳輸的場景下,有效保護用戶數據免受惡意攻擊。
          2. 開發靈活性: 采用RSA加密,開發人員可以在前端實現加密過程,使得后端不需要存儲用戶的明文密碼,提高了系統的安全性。
          3. 符合安全標準: 在某些行業或法規中,對于用戶數據的保護有著嚴格的要求,采用RSA等加密算法是符合這些標準的有效手段。

          不足:

          1. 復雜性增加: RSA加密算法相對較復雜,特別是在實現時需要正確處理密鑰、填充、簽名等細節。這可能導致在測試過程中或在實際應用中出現難以解決的問題。
          2. 性能開銷: RSA加密相對于對稱加密來說,通常具有更大的計算開銷。在高并發或需要低延遲的系統中,可能對性能產生一定的影響。
          3. 維護難度: 如果系統中涉及到密鑰的定期更新、失效、或者其他維護操作,可能需要額外的管理工作,增加了系統的復雜性。
          4. 前后端協調: RSA加密通常需要前后端協同工作,確保加密、解密過程的一致性。如果在這個過程中出現不一致或誤解,可能導致登錄失敗或者數據丟失等問題。

          主站蜘蛛池模板: 日韩免费观看一区| 亚洲AV无码一区东京热久久| 亚洲一区二区三区久久| 国产成人一区二区三区免费视频 | 天堂va视频一区二区| 亚洲一区二区三区香蕉| 性色AV一区二区三区无码| 亚洲国产成人一区二区三区| 理论亚洲区美一区二区三区| 久久综合亚洲色一区二区三区| 激情综合丝袜美女一区二区| 亚洲午夜精品一区二区| 国产精品福利区一区二区三区四区 | 国产精品一区二区久久精品涩爱| 国产在线无码一区二区三区视频| 高清在线一区二区| 无码一区二区三区免费视频| 日韩精品一区二区三区色欲AV| 免费一区二区无码东京热| 亚洲男人的天堂一区二区| 国产精品视频一区国模私拍| 国产成人精品久久一区二区三区| 国产成人久久精品一区二区三区| 一区二区三区在线看| 精品一区二区三区免费毛片| 国产成人精品一区二区A片带套 | 亚洲va乱码一区二区三区| 无码人妻久久一区二区三区免费| 国产精品一区二区av| 国产剧情国产精品一区| 无码人妻精品一区二区三区在线| 日韩视频一区二区三区| 日韩精品一区二区三区中文| 无码人妻AⅤ一区二区三区| 久久亚洲日韩精品一区二区三区 | 春暖花开亚洲性无区一区二区 | 亚洲高清美女一区二区三区| 91无码人妻精品一区二区三区L| 中文字幕日韩一区二区三区不卡| 亚洲国产精品综合一区在线| 国产自产对白一区|