mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 00:26:40 +00:00
Made breached pwd API comments clearer
This commit is contained in:
@@ -14,12 +14,11 @@ interface PasswordCheckProps {
|
|||||||
const passwordCheck = ({
|
const passwordCheck = ({
|
||||||
password,
|
password,
|
||||||
setPasswordErrorTooShort,
|
setPasswordErrorTooShort,
|
||||||
|
setPasswordErrorTooLong,
|
||||||
setPasswordErrorNumber,
|
setPasswordErrorNumber,
|
||||||
setPasswordErrorLowerCase,
|
setPasswordErrorLowerCase,
|
||||||
setPasswordErrorTooLong,
|
|
||||||
errorCheck
|
errorCheck
|
||||||
}: PasswordCheckProps) => {
|
}: PasswordCheckProps) => {
|
||||||
|
|
||||||
if (!password || password.length < 14) {
|
if (!password || password.length < 14) {
|
||||||
setPasswordErrorTooShort(true);
|
setPasswordErrorTooShort(true);
|
||||||
errorCheck = true;
|
errorCheck = true;
|
||||||
@@ -27,7 +26,7 @@ const passwordCheck = ({
|
|||||||
setPasswordErrorTooShort(false);
|
setPasswordErrorTooShort(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password.length > 100) {
|
if (password.length > 100) {
|
||||||
setPasswordErrorTooLong(true);
|
setPasswordErrorTooLong(true);
|
||||||
errorCheck = true;
|
errorCheck = true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import crypto from "crypto"; // added types from @types/node
|
|||||||
|
|
||||||
export const checkIsPasswordBreached = async (password: string) => {
|
export const checkIsPasswordBreached = async (password: string) => {
|
||||||
// see API details here: https://haveibeenpwned.com/API/v3#SearchingPwnedPasswordsByRange
|
// see API details here: https://haveibeenpwned.com/API/v3#SearchingPwnedPasswordsByRange
|
||||||
// in short, the pending password is hashed (SHA-1), fist 5 chars are sliced and compared against a ranged hash table
|
// in short, the pending password is hashed (SHA-1), the first 5 chars are sliced and compared against a ranged hash table
|
||||||
// if there is a match, that password has been involved in a password breach and should not be accepted
|
// if there is a match, that password has been involved in a password breach and should not be accepted
|
||||||
|
|
||||||
// the database consists of ~700 mln breached passwords and is continuously being updated including with data from the FBI & the UK's NCA
|
// the database consists of ~700 mln breached passwords and is continuously updated
|
||||||
// https://www.troyhunt.com/open-source-pwned-passwords-with-fbi-feed-and-225m-new-nca-passwords-is-now-live/
|
// https://www.troyhunt.com/open-source-pwned-passwords-with-fbi-feed-and-225m-new-nca-passwords-is-now-live/
|
||||||
|
|
||||||
const dataBreachCheckAPIBaseURL = "https://api.pwnedpasswords.com/range/"; // added to CSP
|
const dataBreachCheckAPIBaseURL = "https://api.pwnedpasswords.com/range/"; // added to CSP
|
||||||
@@ -15,27 +15,26 @@ export const checkIsPasswordBreached = async (password: string) => {
|
|||||||
const textEncoder = new TextEncoder();
|
const textEncoder = new TextEncoder();
|
||||||
const encodedPwd = textEncoder.encode(password);
|
const encodedPwd = textEncoder.encode(password);
|
||||||
const hash = crypto.createHash("sha1").update(encodedPwd).digest();
|
const hash = crypto.createHash("sha1").update(encodedPwd).digest();
|
||||||
|
let hashedPwd = Array.from(new Uint8Array(hash))
|
||||||
const hashedPwd = Array.from(new Uint8Array(hash))
|
|
||||||
.map((byte) => byte.toString(16).padStart(2, "0"))
|
.map((byte) => byte.toString(16).padStart(2, "0"))
|
||||||
.join("")
|
.join("")
|
||||||
.toUpperCase();
|
.toUpperCase();
|
||||||
|
hashedPwd = hashedPwd.slice(0, 5); // ONLY the first five SHA-1 hash chars are sent over HTTPS (the whole string can be sent but that's not very secure due to SHA-1 flaws)
|
||||||
|
|
||||||
// Ensure that ONLY the first five SHA-1 hash chars are sent over HTTPS
|
const response = await axios.get(`${dataBreachCheckAPIBaseURL}${hashedPwd}`);
|
||||||
const response = await axios.get(`${dataBreachCheckAPIBaseURL}${hashedPwd.slice(0, 5)}`);
|
|
||||||
const responseData = response.data.toUpperCase();
|
const responseData = response.data.toUpperCase();
|
||||||
const isBreachedPassword = responseData.includes(hashedPwd.slice(5, 40));
|
const isBreachedPassword = responseData.includes(hashedPwd.slice(5, 40)); // compare against the API's ranged db's hash table
|
||||||
|
|
||||||
// Clear the hashed password from memory (good practice)
|
// Clear the hashed password from memory
|
||||||
const zeroBuffer = new Uint8Array(encodedPwd.length);
|
const zeroBuffer = new Uint8Array(encodedPwd.length);
|
||||||
encodedPwd.set(zeroBuffer);
|
encodedPwd.set(zeroBuffer);
|
||||||
|
|
||||||
return isBreachedPassword; // boolean
|
return isBreachedPassword; // boolean: true === "password has been involved in a data breach"
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (axios.isAxiosError(err) && err.response && err.response.status === 429) {
|
if (axios.isAxiosError(err) && err.response && err.response.status === 429) {
|
||||||
console.error("Received a 429 response from the Pwnd Passwords API");
|
console.error("Received a 429 response from the Pwnd Passwords API");
|
||||||
// Handle the 429 error here (not 100% sure what the rate limits are for the password API)
|
// Handle the 429 error here (not 100% sure what the rate limits are for the password API but looks like <10 calls/min)
|
||||||
// an error here should not cause a fail of setting/resetting/changing the password
|
// an error here should not cause the setting/resetting/changing password to fail (unless desired)
|
||||||
} else {
|
} else {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user