node.js 实现 AES CTR 加解密

node aesctr

前言

由于最近我们在做一款安全的文件分享 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;

 

最新文章

  1. JavaScript进阶之路(一)初学者的开始
  2. [史上最全]C#(VB.NET)中位运算符工作过程剖析(译)
  3. HTML5触屏版多线程渲染模板技术分享
  4. asp.net MVC4的执行流程
  5. PAT 1026. 程序运行时间(15)
  6. nodejs模仿http请求组件nodegrass简单例子
  7. 使用ajax上传中遇到的问题
  8. jqeury.base
  9. iOS 进阶 第四天(0329)
  10. jQuery Validate 插件
  11. Unity3D NGUI制作进度条
  12. 说说oracle的 sysdate、trunc函数
  13. 4 Java学习之 反射Reflection
  14. 【转】Ubuntu重装,直接进win7,不进linux的解决方案(添加Ubuntu启动菜单)
  15. Oracle游标cursor1基础和隐式游标
  16. new Date() IE浏览器下不起做用的解决方法
  17. flask同源策略解决办法及flask-cors只允许特定域名跨域
  18. QML学习笔记(五)— 做一个简单的待做事项列表
  19. Linux下清理内存和Cache方法见下文:
  20. javascript(面向对象,作用域,闭包,设计模式等)

热门文章

  1. 缓存融合(Cache Fusion)介绍
  2. Oracle自动性能统计
  3. mysqli实现增删改查(转)
  4. Python学习之UDP版socket&amp;SocketServer
  5. linux等 入门思维导图
  6. linux中权限对文件和目录的影响?
  7. 【神经网络与深度学习】Caffe训练执行时爆出的Check failed: registry.count(t ype) == 1 (0 vs. 1) Unknown layer type
  8. elasticsearch 冷热数据的读写分离
  9. 模板if 的使用
  10. [转帖]Linux杂谈: 树形显示多级目录--tree