158 lines
5.1 KiB
JavaScript
Executable file
158 lines
5.1 KiB
JavaScript
Executable file
/**
|
||
* Created by bmf on 11/2/13.
|
||
*
|
||
* Documentation of crypto http://nacl.cr.yp.to/box.html
|
||
*/
|
||
/* jslint node: true */
|
||
'use strict';
|
||
|
||
var binding = require('../build/Release/sodium');
|
||
var assert = require('assert');
|
||
var toBuffer = require('./toBuffer');
|
||
var SecretBoxKey = require('./keys/secretbox-key');
|
||
var Nonce = require('./nonces/secretbox-nonce');
|
||
|
||
/**
|
||
* Public-key authenticated encryption: Box
|
||
*
|
||
* @param {String|Buffer|Array} secretKey sender's private key.
|
||
* @param {String|Buffer|Array} publicKey recipient's private key.
|
||
*
|
||
* @see Keys
|
||
* @constructor
|
||
*/
|
||
module.exports = function SecretBox(secretKey, encoding) {
|
||
var self = this;
|
||
|
||
/** default encoding to use in all string operations */
|
||
self.defaultEncoding = undefined;
|
||
|
||
if( secretKey instanceof SecretBoxKey) {
|
||
self.boxKey = secretKey;
|
||
}
|
||
else {
|
||
/** Set the keys used to encrypt and decrypt messages */
|
||
self.boxKey = new SecretBoxKey(secretKey, encoding);
|
||
}
|
||
|
||
/** SecretBox padding of cipher text buffer */
|
||
self.boxZeroBytes = function() {
|
||
return binding.crypto_secretbox_BOXZEROBYTES;
|
||
};
|
||
|
||
/** Passing of message. This implementation does message padding automatically */
|
||
self.zeroBytes = function() {
|
||
return binding.crypto_secretbox_ZEROBYTES;
|
||
};
|
||
|
||
/** String name of the default crypto primitive used in secretbox operations */
|
||
self.primitive = function() {
|
||
return binding.crypto_secretbox_PRIMITIVE;
|
||
};
|
||
|
||
/**
|
||
* Get the box-key secret key object
|
||
* @returns {BoxKey|*}
|
||
*/
|
||
self.key = function() {
|
||
return self.boxKey;
|
||
};
|
||
|
||
/**
|
||
* Set the default encoding to use in all string conversions
|
||
* @param {String} encoding encoding to use
|
||
*/
|
||
self.setEncoding = function(encoding) {
|
||
assert(!!encoding.match(/^(?:utf8|ascii|binary|hex|utf16le|ucs2|base64)$/), 'Encoding ' + encoding + ' is currently unsupported.');
|
||
self.defaultEncoding = encoding;
|
||
};
|
||
|
||
/**
|
||
* Get the current default encoding
|
||
* @returns {undefined|String}
|
||
*/
|
||
self.getEncoding = function() {
|
||
return self.defaultEncoding;
|
||
};
|
||
|
||
/**
|
||
* Encrypt a message
|
||
* The crypto_secretbox function is designed to meet the standard notions of
|
||
* privacy and authenticity for a secret-key authenticated-encryption scheme
|
||
* using nonces. For formal definitions see, e.g., Bellare and Namprempre,
|
||
* "Authenticated encryption: relations among notions and analysis of the
|
||
* generic composition paradigm," Lecture Notes in Computer Science
|
||
* 1976 (2000), 531–545, http://www-cse.ucsd.edu/~mihir/papers/oem.html.
|
||
*
|
||
* Note that the length is not hidden. The basic API leaves it up to the
|
||
* caller to generate a unique nonce for every message, in the high level
|
||
* API a random nonce is generated automatically and you do no need to
|
||
* worry about it.
|
||
*
|
||
* If no options are given a new random nonce will be generated automatically
|
||
* and both planText and cipherText must be buffers
|
||
*
|
||
* @param {Buffer|String|Array} plainText message to encrypt
|
||
* @param {String} [encoding] encoding of message string
|
||
*
|
||
* @returns {Object} cipher box
|
||
*/
|
||
self.encrypt = function (plainText, encoding) {
|
||
encoding = encoding || self.defaultEncoding;
|
||
|
||
// generate a new random nonce
|
||
var nonce = new Nonce();
|
||
|
||
var buf = toBuffer(plainText, encoding);
|
||
|
||
var cipherText = binding.crypto_secretbox(
|
||
buf,
|
||
nonce.get(),
|
||
self.boxKey.get());
|
||
|
||
if( !cipherText ) {
|
||
return undefined;
|
||
}
|
||
|
||
return {
|
||
cipherText: cipherText,
|
||
nonce : nonce.get()
|
||
};
|
||
};
|
||
|
||
/**
|
||
* The decrypt function verifies and decrypts a cipherText using the
|
||
* receiver's secret key, the sender's public key, and a nonce.
|
||
* The function returns the resulting plaintext m.
|
||
*
|
||
* @param {Buffer|String|Array} cipherText the encrypted message
|
||
* @param {Buffer|String|Array} nonce the nonce used to encrypt
|
||
* @param {String} [encoding] the encoding to used in cipherText, nonce, plainText
|
||
*/
|
||
self.decrypt = function (cipherBox, encoding) {
|
||
encoding = String(encoding || self.defaultEncoding);
|
||
|
||
assert(typeof cipherBox == 'object' && cipherBox.hasOwnProperty('cipherText') && cipherBox.hasOwnProperty('nonce'), 'cipherBox is an object with properties `cipherText` and `nonce`.');
|
||
assert(cipherBox.cipherText instanceof Buffer, 'cipherBox should have a cipherText property that is a buffer') ;
|
||
assert(cipherBox.nonce instanceof Buffer, 'cipherBox should have a nonce property that is a buffer') ;
|
||
|
||
var nonce = new Nonce(cipherBox.nonce);
|
||
|
||
var plainText = binding.crypto_secretbox_open(
|
||
cipherBox.cipherText,
|
||
nonce.get(),
|
||
self.boxKey.get()
|
||
);
|
||
|
||
if( plainText && encoding ) {
|
||
return plainText.toString(encoding);
|
||
}
|
||
|
||
return plainText;
|
||
};
|
||
|
||
// Aliases
|
||
self.close = self.encrypt;
|
||
self.open = self.decrypt;
|
||
};
|