keypair.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /**
  2. * Created by bmf on 11/2/13.
  3. */
  4. /* jslint node: true */
  5. 'use strict';
  6. var assert = require('assert');
  7. var CryptoBaseBuffer = require('../crypto-base-buffer');
  8. module.exports = function KeyPair() {
  9. var self = this;
  10. /** secret key */
  11. self.secretKey = new CryptoBaseBuffer();
  12. self.secretKeySize = 0;
  13. /** public key */
  14. self.publicKey = new CryptoBaseBuffer();
  15. self.publicKeySize = 0;
  16. self.type = undefined;
  17. /** default encoding to use in all string operations */
  18. self.defaultEncoding = undefined;
  19. self.init = function(options) {
  20. options = options || {};
  21. if( !options.type ) {
  22. throw new Error('[KeyPair] type not given in init');
  23. }
  24. self.type = options.type;
  25. if( !options.publicKeySize ) {
  26. throw new Error('[KeyPair] public key size not given');
  27. }
  28. self.publicKeySize = options.publicKeySize;
  29. if( !options.secretKeySize ) {
  30. throw new Error('[KeyPair] secret key size not given');
  31. }
  32. self.secretKeySize = options.secretKeySize;
  33. // init both buffers
  34. self.publicKey.init({
  35. expectedSize: options.publicKeySize,
  36. type: self.type + 'PublicKey'
  37. });
  38. self.secretKey.init({
  39. expectedSize: options.secretKeySize,
  40. type: self.type + 'SecretKey'
  41. });
  42. // We will only accept hex string representations of keys
  43. self.publicKey.setValidEncodings(['hex', 'base64']);
  44. self.secretKey.setValidEncodings(['hex', 'base64']);
  45. // the default encoding to us in all string set/toString methods is Hex
  46. self.publicKey.setEncoding('base64');
  47. self.secretKey.setEncoding('base64');
  48. // Public Key
  49. self.setPublicKey(options.publicKey, options.encoding);
  50. // Secret Key
  51. self.setSecretKey(options.secretKey, options.encoding);
  52. };
  53. /** Box Public Key buffer size in bytes */
  54. self.publicKeyBytes = function() {
  55. return self.publicKeySize;
  56. };
  57. /** Box Public Key buffer size in bytes */
  58. self.secretKeyBytes = function() {
  59. return self.secretKeySize;
  60. };
  61. /* Aliases */
  62. self.pkBytes = self.publicKeyBytes;
  63. self.skBytes = self.secretKeyBytes;
  64. /**
  65. * Set the default encoding to use in all string conversions
  66. * @param {String} encoding encoding to use
  67. */
  68. self.setEncoding = function(encoding) {
  69. assert(!!encoding.match(/^(?:utf8|ascii|binary|hex|utf16le|ucs2|base64)$/), 'Encoding ' + encoding + ' is currently unsupported.');
  70. self.defaultEncoding = encoding;
  71. self.publicKey.setEncoding(encoding);
  72. self.secretKey.setEncoding(encoding);
  73. };
  74. /**
  75. * Get the current default encoding
  76. * @returns {undefined|String}
  77. */
  78. self.getEncoding = function() {
  79. return self.defaultEncoding;
  80. };
  81. /**
  82. * Check if key pair is valid
  83. * @param keys {Object} an object with secrteKey, and publicKey members
  84. * @returns {boolean} true is both public and secret keys are valid
  85. */
  86. self.isValid = function(keys, encoding) {
  87. assert.equal(typeof keys, 'object');
  88. assert.ok(keys.publicKey);
  89. assert.ok(keys.secretKey);
  90. encoding = encoding || self.defaultEncoding;
  91. return self.publicKey.isValid(keys.publicKey, encoding) &&
  92. self.secretKey.isValid(keys.secretKey, encoding);
  93. };
  94. /**
  95. * Wipe keys securely
  96. */
  97. self.wipe = function() {
  98. self.publicKey.wipe();
  99. self.secretKey.wipe();
  100. };
  101. /**
  102. * Generate a random key pair
  103. */
  104. self.generate = function() {
  105. throw new Error('KeyPair: this method should be implemented in each sub class');
  106. };
  107. /**
  108. * Getter for the public key
  109. * @returns {undefined| Buffer} public key
  110. */
  111. self.getPublicKey = function() {
  112. return self.publicKey;
  113. };
  114. /**
  115. * Getter for the secretKey
  116. * @returns {undefined| Buffer} secret key
  117. */
  118. self.getSecretKey = function() {
  119. return self.secretKey;
  120. };
  121. self.pk = self.getPublicKey;
  122. self.sk = self.getSecretKey;
  123. /**
  124. * Getter for the key pair
  125. * @returns {Object} with both public and private keys
  126. */
  127. self.get = function() {
  128. return {
  129. 'publicKey' : self.publicKey.get(),
  130. 'secretKey' : self.secretKey.get()
  131. };
  132. };
  133. /**
  134. * Set the secret key to a known value
  135. * @param v {String|Buffer|Array} the secret key
  136. * @param encoding {String} optional. If v is a string you can specify the encoding
  137. */
  138. self.set = function(keys, encoding) {
  139. assert.equal(typeof keys, 'object');
  140. if( keys instanceof KeyPair ) {
  141. self.secretKey.set(keys.sk(), encoding);
  142. self.publicKey.set(keys.pk(), encoding);
  143. }
  144. else {
  145. encoding = encoding || self.defaultEncoding;
  146. if( typeof keys === 'object' ) {
  147. if( keys.secretKey ) {
  148. self.secretKey.set(keys.secretKey, encoding);
  149. }
  150. if( keys.publicKey ) {
  151. self.publicKey.set(keys.publicKey, encoding);
  152. }
  153. }
  154. }
  155. };
  156. self.setPublicKey = function(key, encoding) {
  157. if( key instanceof KeyPair ) {
  158. self.publicKey = key.pk();
  159. }
  160. else if( key instanceof CryptoBaseBuffer ) {
  161. if( key.size() == self.publicKeySize ) {
  162. self.publicKey = key;
  163. }
  164. }
  165. else {
  166. self.publicKey.init({
  167. expectedSize: self.publicKeySize,
  168. buffer: key,
  169. encoding: encoding,
  170. type: self.type + 'PublicKey'
  171. });
  172. }
  173. };
  174. self.setSecretKey = function(key, encoding) {
  175. if( key instanceof KeyPair ) {
  176. self.secretKey = key.sk();
  177. }
  178. else if( key instanceof CryptoBaseBuffer ) {
  179. if( key.size() == self.secretKeySize ) {
  180. self.secretKey = key;
  181. }
  182. }
  183. else {
  184. self.secretKey.init({
  185. expectedSize: self.secretKeySize,
  186. buffer: key,
  187. encoding: encoding,
  188. type: self.type + 'SecretKey'
  189. });
  190. }
  191. };
  192. /**
  193. * Convert the secret key to a string object
  194. * @param encoding {String} optional sting encoding. defaults to 'hex'
  195. */
  196. self.toString = function(encoding) {
  197. encoding = encoding || self.defaultEncoding;
  198. return self.secretKey.toString(encoding) + "," +
  199. self.publicKey.toString(encoding);
  200. };
  201. /**
  202. * Convert the secret key to a JSON object
  203. * @param encoding {String} optional sting encoding. defaults to 'hex'
  204. */
  205. self.toJson = function(encoding) {
  206. encoding = encoding || self.defaultEncoding;
  207. var out = '{';
  208. if( self.secretKey ) {
  209. out += '"secretKey" :"' + self.secretKey.toString(encoding) + '"';
  210. }
  211. if( self.secretKey && self.publicKey ) {
  212. out += ', ';
  213. }
  214. if( self.publicKey ) {
  215. out += '"publicKey" :"' + self.publicKey.toString(encoding) + '"';
  216. }
  217. out += '}';
  218. return out;
  219. };
  220. };