http://www.oschina.net/code/snippet_552425_46178
function encrypt(data, keyJSON){
var data = new TextEncoder("UTF-8").encode(data);
var randomsKeys = geneRandomHexStr(64); // 128 bit keys
var encryptedKey = hexStringToUint8Array(randomsKeys);
var aesAlgo = {name: 'aes-cbc', iv: hexStringToUint8Array("000102030405060708090a0b0c0d0e0f")};
return crypto.subtle.importKey("jwk", keyJSON, {name: "rsa-oaep", hash: {name: "sha-256"}},true, ['encrypt'])
.then(function(publicKey){
return crypto.subtle.encrypt({name: "rsa-oaep"}, publicKey, encryptedKey);
}).then(function(res){
encryptedKey = bytesToHexString(res)
// use aes to encrypt data
// import aes key
return crypto.subtle.importKey('raw',
hexStringToUint8Array(randomsKeys) , aesAlgo, false, ['encrypt', 'decrypt']);
}).then(function(result){
// use aes to encode
return crypto.subtle.encrypt(aesAlgo,
result, data);
}).then(function(encryptedData){
return Promise.resolve({
'encrypted': bytesToHexString(encryptedData),
'encryptedKey': encryptedKey,
});
});
//console.log(new TextDecoder("UTF-8").decode(data));
// use server public key to encrypt
}
function decrypt(data, keyJSON){
// use local private key to decrypt
var encryptedKey = new hexStringToUint8Array(data.encryptedKey);
var encryptedData = new hexStringToUint8Array(data.encrypted);
var aesAlgo = {name: 'aes-cbc', iv: hexStringToUint8Array("000102030405060708090a0b0c0d0e0f")};
// decrypt key
return crypto.subtle.importKey('jwk', keyJSON, {name: "rsa-oaep", hash: {name: "sha-256"}}, true,
['decrypt']).then(function(privateKey){
return crypto.subtle.decrypt({name: 'rsa-oaep'}, privateKey, encryptedKey);
}).then(function(decryptedKey){
// import aes key
return crypto.subtle.importKey('raw',
decryptedKey, aesAlgo, false, ['encrypt', 'decrypt']);
}).catch(function(){
console.error("decrypt error");
}).then(function(result){
// decode encrypted data
return crypto.subtle.decrypt(aesAlgo, result, encryptedData);
}).then(function(data){
return Promise.resolve(new TextDecoder("UTF-8").decode(new Uint8Array(data)));
})
}
function createNewUserKey(){
var algorithmKeyGen = {
name: "RSA-OAEP",
hash: {name: "sha-256"},
// RsaKeyGenParams
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), // Equivalent to 65537
};
var nonExtractable = false;
var publicKey = "";
var privateKey = "";
var keyPairs = "";
return crypto.subtle.generateKey(algorithmKeyGen, true, ['encrypt', 'decrypt']).then(function(result) {
// gene key pair
keyPairs = result;
return Promise.all([crypto.subtle.exportKey("jwk", keyPairs.publicKey),
crypto.subtle.exportKey("jwk", keyPairs.privateKey)]);
})
}
function _arrayBufferToBase64( buffer ) {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
}
function hexStringToUint8Array(hexString) {
if (hexString.length % 2 != 0)
throw "Invalid hexString";
var arrayBuffer = new Uint8Array(hexString.length / 2);
for (var i = 0; i < hexString.length; i += 2) {
var byteValue = parseInt(hexString.substr(i, 2), 16);
if (byteValue == NaN)
throw "Invalid hexString";
arrayBuffer[i/2] = byteValue;
}
return arrayBuffer;
}
function bytesToHexString(bytes) {
if (!bytes)
return null;
bytes = new Uint8Array(bytes);
var hexBytes = [];
for (var i = 0; i < bytes.length; ++i) {
var byteString = bytes[i].toString(16);
if (byteString.length < 2)
byteString = "0" + byteString;
hexBytes.push(byteString);
}
return hexBytes.join("");
}
function geneRandomHexStr(length){
var text = "";
var possible = "0123456789abcdef";
for( var i=0; i < length; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
createNewUserKey().then(function(keyPairs){
encrypt("this is origin text", keyPairs[0]).then(function(res){
console.log('public', JSON.stringify(keyPairs[0]));
console.log('private', JSON.stringify(keyPairs[1]));
decrypt(res, keyPairs[1]).then(function(decrypted){
console.log('decrypted', decrypted);
});
});
})
---------------------------------------------------------------------------------------------------------------------------
var key = CryptoJS.enc.Utf8.parse('1234567890123456');
var iv = CryptoJS.enc.Utf8.parse('1234567890123456');
console.log("key::"+key.toString(CryptoJS.enc.Hex));
console.log("iv::"+iv.toString(CryptoJS.enc.Hex));
var value = '你好呀你好嘛你好吗你好哦';
var encryptData = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(value), key, {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
iv:iv
});
var encryptDataHex = encryptData.ciphertext.toString(CryptoJS.enc.Hex);
console.log(encryptDataHex);
var base64 = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(encryptDataHex));
var bytes = CryptoJS.AES.decrypt(base64, key, {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
iv:iv
});
console.log("encryptedData = %s", bytes.toString(CryptoJS.enc.Utf8));
-------------------------------------------------------------------------------------------------
对应java代码
-------------------------------------------------------------------------------------------------
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.icss.regie.crypto;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
*
* @author Administrator
*/
/**
*
* @author ngh
* AES128 算法
*
* CBC 模式
*
* PKCS7Padding 填充模式
*
* CBC模式需要添加一个参数iv
*
* 介于java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别
* 要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现
*/
public class AES {
// 算法名称
final String KEY_ALGORITHM = "AES";
// 加解密算法/模式/填充方式
final String algorithmStr = "AES/CBC/PKCS7Padding";
//
private Key key;
private Cipher cipher;
boolean isInited = false;
public void init(byte[] keyBytes) {
// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
int base = 16;
if (keyBytes.length % base != 0) {
int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
keyBytes = temp;
}
// 初始化
Security.addProvider(new BouncyCastleProvider());
// 转化成JAVA的密钥格式
key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
try {
// 初始化cipher
cipher = Cipher.getInstance(algorithmStr, "BC");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 加密方法
*
* @param content
* 要加密的字符串
* @param keyBytes
* 加密密钥
* @return
*/
public byte[] encrypt(byte[] content, byte[] keyBytes,String ivParameter) {
byte[] encryptedText = null;
init(keyBytes);
System.out.println("IV:" + ivParameter);
try {
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivParameter.getBytes("utf-8")));
encryptedText = cipher.doFinal(content);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return encryptedText;
}
/**
* 解密方法
*
* @param encryptedData
* 要解密的字符串
* @param keyBytes
* 解密密钥
* @return
*/
public byte[] decrypt(byte[] encryptedData, byte[] keyBytes,String ivParameter) {
byte[] encryptedText = null;
init(keyBytes);
System.out.println("IV:" + ivParameter);
try {
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivParameter.getBytes("utf-8")));
encryptedText = cipher.doFinal(encryptedData);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return encryptedText;
}
}
------------------------------
public class Test {
public static void main(String[] args) throws UnsupportedEncodingException {
AES aes = new AES();
String sKey="1234567890123456";
String ivParameter="1234567890123456";
// 需要加密的字串
String cSrc = "你好呀你好嘛你好吗你好哦";
System.out.println("key:::"+ Test.bytesToHexString(sKey.getBytes("UTF-8")));
System.out.println("ivParameter:::"+Test.bytesToHexString(ivParameter.getBytes("UTF-8")));
System.out.println("加密前的字串是:"+cSrc);
// 加密
byte[] result = aes.encrypt(cSrc.getBytes("UTF-8"),sKey.getBytes("UTF-8"),ivParameter);
System.out.println("加密后的字串是:"+ Test.bytesToHexString(result));
System.out.println("238f93338d84edb47c544aca7f09ae25e6b867f2befbf38dbe3a95bfa487e212c915b90a7ccbb5fd0c7970ba7a975bc1".equals(Test.bytesToHexString(result)));
// 解密
byte[] DeString = aes.decrypt(result,sKey.getBytes("UTF-8"),ivParameter);
System.out.println("解密后的字串是:" + Test.bytesToHexString(DeString));
System.out.println("e4bda0e5a5bde59180e4bda0e5a5bde5989be4bda0e5a5bde59097e4bda0e5a5bde593a6".equals(Test.bytesToHexString(DeString)));
System.out.println("解密后的字串是:" + new String(DeString,Charset.forName("UTF-8")));
}
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
/**
* Convert hex string to byte[]
*
* @param hexString the hex string
* @return byte[]
*/
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
/**
* Convert char to byte
*
* @param c char
* @return byte
*/
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
}