cryptojs支持rsa加密_【转】js 原生 aes rsa 加解密 及 CryptoJS 加解密

本文展示了如何使用 JavaScript 实现 RSA 和 AES 的加密与解密操作,结合了 CryptoJS 库和 Web Cryptography API。通过示例代码,演示了加密和解密过程,以及与 Java 端的加密解密代码对应的部分。
摘要由CSDN通过智能技术生成

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);

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值