【转】js 原生 aes rsa 加解密 及 CryptoJS 加解密

本文介绍了如何使用JavaScript原生API和CryptoJS库进行AES和RSA加解密操作。示例代码包括了创建密钥对、加密解密过程,以及在不同环境下的加解密实现,如浏览器端和Java端。
摘要由CSDN通过智能技术生成

 

http://www.oschina.net/code/snippet_552425_46178

 

<!doctype html>

<html>

    <head>

        <meta charset='UTF-8'>

    </head>

    <body>

        <div class='test'></div>

        <script type="text/javascript">

 

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

                    });

                });

            })

 

        </script>

    </body>

</html>

 

---------------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html>

<head>

<meta http-equiv=Content-Type content="text/html;charset=utf-8">

<meta charset="=utf-8"/>

<script type="text/javascript" src = 'crypto-js.js'></script>

<script type="text/javascript">

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

</script>

</head>

<body>

</body>

</html>

 

-------------------------------------------------------------------------------------------------

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

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值