您的位置:首页 > 编程语言 > Java开发

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

2016-07-13 23:02 507 查看
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));
}


得到的结果跟java里相同。这样就同步种语言的加密了。

期间参考了很多资料,比如SO上一篇:

http://stackoverflow.com/questions/22607791/aes-encryption-using-java-and-decryption-using-javascript

里面写到

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

肯定有更多的解决方案,只是我还没懂。还得多学习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 加密 解密 js rn