Skip to content

Instantly share code, notes, and snippets.

@composite
Created March 16, 2024 08:03
Show Gist options
  • Save composite/e943b5b993b9b329b41bb0092dc21d89 to your computer and use it in GitHub Desktop.
Save composite/e943b5b993b9b329b41bb0092dc21d89 to your computer and use it in GitHub Desktop.
Generate and verify password based on PBKDF2 with SHA-256 using Web Standards. works on modern browser, node(20 or later), and any cloud's edge environment.
const encoder = new TextEncoder();
const ITERATIONS = 65535;
const LENGTH = 64;
const ALGORITHM = 'PBKDF2';
const DIGEST = 'SHA-256';
const DERIVED_KEY = {
name: 'AES-CBC',
length: 256,
} as const;
const USAGES = {
algorithm: ['deriveBits', 'deriveKey'],
digest: ['encrypt', 'decrypt'],
} as const;
const tob64 = (b: ArrayLike<number> | ArrayBufferLike) => btoa(String.fromCodePoint(...new Uint8Array(b)));
const fromb64 = (s: string) => Uint8Array.from(atob(s), (c) => c.charCodeAt(0));
/**
* 해시에 필요한 무작위 솔트 생성
*/
export const createSalt = () => crypto.getRandomValues(new Uint8Array(LENGTH));
const keygen = async (passphase: Uint8Array, salt: Uint8Array) => {
const key = await crypto.subtle.importKey('raw', passphase, { name: ALGORITHM }, false, USAGES.algorithm);
const result = await crypto.subtle.deriveKey(
{
name: ALGORITHM,
salt,
hash: DIGEST,
iterations: ITERATIONS,
},
key,
DERIVED_KEY,
true,
USAGES.digest
);
return await crypto.subtle.exportKey('raw', result);
};
/**
* 비밀번호 해시 생성
* @param password 평문 비밀번호
* @return 해시된 비밀번호
*/
export const createPassword = async (password: string): Promise<{ password: string; salt: string }> => {
const salt = createSalt();
return {
password: tob64(await keygen(encoder.encode(password), salt))!,
salt: tob64(salt)!,
};
};
/**
* 평문 비밀번호와 실제 비밀번호 비교
* @param hashed 해시된 비밀번호
* @param request 평문 비밀번호
* @param salt 해시에 필요한 솔트
* @return 비교 결과
*/
export const comparePassword = async (hashed: string, request: string, salt: string): Promise<boolean> => {
const gensalt = fromb64(salt);
return tob64(await keygen(encoder.encode(request), gensalt)) === hashed;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment