zoukankan      html  css  js  c++  java
  • node.js 实现 AES CTR 加解密

    node.js 实现 AES CTR 加解密

    前言

    由于最近我们在做一款安全的文件分享 App, 所有文件均需要使用 aes ctr 来进行加密,aes key 还有一整套完整的许可体系在保护, 然后再通知各种阅读器进行打开。

    关于 aes ctr 不在此做说明,如需了解,请访问 : AES CTR 详细介绍

    正文

    直接上代码

    'use strict'
    
    var crypto = require('crypto')
    
    // 异或 key 的加解算法
    let alg = 'aes-256-ecb';
    // 加密的数据块大小,单位字节
    let block_size  = 16;
    
    class AES {
        /**
         * 构造函数
         * @param key_buffer  aes key 的 byte 数组
         * @param iv_buffer   随机数据的 byte 数组
         */
        constructor(key_buffer,iv_buffer ){
            this._key = key_buffer;
            this._iv = iv_buffer;
        }
    
        /**
         * 加密
         * @param data_buffer  明文数据
         * @param offset       偏移量
         * @returns {Buffer}   加密后的数据
         */
        encryt(data_buffer, offset ){
            return this._crypt(data_buffer, offset)
        }
    
        /**
         * 解密
         * @param enc_data_buffer 加密后的数据
         * @param offset          偏移量
         * @returns {Buffer}      解密后的数据
         */
        decrypt(enc_data_buffer, offset){
           return this._crypt(enc_data_buffer, offset);
        }
    
        /**
         * 加解密传的数据块
         * @param data_buffer     数据 buffer
         * @param offset          偏移量,用于计算 counter
         * @returns {Buffer}      加密或解密后的数据
         * @private
         */
        _crypt(data_buffer, offset){
    
            let byte_length = data_buffer.length;
            let enc_data_buffer = Buffer.alloc(byte_length);
    
            let start_counter = Math.floor(offset / block_size);
            let total_counter = (offset+byte_length) % block_size == 0 ?
                                                                ((offset+byte_length) / block_size)-1 :
                                                                Math.floor((offset+byte_length) / block_size);
            // 已处理的字节长度
            var handled_length = 0;
            for(var i = start_counter; i<= total_counter; i++){
                // 本次处理的字节长度
                let handle_length = (i+1)*block_size-offset-handled_length;
                if(handled_length + handle_length > byte_length){
                    handle_length = byte_length - handled_length;
                }
                let handle_data_buffer = data_buffer.slice(handled_length, handled_length + handle_length);
                let handled_data_buffer = null;
                if(i == 0 && handle_length < block_size && total_counter > 0){
                    handled_data_buffer = this._cryptBlock(handle_data_buffer, i, handle_length,-1);
                } else {
                    handled_data_buffer = this._cryptBlock(handle_data_buffer, i, handle_length,0);
                }
    
                enc_data_buffer.fill(handled_data_buffer,handled_length, handled_length+handle_length);
                handled_length += handle_length;
    
            }
    
            return enc_data_buffer;
        }
    
        /**
         * 对16个字节的数据块的加解密
         * @param data_buffer  要加密的16字节数据块
         * @param counter      分块代号,从0开始
         * @param length       data_buffer 的长度,<=16, 多数情况下为 16,只有在不满 16 字节时才会 < 16
         * @param forward -1:  表示数据块头不足 16 字节,0 表示正好是 16 字节 或 数据块尾不满 16 节节
         * @returns {Buffer}
         * @private
         */
        _cryptBlock(data_buffer, counter, length, forward){
    
            var xor_buffer = Buffer.alloc(block_size);
            xor_buffer.fill(this._iv.slice(0,8),0,8)
            xor_buffer.writeUIntBE(counter,10,6);
    
            let cipher = crypto.createCipheriv(alg,this._key,null);
            var xor_key_buffer = cipher.update(xor_buffer);
            cipher.final();
    
            var enc_buffer = Buffer.alloc(length);
            if(forward === -1){
                let length_diff = block_size - length;
                for(var i=length_diff;i<block_size;i++){
                    let number = data_buffer[i-length_diff] ^ xor_key_buffer[i];
                    enc_buffer[i-length_diff] = number;
                }
            } else {
                for(var i =0; i < length; i++){
                    let number = data_buffer[i] ^ xor_key_buffer[i];
                    enc_buffer[i] = number;
                }
            }
            return enc_buffer;
        }
    }
    
    
    exports.AES = AES;
    

     

     

  • 相关阅读:
    不可小视视图对效率的影响力
    Maximum Margin Planning
    PhysicsBased Boiling Simulation

    Learning Behavior Styles with Inverse Reinforcement Learning
    Simulating Biped Behaviors from Human Motion Data
    Nearoptimal Character Animation with Continuous Control
    Apprenticeship Learning via Inverse Reinforcement Learning
    回报函数学习的学徒学习综述
    Enabling Realtime Physics Simulation in Future Interactive Entertainment
  • 原文地址:https://www.cnblogs.com/feshfans/p/11001523.html
Copyright © 2011-2022 走看看