TimeEstimates.esm.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import zxcvbnOptions from './Options.esm.js';
  2. const SECOND = 1;
  3. const MINUTE = SECOND * 60;
  4. const HOUR = MINUTE * 60;
  5. const DAY = HOUR * 24;
  6. const MONTH = DAY * 31;
  7. const YEAR = MONTH * 12;
  8. const CENTURY = YEAR * 100;
  9. const times = {
  10. second: SECOND,
  11. minute: MINUTE,
  12. hour: HOUR,
  13. day: DAY,
  14. month: MONTH,
  15. year: YEAR,
  16. century: CENTURY
  17. };
  18. /*
  19. * -------------------------------------------------------------------------------
  20. * Estimates time for an attacker ---------------------------------------------------------------
  21. * -------------------------------------------------------------------------------
  22. */
  23. class TimeEstimates {
  24. translate(displayStr, value) {
  25. let key = displayStr;
  26. if (value !== undefined && value !== 1) {
  27. key += 's';
  28. }
  29. const {
  30. timeEstimation
  31. } = zxcvbnOptions.translations;
  32. return timeEstimation[key].replace('{base}', `${value}`);
  33. }
  34. estimateAttackTimes(guesses) {
  35. const crackTimesSeconds = {
  36. onlineThrottling100PerHour: guesses / (100 / 3600),
  37. onlineNoThrottling10PerSecond: guesses / 10,
  38. offlineSlowHashing1e4PerSecond: guesses / 1e4,
  39. offlineFastHashing1e10PerSecond: guesses / 1e10
  40. };
  41. const crackTimesDisplay = {
  42. onlineThrottling100PerHour: '',
  43. onlineNoThrottling10PerSecond: '',
  44. offlineSlowHashing1e4PerSecond: '',
  45. offlineFastHashing1e10PerSecond: ''
  46. };
  47. Object.keys(crackTimesSeconds).forEach(scenario => {
  48. const seconds = crackTimesSeconds[scenario];
  49. crackTimesDisplay[scenario] = this.displayTime(seconds);
  50. });
  51. return {
  52. crackTimesSeconds,
  53. crackTimesDisplay,
  54. score: this.guessesToScore(guesses)
  55. };
  56. }
  57. guessesToScore(guesses) {
  58. const DELTA = 5;
  59. if (guesses < 1e3 + DELTA) {
  60. // risky password: "too guessable"
  61. return 0;
  62. }
  63. if (guesses < 1e6 + DELTA) {
  64. // modest protection from throttled online attacks: "very guessable"
  65. return 1;
  66. }
  67. if (guesses < 1e8 + DELTA) {
  68. // modest protection from unthrottled online attacks: "somewhat guessable"
  69. return 2;
  70. }
  71. if (guesses < 1e10 + DELTA) {
  72. // modest protection from offline attacks: "safely unguessable"
  73. // assuming a salted, slow hash function like bcrypt, scrypt, PBKDF2, argon, etc
  74. return 3;
  75. }
  76. // strong protection from offline attacks under same scenario: "very unguessable"
  77. return 4;
  78. }
  79. displayTime(seconds) {
  80. let displayStr = 'centuries';
  81. let base;
  82. const timeKeys = Object.keys(times);
  83. const foundIndex = timeKeys.findIndex(time => seconds < times[time]);
  84. if (foundIndex > -1) {
  85. displayStr = timeKeys[foundIndex - 1];
  86. if (foundIndex !== 0) {
  87. base = Math.round(seconds / times[displayStr]);
  88. } else {
  89. displayStr = 'ltSecond';
  90. }
  91. }
  92. return this.translate(displayStr, base);
  93. }
  94. }
  95. export { TimeEstimates as default };
  96. //# sourceMappingURL=TimeEstimates.esm.js.map