UNPKG

@better-auth/utils

Version:

A collection of utilities for better-auth

385 lines (253 loc) 11.2 kB
# Better Auth Utils A simple typescript API for common auth utilities like hashing, encryption, encoding, and OTP generation. Built on top of Web Crypto APIs to provide a unified API for both Node.js (using the Crypto module) and web environments (using the Web Crypto API) through Conditional Exports. ```bash pnpm add @better-auth/utils ``` ## Utilities at a Glance utilities provided by `@better-auth/utils`: | Utility | Description | |-------------------|----------------------------------------------------| | [**Hash**](#hash) | Hash inputs using sha family hash functions. | | [**HMAC**](#hmac) | Hash inputs using HMAC with a secret key. | | [**Random String**](#random-string) | Generate random strings with a specified length and charset. | | [**RSA**](#rsa) | Perform encryption, decryption, signing, and verification with RSA keys. | | [**ECDSA**](#ecdsa) | Perform signing and verification with ECDSA keys. | | [**OTP**](#otp) | Generate and verify one-time passwords. | | [**Base64**](#base64) | Encode and decode data in base64 format. | | [**Hex**](#hex) | Encode and decode data in hexadecimal format. | | [**Binary**](#binary) | Encode and decode data in binary format. | ## Hash Digest provides a way to hash an input using sha family hash functions. It wraps over `crypto.digest` and provide utilities to encode output in hex or base 64. ```ts import { createHash } from "@better-auth/utils/hash" const hashBuffer = await createHash("SHA-256").digest("text"); const hashInHex = await createHash("SHA-256", "hex").digest("text"); ``` To encode output in base64 ```ts const hashInBase64 = await createHash("SHA-256", "base64").digest("text"); ``` ## HMAC The HMAC utility allows you to securely hash data using a secret key and SHA family hash functions. It provides methods to `sign`, `verify`, and `create` a customized HMAC instance with specific hashing algorithms and encoding formats. ### Create HMAC To create an HMAC instance, use the createHMAC function. You can specify the SHA family algorithm ("SHA-256", "SHA-384", or "SHA-512") and the desired encoding format ("none", "hex", "base64", "base64url", or "base64urlnopad"). It takes a secret key and returns a key object which could be used to sign and verify data. ```ts import { createHMAC } from './hmac'; const hmac = createHMAC("SHA-256", "hex"); // Customize algorithm and encoding ``` ### Import Key The importKey method takes a secret key (string, buffer, or typed array) and returns a CryptoKey object that can be used for signing and verifying data. ```ts const secretKey = "my-secret-key"; // Can also be a buffer or TypedArray const key = await hmac.importKey(secretKey); ``` ### Sign The sign method takes a secret key (or CryptoKey) and data to generate a signature. If you provide a raw secret key, it will automatically be imported. ```ts const key = await hmac.importKey("my-secret-key"); const signature = await hmac.sign(key, "text to sign"); console.log(signature); // Encoded based on the selected encoding format (e.g., hex) ``` You could also directly sign using the raw string secret key. ```ts const signature2 = await hmac.sign("secret-key",{ data: "text" }); ``` ### Verify The verify method checks if a given signature matches the data using the secret key. You can provide either a raw secret key or a CryptoKey. ```ts const key = await hmac.importKey("my-secret-key"); const isValid = await hmac.verify(key, "text to sign", signature); console.log(isValid); // true or false ``` ## Random String Random crypto secure string generator. It wraps over `crypto.getRandomValues` and provide utilities to generator based on length and charset. 1. first create a random string generator with desired charset. ```ts import { createRandomStringGenerator } from "@better-auth/utils/random" export const generateRandomString = createRandomStringGenerator("A-Z", "0-9", "a-z", "-_") ``` 2. generate random string based on length. ```ts const randomString = generateRandomString(32) const randomString2 = generateRandomString(32, "A-Z", "0-9") // override charset ``` ## RSA RSA utilities provide a simple interface to work with RSA cryptographic operations, such as generating key pairs, encrypting and decrypting data, and signing and verifying messages. ### Key Pair Generation You can generate RSA key pairs with specified parameters. By default, the `modulusLength` is 2048 bits and the hash algorithm is `SHA-256`. ```ts import { rsa } from "@better-auth/utils/rsa"; const keyPair = await rsa.generateKeyPair(2048, "SHA-256"); const { publicKey, privateKey } = keyPair; ``` ### Exporting Keys Export a public or private key in your preferred format. ```ts const jwk = await rsa.exportKey(publicKey, "jwk"); const spki = await rsa.exportKey(publicKey, "spki"); ``` ### Importing Keys Import a key in the `jwk` format for specific usage (`encrypt`, `decrypt`, `sign`, or `verify`). ```ts const importedKey = await rsa.importKey(jwk, "encrypt"); ``` ### Encryption Encrypt sensitive data using an RSA public key. Input can be a string, `ArrayBuffer`, `TypedArray` or `string`. ```ts const encryptedData = await rsa.encrypt(publicKey, "Sensitive data"); ``` ### Decryption Decrypt encrypted data using the corresponding RSA private key. ```ts const decryptedData = await rsa.decrypt(privateKey, encryptedData); const originalText = new TextDecoder().decode(decryptedData); ``` ### Signing Sign a message using the RSA private key. Input can be a string, `ArrayBuffer`, or `TypedArray`. ```ts const signature = await rsa.sign(privateKey, "Message to sign"); ``` ### Verifying Verify a signature against the original data using the RSA public key. ```ts const isValid = await rsa.verify(publicKey, { signature, data: "Message to sign", }); ``` ## ECDSA ECDSA utilities provide a simple interface to perform key pair generation, signing, and verification using elliptic curve cryptography. ### Key Pair Generation You can generate ECDSA key pairs with your preferred curve. Supported curves are `"P-256"`, `"P-384"`, and `"P-521"`. ```ts import { ecdsa } from "@better-auth/utils/ecdsa"; const { privateKey, publicKey } = await ecdsa.generateKeyPair("P-256"); ``` ### Exporting Keys Export a public or private key in your preferred format, such as `pkcs8` or `spki`. ```ts const exportedPrivateKey = await ecdsa.exportKey(privateKey, "pkcs8"); const exportedPublicKey = await ecdsa.exportKey(publicKey, "spki"); ``` ### Importing Keys Import an ECDSA private or public key in the appropriate format. Public keys can also be provided as strings. ```ts const importedPrivateKey = await ecdsa.importPrivateKey(exportedPrivateKey, "P-256"); const importedPublicKey = await ecdsa.importPublicKey(exportedPublicKey, "P-256"); ``` ### Signing Sign data using the ECDSA private key. The input can be a string or `ArrayBuffer`. You can specify the hash algorithm, which defaults to `"SHA-256"`. ```ts const signature = await ecdsa.sign(privateKey, "Message to sign", "SHA-256"); ``` ### Verifying Verify a signature against the original data using the ECDSA public key. Input can be a string or `ArrayBuffer`. Signature verification requires providing the signature, data, and hash algorithm (default: `"SHA-256"`). ```ts const isValid = await ecdsa.verify(publicKey, { signature, data: "Message to verify", hash: "SHA-256", }); ``` ## OTP The OTP utility provides a simple and secure way to generate and verify one-time passwords (OTPs), commonly used in multi-factor authentication (MFA) systems. It includes support for both HOTP (HMAC-based One-Time Password) and TOTP (Time-based One-Time Password) standards. It's implemented based on [RFC 4226](https://tools.ietf.org/html/rfc4226) and [RFC 6238](https://tools.ietf.org/html/rfc6238). ### Generating HOTP HOTP generates a one-time password based on a counter value and a secret key. The counter should be incremented for each new OTP. ```ts import { createOTP } from "@better-auth/utils/otp"; const secret = "my-super-secret-key"; const counter = 1234; const otp = createOTP(secret, { digits: 6, }).hotp(counter); ``` ### Generating TOTP TOTP generates a one-time password based on the current time and a secret key. The time step is typically 30 seconds. ```ts import { createOTP } from "@better-auth/utils/otp"; const secret = "my-super-secret-key" const otp = createOTP(secret, { digits: 6, period: 30, }).totp(); ``` ### Verifying TOTP Verify a TOTP against the secret key and a specified time window. The default time window is 30 seconds. ```ts import { createOTP } from "@better-auth/utils/otp"; const secret = "my-super-secret-key" const isValid = createOTP(secret, { digits: 6, period: 30, }).verify(otp); ``` You can also specify the time window in seconds. ```ts import { createOTP } from "@better-auth/utils"; const isValid = createOTP(secret).verify(otp, { window: 60 }); ``` ### Generate URL for Authenticator App Generate a URL for provisioning a TOTP secret key in an authenticator app. - `issuer` - The name of the service or app. - `account` - The user's email or username. ```ts import { createOTP } from "@better-auth/utils/otp"; const secret = "my-super-secret-key"; const qrCodeUrl = createOTP(secret).url("my-app", "user@email.com"); ``` ## Base64 Base64 utilities provide a simple interface to encode and decode data in base64 format. ### Encoding Encode data in base64 format. Input can be a string, `ArrayBuffer`, or `TypedArray`. ```ts import { base64 } from "@better-auth/utils/base64"; const encodedData = base64.encode("Data to encode"); ``` options: - `padding` - Include padding characters (`=`) at the end of the encoded string ```ts const encodedData = base64.encode("Data to encode", { url: true, padding: false }); ``` ### Decoding Decode base64-encoded data. Input can be a string or `ArrayBuffer`. ```ts const decodedData = await base64.decode(encodedData); ``` It automatically detects if the input is URL-safe and includes padding characters. ### Base64Url Url safe alternative ```ts import { base64Url } from "@better-auth/utils/base64"; const encodedData = base64Url.encode("Data to encode"); ``` ## Hex Hex utilities provide a simple interface to encode and decode data in hexadecimal format. ### Encoding Encode data in hexadecimal format. Input can be a string, `ArrayBuffer`, or `TypedArray`. ```ts import { hex } from "@better-auth/utils/hex"; const encodedData = hex.encode("Data to encode"); ``` ### Decoding Decode hexadecimal-encoded data. Input can be a string or `ArrayBuffer`. ```ts const decodedData = hex.decode(encodedData); ``` ## Binary A utilities provide a simple interface to encode and decode data in binary format. It uses `TextEncode` and `TextDecoder` to encode and decode data respectively. ### Encoding ```ts import { binary } from "@better-auth/util/binary" const data = binary.encode("Hello World!") ``` ### Decoding ```ts import { binary } from "@better-auth/util/binary" const data = binary.decode(new Unit8Array([[72, 101, 108, 108, 111]])) ``` ## License MIT