You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

122 lines
3.8 KiB

  1. var pbkdf2 = require('pbkdf2');
  2. var createHmac = require('create-hmac');
  3. var Promise = require("bluebird");
  4. var v2 = require('./src/v2');
  5. module.exports = {
  6. encryptLogin: _encryptLogin,
  7. renderPassword: _renderPassword,
  8. createFingerprint: createFingerprint,
  9. _deriveEncryptedLogin: _deriveEncryptedLogin,
  10. _getPasswordTemplate: _getPasswordTemplate,
  11. _prettyPrint: _prettyPrint,
  12. _string2charCodes: _string2charCodes,
  13. _getCharType: _getCharType,
  14. _getPasswordChar: _getPasswordChar,
  15. _createHmac: _createHmac,
  16. _calcEntropy: v2.calcEntropy,
  17. _getSetOfCharacters: v2.getSetOfCharacters,
  18. };
  19. function _encryptLogin(login, masterPassword, options) {
  20. var _options = options !== undefined ? options : {};
  21. var iterations = _options.iterations || 8192;
  22. var keylen = _options.keylen || 32;
  23. return new Promise(function (resolve, reject) {
  24. if (!login || !masterPassword) {
  25. reject('login and master password parameters could not be empty');
  26. }
  27. pbkdf2.pbkdf2(masterPassword, login, iterations, keylen, 'sha256', function (error, key) {
  28. if (error) {
  29. reject('error in pbkdf2');
  30. } else {
  31. resolve(key.toString('hex'));
  32. }
  33. });
  34. })
  35. }
  36. function _renderPassword(encryptedLogin, site, passwordOptions) {
  37. return _deriveEncryptedLogin(encryptedLogin, site, passwordOptions).then(function (derivedEncryptedLogin) {
  38. var template = passwordOptions.template || _getPasswordTemplate(passwordOptions);
  39. return _prettyPrint(derivedEncryptedLogin, template);
  40. });
  41. }
  42. function _createHmac(encryptedLogin, salt) {
  43. return new Promise(function (resolve) {
  44. resolve(createHmac('sha256', new Buffer(encryptedLogin)).update(salt).digest('hex'));
  45. });
  46. }
  47. function _deriveEncryptedLogin(encryptedLogin, site, options) {
  48. var _options = options !== undefined ? options : {};
  49. var length = _options.length || 12;
  50. var counter = _options.counter || 1;
  51. var salt = site + counter.toString();
  52. return _createHmac(encryptedLogin, salt).then(function (derivedHash) {
  53. return derivedHash.substring(0, length);
  54. });
  55. }
  56. function _getPasswordTemplate(passwordTypes) {
  57. var templates = {
  58. lowercase: 'vc',
  59. uppercase: 'VC',
  60. numbers: 'n',
  61. symbols: 's',
  62. };
  63. var returnedTemplate = '';
  64. Object.keys(templates).forEach(function (template) {
  65. if (passwordTypes.hasOwnProperty(template) && passwordTypes[template]) {
  66. returnedTemplate += templates[template]
  67. }
  68. });
  69. return returnedTemplate;
  70. }
  71. function _prettyPrint(hash, template) {
  72. var password = '';
  73. _string2charCodes(hash).forEach(function (charCode, index) {
  74. var charType = _getCharType(template, index);
  75. password += _getPasswordChar(charType, charCode);
  76. });
  77. return password;
  78. }
  79. function _string2charCodes(text) {
  80. var charCodes = [];
  81. for (var i = 0; i < text.length; i++) {
  82. charCodes.push(text.charCodeAt(i));
  83. }
  84. return charCodes;
  85. }
  86. function _getCharType(template, index) {
  87. return template[index % template.length];
  88. }
  89. function _getPasswordChar(charType, index) {
  90. var passwordsChars = {
  91. V: 'AEIOUY',
  92. C: 'BCDFGHJKLMNPQRSTVWXZ',
  93. v: 'aeiouy',
  94. c: 'bcdfghjklmnpqrstvwxz',
  95. A: 'AEIOUYBCDFGHJKLMNPQRSTVWXZ',
  96. a: 'AEIOUYaeiouyBCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz',
  97. n: '0123456789',
  98. s: '@&%?,=[]_:-+*$#!\'^~;()/.',
  99. x: 'AEIOUYaeiouyBCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz0123456789@&%?,=[]_:-+*$#!\'^~;()/.'
  100. };
  101. var passwordChar = passwordsChars[charType];
  102. return passwordChar[index % passwordChar.length];
  103. }
  104. function createFingerprint(str) {
  105. return new Promise(function (resolve) {
  106. resolve(createHmac('sha256', new Buffer(str)).digest('hex'))
  107. });
  108. }