UNPKG

vpn.email.client

Version:
99 lines (98 loc) 3.59 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. */ "use strict"; const crypto = require("crypto"); exports.encrypt = (text, masterkey, 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 */ exports.decrypt = (data, 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); } }; exports.packetBuffer = (bit0, _serial, id, 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]); }; exports.openPacket = (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) }; };