-
Notifications
You must be signed in to change notification settings - Fork 815
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Require verifying password before chaning it (#1246)
* Verify current password before changing it. * split out verifyPassword into two functions * typo * change incorrect password message
- Loading branch information
1 parent
fb8bc84
commit 15667ec
Showing
3 changed files
with
132 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { BrowserStorage, isOldKey } from "./storage"; | ||
|
||
export async function argonHash( | ||
value: string, | ||
salt: string | ||
): Promise<string | undefined> { | ||
const iframe = document.getElementById("argon-sandbox"); | ||
const message = { | ||
action: "hash", | ||
value, | ||
salt, | ||
}; | ||
|
||
if (!iframe) { | ||
throw new Error("argon-sandbox missing!"); | ||
} | ||
|
||
const argonPromise: Promise<string | undefined> = new Promise((resolve) => { | ||
window.addEventListener("message", (response) => { | ||
resolve(response.data.response); | ||
}); | ||
// @ts-expect-error bad typings | ||
iframe.contentWindow.postMessage(message, "*"); | ||
}); | ||
|
||
return argonPromise; | ||
} | ||
|
||
export async function argonVerify( | ||
value: string, | ||
hash: string | ||
): Promise<boolean> { | ||
const iframe = document.getElementById("argon-sandbox"); | ||
const message = { | ||
action: "verify", | ||
value, | ||
hash, | ||
}; | ||
|
||
if (!iframe) { | ||
throw new Error("argon-sandbox missing!"); | ||
} | ||
|
||
const argonPromise: Promise<boolean> = new Promise((resolve) => { | ||
window.addEventListener("message", (response) => { | ||
resolve(response.data.response); | ||
}); | ||
// @ts-expect-error bad typings | ||
iframe.contentWindow.postMessage(message, "*"); | ||
}); | ||
|
||
return argonPromise; | ||
} | ||
|
||
// Verify a password using keys in BrowserStorage | ||
export async function verifyPasswordUsingKeyID( | ||
keyId: string, | ||
password: string | ||
): Promise<boolean> { | ||
// Get key for current encryption | ||
const keys = await BrowserStorage.getKeys(); | ||
if (isOldKey(keys)) { | ||
throw new Error( | ||
"v3 encryption not being used with verifyPassword. This should never happen!" | ||
); | ||
} | ||
|
||
const key = keys.find((key) => key.id === keyId); | ||
if (!key) { | ||
throw new Error(`Key ${keyId} not in BrowserStorage`); | ||
} | ||
|
||
return verifyPasswordUsingKey(key, password); | ||
} | ||
|
||
export async function verifyPasswordUsingKey( | ||
key: Key, | ||
password: string | ||
): Promise<boolean> { | ||
// Hash password with argon | ||
const rawHash = await argonHash(password, key.salt); | ||
if (!rawHash) { | ||
throw new Error("argon2 did not return a hash!"); | ||
} | ||
// https://passlib.readthedocs.io/en/stable/lib/passlib.hash.argon2.html#format-algorithm | ||
const possibleHash = rawHash.split("$")[5]; | ||
|
||
// verify user password by comparing their password hash with the | ||
// hash of their password's hash | ||
return await argonVerify(possibleHash, key.hash); | ||
} |