vpn.email
Version:
vpn.email client
101 lines (76 loc) • 2.63 kB
text/typescript
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: string, masterkey ) => {
// random initialization vector
var iv = crypto.randomBytes ( 12 );
// random salt
var 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
var key = crypto.pbkdf2Sync ( masterkey, salt, 2145, 32, 'sha512' );
// AES 256 GCM Mode
var cipher = crypto.createCipheriv ( 'aes-256-gcm', key, iv );
// encrypt the given text
var encrypted = Buffer.concat ([ cipher.update ( Buffer.from ( text, 'utf8' )), cipher.final ()]);
// extract the auth tag
var tag = cipher.getAuthTag ();
// generate output
return Buffer.concat ([ salt, iv, tag, encrypted ])
}
/**
* 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
var salt = data.slice ( 0, 64 );
var iv = data.slice ( 64, 76 );
var tag = data.slice ( 76, 92 );
var text = data.slice ( 92 );
// derive key using; 32 byte key length
var key = crypto.pbkdf2Sync ( masterkey, salt , 2145, 32, 'sha512' );
// AES 256 GCM Mode
var decipher = crypto.createDecipheriv ( 'aes-256-gcm', key, iv );
decipher.setAuthTag ( tag );
// encrypt the given text
var decrypted = decipher.update ( text ) + decipher.final ( 'utf8' );
return CallBack ( null, decrypted )
} 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 )
}
}