1. 程式人生 > >Java端和JS端的AES加密解密同步

Java端和JS端的AES加密解密同步

Java端和JS端的AES加密演算法同步
公司要求登入時使用者名稱和密碼必須先加密,再將資料傳送到伺服器。由於這種加密必須要求是可逆的,所以不能用MD5來加密,MD5不是可逆的。後臺選擇了用AES加密。然後問題就是如何跟公司的Java演算法得到同樣的結果。
後來在搜尋了很多演算法後,發現瞭解決方案,改動公司的演算法,然後就可以輕鬆匹配了。
• Java端的演算法:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import
sun.misc.BASE64Decoder; public class Encryption { public static void main(String args[]) throws Exception { System.out.println("encrypted: "+encrypt()); System.out.println("decrypted: "+desEncrypt().trim()); } public static String encrypt() throws Exception { try { String data = "123456"
; String key = "1234567812345678"; String iv = "1234567812345678"; Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); int blockSize = cipher.getBlockSize(); byte[] dataBytes = data.getBytes(); int plaintextLength = dataBytes.length; if (plaintextLength % blockSize != 0
) { plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize)); } byte[] plaintext = new byte[plaintextLength]; System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length); SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); byte[] encrypted = cipher.doFinal(plaintext); return new sun.misc.BASE64Encoder().encode(encrypted); } catch (Exception e) { e.printStackTrace(); return null; } } public static String desEncrypt() throws Exception { String encrypted = encrypt() ; try { String data = encrypted ; String key = "1234567812345678"; String iv = "1234567812345678"; byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data); Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); byte[] original = cipher.doFinal(encrypted1); String originalString = new String(original); return originalString; } catch (Exception e) { e.printStackTrace(); return null; } } }

演算法得到的結果為:

encrypted: aK7+UX24ttBgfTnAndz9aQ==
decrypted: 123456

• React native 裡的處理
需要的庫為 crypto-js

import CryptoJS from 'crypto-js';

程式碼如下:

encryptFun() {
    var data = "123456";
    var key  = CryptoJS.enc.Latin1.parse('1234567812345678');
    var iv   = CryptoJS.enc.Latin1.parse('1234567812345678');  
    //加密
    var encrypted = CryptoJS.AES.encrypt(
      data,
      key,
      {iv:iv,mode:CryptoJS.mode.CBC,padding:CryptoJS.pad.ZeroPadding
    });
    console.log('encrypted: ' + encrypted) ;
    //解密
    var decrypted = CryptoJS.AES.decrypt(encrypted,key,{iv:iv,padding:CryptoJS.pad.ZeroPadding});
    console.log('decrypted: '+decrypted.toString(CryptoJS.enc.Utf8));
  }

Your Java code uses the 128-bit AES key while your JavaScript code
uses the 256-bit AES key. Your Java code uses the
“Abcdefghijklmnop”.getBytes() as the actual key value, while your
JavaScript code uses the “Abcdefghijklmnop” as the passphrase from
which the actual key is derived. The default transformation for Java
AES is AES/ECB/PKCS5Padding, while default transformation for CryptoJS
is AES/CBC/PKCS7Padding.

這個讓我知道一些預設的格式轉換問題。不過徹底解決問題的還是下面的這個網站:
AES加密CBC模式相容互通四種程式語言平臺【PHP、Javascript、Java、C#】
http://my.oschina.net/Jacker/blog/86383
肯定有更多的解決方案,只是我還沒懂。還得多學習。