secretbox.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /**
  2. * Created by bmf on 11/2/13.
  3. *
  4. * Documentation of crypto http://nacl.cr.yp.to/box.html
  5. */
  6. /* jslint node: true */
  7. 'use strict';
  8. var binding = require('../build/Release/sodium');
  9. var assert = require('assert');
  10. var toBuffer = require('./toBuffer');
  11. var SecretBoxKey = require('./keys/secretbox-key');
  12. var Nonce = require('./nonces/secretbox-nonce');
  13. /**
  14. * Public-key authenticated encryption: Box
  15. *
  16. * @param {String|Buffer|Array} secretKey sender's private key.
  17. * @param {String|Buffer|Array} publicKey recipient's private key.
  18. *
  19. * @see Keys
  20. * @constructor
  21. */
  22. module.exports = function SecretBox(secretKey, encoding) {
  23. var self = this;
  24. /** default encoding to use in all string operations */
  25. self.defaultEncoding = undefined;
  26. if( secretKey instanceof SecretBoxKey) {
  27. self.boxKey = secretKey;
  28. }
  29. else {
  30. /** Set the keys used to encrypt and decrypt messages */
  31. self.boxKey = new SecretBoxKey(secretKey, encoding);
  32. }
  33. /** SecretBox padding of cipher text buffer */
  34. self.boxZeroBytes = function() {
  35. return binding.crypto_secretbox_BOXZEROBYTES;
  36. };
  37. /** Passing of message. This implementation does message padding automatically */
  38. self.zeroBytes = function() {
  39. return binding.crypto_secretbox_ZEROBYTES;
  40. };
  41. /** String name of the default crypto primitive used in secretbox operations */
  42. self.primitive = function() {
  43. return binding.crypto_secretbox_PRIMITIVE;
  44. };
  45. /**
  46. * Get the box-key secret key object
  47. * @returns {BoxKey|*}
  48. */
  49. self.key = function() {
  50. return self.boxKey;
  51. };
  52. /**
  53. * Set the default encoding to use in all string conversions
  54. * @param {String} encoding encoding to use
  55. */
  56. self.setEncoding = function(encoding) {
  57. assert(!!encoding.match(/^(?:utf8|ascii|binary|hex|utf16le|ucs2|base64)$/), 'Encoding ' + encoding + ' is currently unsupported.');
  58. self.defaultEncoding = encoding;
  59. };
  60. /**
  61. * Get the current default encoding
  62. * @returns {undefined|String}
  63. */
  64. self.getEncoding = function() {
  65. return self.defaultEncoding;
  66. };
  67. /**
  68. * Encrypt a message
  69. * The crypto_secretbox function is designed to meet the standard notions of
  70. * privacy and authenticity for a secret-key authenticated-encryption scheme
  71. * using nonces. For formal definitions see, e.g., Bellare and Namprempre,
  72. * "Authenticated encryption: relations among notions and analysis of the
  73. * generic composition paradigm," Lecture Notes in Computer Science
  74. * 1976 (2000), 531–545, http://www-cse.ucsd.edu/~mihir/papers/oem.html.
  75. *
  76. * Note that the length is not hidden. The basic API leaves it up to the
  77. * caller to generate a unique nonce for every message, in the high level
  78. * API a random nonce is generated automatically and you do no need to
  79. * worry about it.
  80. *
  81. * If no options are given a new random nonce will be generated automatically
  82. * and both planText and cipherText must be buffers
  83. *
  84. * @param {Buffer|String|Array} plainText message to encrypt
  85. * @param {String} [encoding] encoding of message string
  86. *
  87. * @returns {Object} cipher box
  88. */
  89. self.encrypt = function (plainText, encoding) {
  90. encoding = encoding || self.defaultEncoding;
  91. // generate a new random nonce
  92. var nonce = new Nonce();
  93. var buf = toBuffer(plainText, encoding);
  94. var cipherText = binding.crypto_secretbox(
  95. buf,
  96. nonce.get(),
  97. self.boxKey.get());
  98. if( !cipherText ) {
  99. return undefined;
  100. }
  101. return {
  102. cipherText: cipherText,
  103. nonce : nonce.get()
  104. };
  105. };
  106. /**
  107. * The decrypt function verifies and decrypts a cipherText using the
  108. * receiver's secret key, the sender's public key, and a nonce.
  109. * The function returns the resulting plaintext m.
  110. *
  111. * @param {Buffer|String|Array} cipherText the encrypted message
  112. * @param {Buffer|String|Array} nonce the nonce used to encrypt
  113. * @param {String} [encoding] the encoding to used in cipherText, nonce, plainText
  114. */
  115. self.decrypt = function (cipherBox, encoding) {
  116. encoding = String(encoding || self.defaultEncoding);
  117. assert(typeof cipherBox == 'object' && cipherBox.hasOwnProperty('cipherText') && cipherBox.hasOwnProperty('nonce'), 'cipherBox is an object with properties `cipherText` and `nonce`.');
  118. assert(cipherBox.cipherText instanceof Buffer, 'cipherBox should have a cipherText property that is a buffer') ;
  119. assert(cipherBox.nonce instanceof Buffer, 'cipherBox should have a nonce property that is a buffer') ;
  120. var nonce = new Nonce(cipherBox.nonce);
  121. var plainText = binding.crypto_secretbox_open(
  122. cipherBox.cipherText,
  123. nonce.get(),
  124. self.boxKey.get()
  125. );
  126. if( plainText && encoding ) {
  127. return plainText.toString(encoding);
  128. }
  129. return plainText;
  130. };
  131. // Aliases
  132. self.close = self.encrypt;
  133. self.open = self.decrypt;
  134. };