Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

index.js 3.3 KiB

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