From e9af665c20d467064e512dafedc0615056c78ed3 Mon Sep 17 00:00:00 2001
From: Carlo <5310264+thecarlo@users.noreply.github.com>
Date: Mon, 29 Apr 2024 13:09:16 +1000
Subject: [PATCH] password strength indicator (#7)
---
.../GeneratePassword/index.test.tsx | 2 +-
src/components/GeneratePassword/index.tsx | 79 ++++++++++++++++++-
src/enums/cssClassType.ts | 4 +
.../getClassByStrength.ts | 25 ++++++
src/functions/crackTimes.ts | 43 ++++++++++
src/functions/estimateCrackTime.ts | 31 ++++++++
src/interfaces/crackTime.ts | 5 ++
7 files changed, 186 insertions(+), 3 deletions(-)
create mode 100644 src/enums/cssClassType.ts
create mode 100644 src/functions/checkPasswordStrength/getClassByStrength.ts
create mode 100644 src/functions/crackTimes.ts
create mode 100644 src/functions/estimateCrackTime.ts
create mode 100644 src/interfaces/crackTime.ts
diff --git a/src/components/GeneratePassword/index.test.tsx b/src/components/GeneratePassword/index.test.tsx
index 9f30f86..f1328a9 100644
--- a/src/components/GeneratePassword/index.test.tsx
+++ b/src/components/GeneratePassword/index.test.tsx
@@ -11,7 +11,7 @@ afterEach(cleanup);
describe('GeneratePassword', () => {
const passphraseDefaultLength = 3;
- const passwordDefaultLength = 15;
+ const passwordDefaultLength = 12;
it('should render the Generate Button', () => {
render(
diff --git a/src/components/GeneratePassword/index.tsx b/src/components/GeneratePassword/index.tsx
index 5a4e486..50d6405 100644
--- a/src/components/GeneratePassword/index.tsx
+++ b/src/components/GeneratePassword/index.tsx
@@ -1,7 +1,10 @@
/* eslint-disable @typescript-eslint/indent */
import React, { useEffect, useRef, useState } from 'react';
+import { CssClassType } from '@enums/cssClassType';
import { checkPasswordStrength } from '@functions/checkPasswordStrength';
+import { getClassByStrength } from '@functions/checkPasswordStrength/getClassByStrength';
import { getClassNameByStrength } from '@functions/checkPasswordStrength/getClassnameByStrength';
+import { estimateCrackTime } from '@functions/estimateCrackTime';
import { PasswordMode } from '../../enums/passwordMode';
import { randomPassword } from '../../functions/randomPassword';
@@ -15,7 +18,7 @@ export const GeneratePassword = (props: GeneratePasswordProps) => {
const passphraseDefaultLength = 3;
- const passwordDefaultLength = 15;
+ const passwordDefaultLength = 12;
const defaultLength =
mode === PasswordMode.Password
@@ -265,7 +268,7 @@ export const GeneratePassword = (props: GeneratePasswordProps) => {
) => {
@@ -312,6 +315,78 @@ export const GeneratePassword = (props: GeneratePasswordProps) => {
+
+
+ {/*
Password Strength
*/}
+
+
+
+
+
+
+
+ {passwordStrength}
+
+
+
Strength
+
+
+
+
+
+
+
+
+
+ {estimateCrackTime(password)}
+
+
Time to crack password
+
+
+
);
};
diff --git a/src/enums/cssClassType.ts b/src/enums/cssClassType.ts
new file mode 100644
index 0000000..536ce1b
--- /dev/null
+++ b/src/enums/cssClassType.ts
@@ -0,0 +1,4 @@
+export const enum CssClassType {
+ Text = 'Text',
+ Background = 'Background',
+}
diff --git a/src/functions/checkPasswordStrength/getClassByStrength.ts b/src/functions/checkPasswordStrength/getClassByStrength.ts
new file mode 100644
index 0000000..cf9667b
--- /dev/null
+++ b/src/functions/checkPasswordStrength/getClassByStrength.ts
@@ -0,0 +1,25 @@
+import { CssClassType } from '@enums/cssClassType';
+
+export const getClassByStrength = (
+ strength: string,
+ classType: CssClassType
+): string => {
+ const cssPrefix = classType === CssClassType.Text ? 'text' : 'bg';
+
+ switch (strength) {
+ case 'Weak':
+ return `${cssPrefix}-red-500`;
+
+ case 'Moderate':
+ return `${cssPrefix}-yellow-500`;
+
+ case 'Strong':
+ return `${cssPrefix}-green-500`;
+
+ case 'Very Strong':
+ return `${cssPrefix}-green-500`;
+
+ default:
+ return `${cssPrefix}-red-500`;
+ }
+};
diff --git a/src/functions/crackTimes.ts b/src/functions/crackTimes.ts
new file mode 100644
index 0000000..7389176
--- /dev/null
+++ b/src/functions/crackTimes.ts
@@ -0,0 +1,43 @@
+import { CrackTime } from '@interfaces/crackTime';
+
+export const crackTimes: Record = {
+ 8: {
+ allChars: '28 seconds',
+ onlyAlphaNum: '2 minutes',
+ onlyAlpha: '5 minutes',
+ },
+ 9: { allChars: '6 hours', onlyAlphaNum: '2 hours', onlyAlpha: '24 minutes' },
+ 10: { allChars: '2 weeks', onlyAlphaNum: '5 days', onlyAlpha: '21 hours' },
+ 11: { allChars: '3 years', onlyAlphaNum: '10 months', onlyAlpha: '1 month' },
+ 12: { allChars: '226 years', onlyAlphaNum: '53 years', onlyAlpha: '6 years' },
+ 13: {
+ allChars: '15 thousand years',
+ onlyAlphaNum: '3 thousand years',
+ onlyAlpha: '332 years',
+ },
+ 14: {
+ allChars: '1 million years',
+ onlyAlphaNum: '200 thousand years',
+ onlyAlpha: '17 thousand years',
+ },
+ 15: {
+ allChars: '77 million years',
+ onlyAlphaNum: '12 million years',
+ onlyAlpha: '900 thousand years',
+ },
+ 16: {
+ allChars: '5 billion years',
+ onlyAlphaNum: '779 million years',
+ onlyAlpha: '46 million years',
+ },
+ 17: {
+ allChars: '380 billion years',
+ onlyAlphaNum: '48 billion years',
+ onlyAlpha: '2 billion years',
+ },
+ 18: {
+ allChars: '26 trillion years',
+ onlyAlphaNum: '2 trillion years',
+ onlyAlpha: '126 billion years',
+ },
+};
diff --git a/src/functions/estimateCrackTime.ts b/src/functions/estimateCrackTime.ts
new file mode 100644
index 0000000..80925eb
--- /dev/null
+++ b/src/functions/estimateCrackTime.ts
@@ -0,0 +1,31 @@
+import { CrackTime } from '@interfaces/crackTime';
+
+import { crackTimes } from './crackTimes';
+
+export const estimateCrackTime = (password: string): string => {
+ const hasUpper = /[A-Z]/.test(password);
+
+ const hasLower = /[a-z]/.test(password);
+
+ const hasNumbers = /[0-9]/.test(password);
+
+ const hasSpecial = /[!@#$%^&*()_+\-=[\]{}|;:'",.<>?]/.test(password);
+
+ let key: keyof CrackTime = 'onlyAlpha';
+
+ if (hasUpper && hasLower && hasNumbers && hasSpecial) {
+ key = 'allChars';
+ } else if (hasUpper && hasLower && hasNumbers) {
+ key = 'onlyAlphaNum';
+ }
+
+ const length = password.length;
+
+ if (length > 18) {
+ return 'Trillions of years';
+ } else if (length >= 8 && crackTimes[length]) {
+ return crackTimes[length][key];
+ }
+
+ return 'Not specified';
+};
diff --git a/src/interfaces/crackTime.ts b/src/interfaces/crackTime.ts
new file mode 100644
index 0000000..da1ff0a
--- /dev/null
+++ b/src/interfaces/crackTime.ts
@@ -0,0 +1,5 @@
+export interface CrackTime {
+ allChars: string;
+ onlyAlphaNum: string;
+ onlyAlpha: string;
+}