这是@Matthew的答案的修改版本,使用TypeScript
import * as crypto from "crypto";
const PASSWORD_LENGTH = 256;
const SALT_LENGTH = 64;
const ITERATIONS = 10000;
const DIGEST = "sha256";
const BYTE_TO_STRING_ENCODING = "hex";
interface PersistedPassword {
salt: string;
hash: string;
iterations: number;
}
export function generateHashPassword(
password: string
): Promise<PersistedPassword> {
return new Promise<PersistedPassword>((accept, reject) => {
const salt = crypto
.randomBytes(SALT_LENGTH)
.toString(BYTE_TO_STRING_ENCODING);
crypto.pbkdf2(
password,
salt,
ITERATIONS,
PASSWORD_LENGTH,
DIGEST,
(error, hash) => {
if (error) {
return reject(error);
}
accept({
salt,
hash: hash.toString(BYTE_TO_STRING_ENCODING),
iterations: ITERATIONS,
});
}
);
});
}
export function verifyPassword(
persistedPassword: PersistedPassword,
passwordAttempt: string
): Promise<boolean> {
return new Promise<boolean>((accept, reject) => {
crypto.pbkdf2(
passwordAttempt,
persistedPassword.salt,
persistedPassword.iterations,
PASSWORD_LENGTH,
DIGEST,
(error, hash) => {
if (error) {
return reject(error);
}
accept(
persistedPassword.hash === hash.toString(BYTE_TO_STRING_ENCODING)
);
}
);
});
}
salt+hash
中获取前10个字符以获取盐值。我使用pbkdf2对即将验证的密码进行哈希,使用相同的盐值。如果“原始盐值+哈希”=“待验证盐值+哈希”,那么我就让用户进入了?就这样吗? - slevincrypto.pbkdf2(password, salt, iterations, 128, 'sha256')
生成哈希值,并使用crypto.timingSafeEqual()
进行比较。 - Francisco Gomes