美文网首页综合
JAVA与NodeJS实现AES加密

JAVA与NodeJS实现AES加密

作者: 飘逸峰 | 来源:发表于2018-03-09 18:31 被阅读0次

    内容要点

    本文实现java与nodejs的AES加密方式如下,并可实现java加密,nodejs解密或者nodejs加密,java解密

    • aes-128-ecb
    • aes-256-ecb
    • aes-128-cbc
    • aes-256-cbc

    java实现AES

    注意

    Java本身限制密钥的长度最多128位,而AES256需要的密钥长度是256位,因此需要到Java官网上下载一个Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files。在Java SE的下载页面下面的Additional Resources那里会有下载链接。下载后打开压缩包,里面有两个jar文件:
    local_policy.jarUS_export_policy.jar
    把这两个jar文件解压到JRE目录下的lib/security文件夹,覆盖原来的文件。这样Java就不再限制密钥的长度了,否则编译会报错:

    java.security.InvalidKeyException: Illegal key size

    import org.apache.commons.lang.StringUtils;
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.spec.AlgorithmParameterSpec;
    
    public class EncodeUtil {
    
        public static void main(String[] args) throws Exception {
            //key是16进制,需要转换为bytes,转换后bytes长度为16,即aes128,如果bytes长度是32则是aes256
            //也就是说keybytes.length须满足16的整数倍
            String key128 = "c4b84456c1379bec99c4d1b7e9f13173";
            String key256 = "c4b84456c1379bec99c4d1b7e9f13173c4b84456c1379bec99c4d1b7e9f13173";
            //iv.length须满足16的整数倍
            byte[] iv = "abcdefgh12345678".getBytes("UTF-8");
            String content_str = "helloworld 你好";
            byte[] contentbytes = content_str.getBytes("utf-8");
    
            //ecb128 bytes
            byte[] encryptbytes = EncodeUtil.aesEncryptToECB(contentbytes,key128);
            byte[] decryptbytes = EncodeUtil.aesDecryptToECB(encryptbytes,key128);
            System.out.println(new String(decryptbytes,"utf-8"));
    
            //ecb256 bytes
            encryptbytes = EncodeUtil.aesEncryptToECB(contentbytes,key256);
            decryptbytes = EncodeUtil.aesDecryptToECB(encryptbytes,key256);
            System.out.println(new String(decryptbytes,"utf-8"));
    
            //ecb128 String
            String encryptString = EncodeUtil.aesEncryptToECB(content_str,key128);
            String decryptString = EncodeUtil.aesDecryptToECB(encryptString,key128);
            System.out.println(decryptString);
    
            //ecb256 String
            encryptString = EncodeUtil.aesEncryptToECB(content_str,key256);
            decryptString = EncodeUtil.aesDecryptToECB(encryptString,key256);
            System.out.println(decryptString);
    
            //cbc128 bytes
            encryptbytes = EncodeUtil.aesEncryptToCBC(contentbytes,key128,iv);
            decryptbytes = EncodeUtil.aesDecryptToCBC(encryptbytes,key128,iv);
            System.out.println(new String(decryptbytes,"utf-8"));
    
            //cbc256 bytes
            encryptbytes = EncodeUtil.aesEncryptToCBC(contentbytes,key256,iv);
            decryptbytes = EncodeUtil.aesDecryptToCBC(encryptbytes,key256,iv);
            System.out.println(new String(decryptbytes,"utf-8"));
    
            //cbc128 String
            encryptString = EncodeUtil.aesEncryptToCBC(content_str,key128,iv);
            decryptString = EncodeUtil.aesDecryptToCBC(encryptString,key128,iv);
            System.out.println(decryptString);
    
            //cbc256 String
            encryptString = EncodeUtil.aesEncryptToCBC(content_str,key256,iv);
            decryptString = EncodeUtil.aesDecryptToCBC(encryptString,key256,iv);
            System.out.println(decryptString);
    
        }
    
        /**
         * base 64 encode
         *
         * @param bytes 待编码的byte[]
         * @return 编码后的base 64 code
         */
        public static String base64Encode(byte[] bytes) {
            return new BASE64Encoder().encode(bytes);
        }
    
        /**
         * base 64 decode
         *
         * @param base64Code 待解码的base 64 code
         * @return 解码后的byte[]
         * @throws Exception
         */
        public static byte[] base64Decode(String base64Code) throws Exception {
            return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);
        }
    
         /**
         * 验证密钥长度是否有效
         *
         * @param key 密钥bytes
         * @throws Exception
         */
        public static void checkkey(byte[] key) throws Exception {
    
            if(key.length != 16 && key.length != 32) {
                throw new Exception("密钥长度错误,key byte[]必须是16或者32位");
            }
        }
    
        /**
         * AES加密 aes-128/256-ecb
         *
         * @param content    待加密的内容
         * @param encryptKey 加密密钥
         * @return 加密后的byte[]
         * @throws Exception
         */
        public static byte[] aesEncryptToECB(byte[] content, String encryptKey) throws Exception {
            byte[] key = org.apache.commons.codec.binary.Hex.decodeHex(encryptKey.toCharArray());
            checkkey(key);
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
            return cipher.doFinal(content);
        }
    
    
    
        /**
         * AES加密 aes-128/256-ecb
         *
         * @param content    待加密的内容
         * @param encryptKey 加密密钥
         * @return 加密后的base64字符串
         * @throws Exception
         */
        public static String aesEncryptToECB(String content, String encryptKey) throws Exception {
            byte[] key = org.apache.commons.codec.binary.Hex.decodeHex(encryptKey.toCharArray());
            checkkey(key);
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
            return base64Encode(cipher.doFinal(content.getBytes("utf-8")));
        }
    
    
        /**
         * AES解密 aes-128/256-ecb
         *
         * @param content 待解密的byte[]
         * @param decryptKey   解密密钥
         * @return 解密后的byte[]
         * @throws Exception
         */
        public static byte[] aesDecryptToECB(byte[] content, String decryptKey) throws Exception {
            byte[] key = org.apache.commons.codec.binary.Hex.decodeHex(decryptKey.toCharArray());
            checkkey(key);
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
            byte[] decryptBytes = cipher.doFinal(content);
            return decryptBytes;
        }
    
    
    
        /**
         * AES解密 aes-128/256-ecb
         *
         * @param content 待解密的byte[]
         * @param decryptKey   解密密钥
         * @return 解密后的String
         * @throws Exception
         */
        public static String aesDecryptToECB(String content, String decryptKey) throws Exception {
            byte[] key = org.apache.commons.codec.binary.Hex.decodeHex(decryptKey.toCharArray());
            checkkey(key);
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
            byte[] decryptBytes = cipher.doFinal(base64Decode(content));
            return new String(decryptBytes,"utf-8");
        }
    
    
        /**
         * AES加密 aes-128/256-cbc
         *
         * @param content 待解密的byte[]
         * @param encryptKey   加密密钥
         * @param iv 偏移
         * @return 解密后的byte[]
         * @throws Exception
         */
        public static byte[] aesEncryptToCBC(byte[] content, String encryptKey,byte[] iv) throws Exception {
            byte[] key = org.apache.commons.codec.binary.Hex.decodeHex(encryptKey.toCharArray());
            checkkey(key);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //算法参数
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"),paramSpec);
            return cipher.doFinal(content);
        }
    
        /**
         * AES解密 aes-128/256-cbc
         *
         * @param content 待解密的byte[]
         * @param decryptKey   解密密钥
         * @param iv 偏移
         * @return 解密后的byte[]
         * @throws Exception
         */
        public static byte[] aesDecryptToCBC(byte[] content, String decryptKey,byte[] iv) throws Exception {
            byte[] key = org.apache.commons.codec.binary.Hex.decodeHex(decryptKey.toCharArray());
            checkkey(key);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //算法参数
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"),paramSpec);
            return cipher.doFinal(content);
        }
    
        /**
         * AES加密 aes-128/256-cbc
         *
         * @param content 待解密的byte[]
         * @param encryptKey   加密密钥
         * @param iv 偏移
         * @return 解密后的byte[]
         * @throws Exception
         */
        public static String aesEncryptToCBC(String content, String encryptKey,byte[] iv) throws Exception {
            byte[] key = org.apache.commons.codec.binary.Hex.decodeHex(encryptKey.toCharArray());
            checkkey(key);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //算法参数
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"),paramSpec);
            return base64Encode(cipher.doFinal(content.getBytes("utf-8")));
        }
    
        /**
         * AES解密 aes-128/256-cbc
         *
         * @param content 待解密的byte[]
         * @param decryptKey   解密密钥
         * @param iv 偏移
         * @return 解密后的byte[]
         * @throws Exception
         */
        public static String aesDecryptToCBC(String content, String decryptKey,byte[] iv) throws Exception {
            byte[] key = org.apache.commons.codec.binary.Hex.decodeHex(decryptKey.toCharArray());
            checkkey(key);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //算法参数
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"),paramSpec);
            byte[] decryptBytes = cipher.doFinal(base64Decode(content));
            return new String(decryptBytes,"utf-8");
        }
    }
    
    

    nodejs

    说明

    以下nodejs代码来源于 aes-cross项目

    /**
     * "AES/cbc/pkcs5Padding" encription and decription.
     * setAutoPadding(true) is actually pkcs5Padding,.
     */
    'use strict';
    
    var crypto = require('crypto');
    
    var CBC = 'cbc';
    var ECB = 'ecb';
    var NULL_IV = new Buffer([]);
    
    var IV = new Buffer([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
    var cipherMode = ECB;
    var keySize = 128;
    var algorithm;
    setAlgorithm();
    var outputEncoding = 'base64';
    var inputEncoding = 'utf8';
    
    function setAlgorithm() {
        algorithm = 'aes-' + keySize + '-' + cipherMode;
    }
    
    function setCipherMode(mode) {
        if (mode !== CBC && mode !== ECB) {
            throw ('AES.setCipherMode error: ' + mode);
        }
        cipherMode = mode;
        setAlgorithm();
    }
    
    function setKeySize(size) {
        if (size !== 128 && size !== 256) {
            throw ('AES.setKeySize error: ' + size);
        }
        keySize = size;
        setAlgorithm();
        // console.log('setKeySize:%j',keySize);
    }
    
    /**
     * the key must match the keySize/8 , like:16 ,32
     * @param  {Buffer} key
     * @return {}
     */
    function checkKey(key) {
        if (!key) {
            throw 'AES.checkKey error: key is null ';
        }
        if (key.length !== (keySize / 8)) {
            throw 'AES.checkKey error: key length is not ' + (keySize / 8) + ': ' + key.length;
        }
    }
    
    /**
     * buffer/bytes encription
     * @param  {Buffer} buff
     * @param  {Buffer} key  the length must be 16 or 32
     * @param  {Buffer} [newIv]   default is [0,0...0]
     * @return {encripted Buffer}
     */
    function encBytes(buff, key, newIv) {
        checkKey(key);
        var iv = newIv || IV;
        if (cipherMode === ECB) iv = NULL_IV;
        var cipher = crypto.createCipheriv(algorithm, key, iv);
        cipher.setAutoPadding(true);
        var re = Buffer.concat([cipher.update(buff), cipher.final()]);
        // console.log('enc re:%s,len:%d', printBuf(re), re.length);
        return re;
    }
    
    /**
     * text encription
     * @param  {string} text
     * @param  {Buffer} key         the length must be 16 or 32
     * @param  {Buffer} [newIv]       default is [0,0...0]
     * @param  {string} [input_encoding]  ["utf8" -default,"ascii","base64","binary"...](https://nodejs.org/api/buffer.html#buffer_buffer)
     * @param  {string} [output_encoding] ["base64" -default,"hex"]
     * @return {string}                 encription result
     */
    function encText(text, key, newIv, input_encoding, output_encoding) {
        checkKey(key);
        var iv = newIv || IV;
        if (cipherMode === ECB) iv = NULL_IV;
        var inEncoding = input_encoding || inputEncoding;
        var outEncoding = output_encoding || outputEncoding;
        var buff = new Buffer(text, inEncoding);
        var out = encBytes(buff, key, iv);
        var re = new Buffer(out).toString(outEncoding);
        return re;
    }
    
    /**
     * buffer/bytes decription
     * @param  {Buffer} buff
     * @param  {Buffer} key  the length must be 16 or 32
     * @param  {Buffer} [newIv] default is [0,0...0]
     * @return {encripted Buffer}
     */
    function decBytes(buff, key, newIv) {
        checkKey(key);
        var iv = newIv || IV;
        if (cipherMode === ECB) iv = NULL_IV;
        var decipher = crypto.createDecipheriv(algorithm, key, iv);
        decipher.setAutoPadding(true);
        var out = Buffer.concat([decipher.update(buff), decipher.final()]);
        return out;
    }
    
    /**
     * text decription
     * @param  {string} text
     * @param  {Buffer} key         the length must be 16 or 32
     * @param  {Buffer} [newIv]       default is [0,0...0]
     * @param  {string} [input_encoding]  ["utf8" - default,"ascii","base64","binary"...](https://nodejs.org/api/buffer.html#buffer_buffer)
     * @param  {string} [output_encoding] ["base64"- default ,"hex"]
     * @return {string}                 decription result
     */
    function decText(text, key, newIv, input_encoding, output_encoding) {
        checkKey(key);
        var iv = newIv || IV;
        if (cipherMode === ECB) iv = NULL_IV;
        var inEncoding = input_encoding || inputEncoding;
        var outEncoding = output_encoding || outputEncoding;
        var buff = new Buffer(text, outEncoding);
        var re = new Buffer(decBytes(buff, key, iv)).toString(inEncoding);
        return re;
    }
    
    
    exports.setCipherMode = setCipherMode;
    exports.setKeySize = setKeySize;
    exports.encText = encText;
    exports.encBytes = encBytes;
    exports.decText = decText;
    exports.decBytes = decBytes;
    
    // 以下为测试部分
    // //key是16进制,需要转换为buffer,转换后buffer长度为16,即aes128,如果buffer长度是32则是aes256
    // var key = new Buffer("c4b84456c1379bec99c4d1b7e9f13173", 'hex');
    // var key256 = new Buffer("c4b84456c1379bec99c4d1b7e9f13173c4b84456c1379bec99c4d1b7e9f13173", 'hex');
    // var str = "helloworld 你好";
    // var buffer = new Buffer(str,"utf8");
    //
    // //aes-ecb-128 buffer
    // var buffer_encrypt = encBytes(buffer,key);
    // var crypto_buffer =decBytes(buffer_encrypt,key);
    // var str = crypto_buffer.toString();
    // console.log(str);
    //
    // //aes-ecb-128 string
    // var text_encrypt = encText(str,key);
    // var text_decrypt =decText(text_encrypt,key);
    // console.log(text_decrypt);
    //
    // text_encrypt = encText(str,key,null,'utf8','base64');
    // text_decrypt =decText(text_encrypt,key,null,'utf8','base64');
    // console.log(text_decrypt);
    //
    // //aes-cbc-128 buffer
    // setCipherMode(CBC);
    // var iv = new Buffer("abcdefgh12345678","utf8");//字符串一定是16位
    // buffer_encrypt = encBytes(buffer,key,iv);
    // crypto_buffer =decBytes(buffer_encrypt,key,iv);
    // str = crypto_buffer.toString();
    // console.log(str);
    //
    // //aes-cbc-128 string
    // text_encrypt = encText(str,key,iv);
    // text_decrypt =decText(text_encrypt,key,iv);
    // console.log(text_decrypt);
    //
    // text_encrypt = encText(str,key,iv,'utf8','base64');
    // text_decrypt =decText(text_encrypt,key,iv,'utf8','base64');
    // console.log(text_decrypt);
    //
    //
    // //aes-ecb-256 buffer
    // setKeySize(256);
    // setCipherMode(ECB);
    // buffer_encrypt = encBytes(buffer,key256);
    // crypto_buffer =decBytes(buffer_encrypt,key256);
    // str = crypto_buffer.toString();
    // console.log("256=="+str);
    
    

    参考资料

    相关文章

      网友评论

        本文标题:JAVA与NodeJS实现AES加密

        本文链接:https://www.haomeiwen.com/subject/dokmfftx.html