Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(crypto): improve docs #4884

Merged
merged 4 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions _tools/check_docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const ENTRY_POINTS = [
"../async/mod.ts",
"../bytes/mod.ts",
"../cli/mod.ts",
"../crypto/mod.ts",
"../collections/mod.ts",
"../data_structures/mod.ts",
"../datetime/mod.ts",
Expand Down
3 changes: 2 additions & 1 deletion crypto/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,8 @@ export type FNVAlgorithms = "FNV32" | "FNV32A" | "FNV64" | "FNV64A";
* @deprecated This will be removed in 1.0.0. Use
* {@linkcode DIGEST_ALGORITHM_NAMES} instead.
*/
export const wasmDigestAlgorithms = DIGEST_ALGORITHM_NAMES;
export const wasmDigestAlgorithms: typeof DIGEST_ALGORITHM_NAMES =
DIGEST_ALGORITHM_NAMES;

/**
* A digest algorithm name supported by std/crypto with a Wasm implementation.
Expand Down
5 changes: 5 additions & 0 deletions crypto/timing_safe_equal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { assert } from "@std/assert/assert";
* {@link https://github.com/w3c/webcrypto/issues/270 | w3c/webcrypto#270}), but until
* that time, `timingSafeEqual()` is provided:
*
* @example Usage
* ```ts
* import { timingSafeEqual } from "@std/crypto/timing-safe-equal";
* import { assert } from "@std/assert/assert";
Expand All @@ -29,6 +30,10 @@ import { assert } from "@std/assert/assert";
*
* assert(timingSafeEqual(a, b));
* ```
*
* @param a The first value to compare.
* @param b The second value to compare.
* @returns `true` if the values are equal, otherwise `false`.
*/
export function timingSafeEqual(
a: ArrayBufferView | ArrayBufferLike | DataView,
Expand Down
104 changes: 100 additions & 4 deletions crypto/unstable_keystack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ async function compare(a: Data, b: Data): Promise<boolean> {
*
* This was inspired by {@link https://github.com/crypto-utils/keygrip/ | keygrip}.
*
* @example
* @example Usage
* ```ts
* import { KeyStack } from "@std/crypto/unstable-keystack";
*
Expand All @@ -98,7 +98,19 @@ export class KeyStack {
return this.#cryptoKeys.get(key)!;
}

/** Number of keys */
/** Number of keys
*
* @example Usage
* ```ts
* import { KeyStack } from "@std/crypto/unstable-keystack";
* import { assertEquals } from "@std/assert/assert-equals";
*
* const keyStack = new KeyStack(["hello", "world"]);
* assertEquals(keyStack.length, 2);
* ```
*
* @returns The length of the key stack.
*/
get length(): number {
return this.#keys.length;
}
Expand All @@ -108,6 +120,17 @@ export class KeyStack {
* data and allows easy key rotation without invalidation of previously signed
* data.
*
* @example Usage
* ```ts
* import { KeyStack } from "@std/crypto/unstable-keystack";
*
iuioiua marked this conversation as resolved.
Show resolved Hide resolved
* const keyStack = new KeyStack(["hello", "world"]);
* const digest = await keyStack.sign("some data");
*
* const rotatedStack = new KeyStack(["deno", "says", "hello", "world"]);
* await rotatedStack.verify("some data", digest); // true
* ```
*
* @param keys An iterable of keys, of which the index 0 will be used to sign
* data, but verification can happen against any key.
*/
Expand All @@ -123,6 +146,20 @@ export class KeyStack {
* Take `data` and return a SHA256 HMAC digest that uses the current 0 index
* of the `keys` passed to the constructor. This digest is in the form of a
* URL safe base64 encoded string.
*
* @example Usage
* ```ts
* import { KeyStack } from "@std/crypto/unstable-keystack";
iuioiua marked this conversation as resolved.
Show resolved Hide resolved
*
* const keyStack = new KeyStack(["hello", "world"]);
* const digest = await keyStack.sign("some data");
*
* const rotatedStack = new KeyStack(["deno", "says", "hello", "world"]);
* await rotatedStack.verify("some data", digest); // true
* ```
*
* @param data The data to sign.
* @returns A URL safe base64 encoded string of the SHA256 HMAC digest.
*/
async sign(data: Data): Promise<string> {
const key = await this.#toCryptoKey(this.#keys[0]!);
Expand All @@ -133,6 +170,21 @@ export class KeyStack {
* Given `data` and a `digest`, verify that one of the `keys` provided the
* constructor was used to generate the `digest`. Returns `true` if one of
* the keys was used, otherwise `false`.
*
* @example Usage
* ```ts
* import { KeyStack } from "@std/crypto/unstable-keystack";
iuioiua marked this conversation as resolved.
Show resolved Hide resolved
*
* const keyStack = new KeyStack(["hello", "world"]);
* const digest = await keyStack.sign("some data");
*
* const rotatedStack = new KeyStack(["deno", "says", "hello", "world"]);
* await rotatedStack.verify("some data", digest); // true
* ```
*
* @param data The data to verify.
* @param digest The digest to verify.
* @returns `true` if the digest was generated by one of the keys, otherwise
*/
async verify(data: Data, digest: string): Promise<boolean> {
return (await this.indexOf(data, digest)) > -1;
Expand All @@ -142,6 +194,21 @@ export class KeyStack {
* Given `data` and a `digest`, return the current index of the key in the
* `keys` passed the constructor that was used to generate the digest. If no
* key can be found, the method returns `-1`.
*
* @example Usage
* ```ts
* import { KeyStack } from "@std/crypto/unstable-keystack";
iuioiua marked this conversation as resolved.
Show resolved Hide resolved
*
* const keyStack = new KeyStack(["hello", "world"]);
* const digest = await keyStack.sign("some data");
*
* const rotatedStack = new KeyStack(["deno", "says", "hello", "world"]);
* await rotatedStack.indexOf("some data", digest);
* ```
*
* @param data The data to verify.
* @param digest The digest to verify.
* @returns The index of the key that was used to generate the digest.
*/
async indexOf(data: Data, digest: string): Promise<number> {
for (let i = 0; i < this.#keys.length; i++) {
Expand All @@ -156,15 +223,44 @@ export class KeyStack {
return -1;
}

/** Custom output for {@linkcode Deno.inspect}. */
/**
* Custom output for {@linkcode Deno.inspect}.
*
* @example Usage
* ```ts
* import { KeyStack } from "@std/crypto/unstable-keystack";
iuioiua marked this conversation as resolved.
Show resolved Hide resolved
*
* const keyStack = new KeyStack(["hello", "world"]);
* console.log(Deno.inspect(keyStack));
* ```
*
* @param inspect The inspect function.
* @returns A string representation of the key stack.
*/
[Symbol.for("Deno.customInspect")](
inspect: (value: unknown) => string,
): string {
const { length } = this;
return `${this.constructor.name} ${inspect({ length })}`;
}

/** Custom output for Node's {@linkcode https://nodejs.org/api/util.html#utilinspectobject-options|util.inspect}. */
/**
* Custom output for Node's {@linkcode https://nodejs.org/api/util.html#utilinspectobject-options|util.inspect}.
*
* @example Usage
* ```ts
* import { KeyStack } from "@std/crypto/unstable-keystack";
* import { inspect } from "node:util";
*
* const keyStack = new KeyStack(["hello", "world"]);
* console.log(inspect(keyStack));
* ```
*
* @param depth The depth to inspect.
* @param options The options to inspect.
* @param inspect The inspect function.
* @returns A string representation of the key stack.
*/
[Symbol.for("nodejs.util.inspect.custom")](
depth: number,
// deno-lint-ignore no-explicit-any
Expand Down
Loading