mirror of
https://github.com/nvms/prsm.git
synced 2025-12-15 15:50:53 +00:00
59 lines
1.4 KiB
TypeScript
59 lines
1.4 KiB
TypeScript
import crypto from "node:crypto";
|
|
|
|
type Algorithm = "sha256" | "sha512";
|
|
|
|
class Hasher {
|
|
private algorithm: "sha256" | "sha512";
|
|
private saltLength: number;
|
|
|
|
constructor(algorithm: Algorithm = "sha256", saltLength: number = 64) {
|
|
this.algorithm = algorithm;
|
|
this.saltLength = saltLength;
|
|
}
|
|
|
|
verify(encoded: string, unencoded: string): boolean {
|
|
const { algorithm, salt } = this.parse(encoded);
|
|
return this.hash(unencoded, algorithm, salt) === encoded;
|
|
}
|
|
|
|
encode(string: string): string {
|
|
const salt = crypto.randomBytes(this.saltLength).toString("base64");
|
|
return this.hash(string, this.algorithm, salt);
|
|
}
|
|
|
|
hash(string: string, algorithm: Algorithm, salt: string): string {
|
|
const hash = crypto.createHash(algorithm);
|
|
hash.update(string);
|
|
hash.update(salt, "utf8");
|
|
return `${algorithm}:${salt}:${hash.digest("base64")}`;
|
|
}
|
|
|
|
private parse(encoded: string): {
|
|
algorithm: Algorithm;
|
|
salt: string;
|
|
digest: string;
|
|
} {
|
|
const parts = encoded.split(":");
|
|
|
|
if (parts.length !== 3) {
|
|
throw new Error(
|
|
`Invalid hash string. Expected 3 parts, got ${parts.length}`,
|
|
);
|
|
}
|
|
|
|
const algorithm: Algorithm = parts[0] as Algorithm;
|
|
const salt: string = parts[1];
|
|
const digest: string = parts[2];
|
|
|
|
return {
|
|
algorithm,
|
|
salt,
|
|
digest,
|
|
};
|
|
}
|
|
}
|
|
|
|
export default new Hasher();
|
|
|
|
export { Hasher, type Algorithm };
|