1
0
Fork 0
liza/src/server/encsvc/EncryptionService.js

187 lines
4.8 KiB
JavaScript

/**
* Contains EncryptionService class
*
* Copyright (C) 2017 R-T Specialty, LLC.
*
* This file is part of the Liza Data Collection Framework.
*
* liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var Class = require( 'easejs' ).Class;
/**
* Simple client to encrypt/decrypt data through use of a service
*/
module.exports = Class( 'EncryptionService',
{
/**
* Identifies a block of data as encrypted through this service
* @type {string}
*/
'private const ENC_HEADER': "\x06\x03\x05",
/**
* Object to do the actual data transfer to/from the service
* @type {EncryptionServiceTransfer}
*/
'private _transfer': null,
/**
* Initializes service client
*
* @param {EncryptionServiceTransfer} transfer transfer object
*
* @return {undefined}
*/
'public __construct': function( transfer )
{
this._transfer = transfer;
},
/**
* Encrypts the given data and returns the result
*
* This operation is asynchronous.
*
* @param {Buffer} data data to encrypt
* @param {function(Buffer)} callback function to call with resulting data
*
* @return {undefined}
*/
'public encrypt': function( data, callback )
{
var _self = this;
this._transfer.encrypt( data, function( data )
{
// return the encrypted data, complete with header
callback( _self._addHeader( data ) );
} );
return this;
},
/**
* Decrypts the given data and returns the result
*
* This operation is asynchronous.
*
* @param {Buffer} data data to decrypt
* @param {function(Buffer)} callback function to call with resulting data
*
* @return {undefined}
*/
'public decrypt': function( data, callback )
{
// if the first bytes are not the encryption header, then it may not be
// safe to decrypt
if ( this.isEncrypted( data ) === false )
{
throw TypeError( "Missing encryption header" );
}
this._transfer.decrypt( this._stripHeader( data ), callback );
return this;
},
/**
* Returns whether the provided data is encrypted
*
* This operates by checking for the encryption header. If it is present, it
* is considered to be encrypted.
*
* @param {Buffer} data data to check
*
* @return {boolean} true if encrypted, otherwise false
*/
'public isEncrypted': function( data )
{
if ( !( data instanceof Buffer ) )
{
return false;
}
// if it's too small, it can't possibly include a header
if ( data.length < 3 )
{
return false;
}
var head_bytes = data.slice( 0, this.__self.$('ENC_HEADER').length )
.toString( 'ascii' );
return ( head_bytes === this.__self.$('ENC_HEADER') )
? true
: false;
},
/**
* Prepends encryption header to data
*
* This operation is synchronous, but memcpy() is fairly quick. If we
* experience many problems, we'll make it async.
*
* @param {Buffer} data
*
* @return {Buffer} data, with header
*/
'private _addHeader': function( data )
{
var header_len = this.__self.$('ENC_HEADER').length;
// create a new buffer to store the encrypted data along with the header
var buf = new Buffer( data.length + header_len );
// write the header and copy in the encrypted data
buf.write( this.__self.$('ENC_HEADER') );
data.copy( buf, header_len );
return buf;
},
/**
* Strips encryption header from data
*
* @param {Buffer} data
*
* @return {Buffer} data, without header
*/
'private _stripHeader': function( data )
{
var header_len = this.__self.$('ENC_HEADER').length;
// create a new buffer and copy all data except for the header
var buf = new Buffer( data.length - header_len );
data.copy( buf, 0, header_len );
return buf;
},
'public getHeader': function()
{
return this.__self.$('ENC_HEADER');
}
} );