UNPKG

vpn.email.client

Version:
137 lines (104 loc) 3.62 kB
/*! * Copyright 2017 Vpn.Email network security technology Canada Inc. All Rights Reserved. * * Vpn.Email network technolog Canada Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import * as crypto from 'crypto' export interface packetBuffer { command: number; uuid: string; buffer: Buffer; serial: number } export interface pairConnect { serverListen: string; clientListen: string; } export const encrypt = ( text: Buffer, masterkey: string, CallBack ) => { // random initialization vector const iv = crypto.randomBytes ( 12 ); // random salt const salt = crypto.randomBytes ( 64 ); // derive key: 32 byte key length - in assumption the masterkey is a cryptographic and NOT a password there is no need for // a large number of iterations. It may can replaced by HKDF try { crypto.pbkdf2 ( masterkey, salt, 2145, 32, 'sha512', ( err, derivedKey ) => { if ( err ) return CallBack ( err ) // AES 256 GCM Mode const cipher = crypto.createCipheriv ( 'aes-256-gcm', derivedKey, iv ); // encrypt the given text const encrypted = Buffer.concat ([ cipher.update ( text ), cipher.final ()]); // generate output const ret = Buffer.concat ([ salt, iv, cipher.getAuthTag (), encrypted ]) return CallBack ( null, ret) }) } catch ( ex ) { console.log ('encrypt catch error!') return CallBack ( ex ) } } /** * Decrypts text by given key * @param String base64 encoded input data * @param Buffer masterkey * @returns String decrypted (original) text */ export const decrypt = ( data: Buffer, masterkey, CallBack ) => { if ( !data || !data.length ) return CallBack ( new Error('null')) try { // base64 decoding // convert data to buffers const salt = data.slice ( 0, 64 ); const iv = data.slice ( 64, 76 ); const tag = data.slice ( 76, 92 ); const text = data.slice ( 92 ); // derive key using; 32 byte key length crypto.pbkdf2 ( masterkey, salt , 2145, 32, 'sha512', ( err, derivedKey ) => { if ( err ) return CallBack ( err ) // AES 256 GCM Mode try { const decipher = crypto.createDecipheriv ( 'aes-256-gcm', derivedKey, iv ); decipher.setAuthTag ( tag ); const decrypted = decipher.update ( text ) + decipher.final ( 'utf8' ) return CallBack ( null, decrypted ) } catch ( ex ) { } }) } catch ( e ) { return CallBack ( e ) } } export const packetBuffer = ( bit0: number, _serial: number, id: string, buffer: Buffer ) => { const _buffer = new Buffer ( 6 ) _buffer.fill ( 0 ) _buffer.writeUInt8 ( bit0, 0 ) _buffer.writeUInt32BE ( _serial, 1 ) const uuid = new Buffer ( id, 'utf8' ) _buffer.writeUInt8 ( id.length, 5 ) if ( buffer && buffer.length ) return Buffer.concat ([ _buffer, uuid, buffer ]) return Buffer.concat ([ _buffer, uuid ]) } export const openPacket = ( buffer: Buffer ) => { const idLength = buffer.readUInt8 ( 5 ) return { command: buffer.readUInt8 ( 0 ), serial: buffer.readUInt32BE ( 1 ), uuid: buffer.toString ( 'utf8', 6, 6 + idLength ), buffer: buffer.slice ( 6 + idLength ) } }