From 6b5ce84607c484523e2aec5ab225a5231ed228ac Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Wed, 29 May 2024 19:31:31 +0900 Subject: [PATCH 1/3] docs(crypto): improve docs --- _tools/check_docs.ts | 1 + crypto/crypto.ts | 3 +- crypto/timing_safe_equal.ts | 5 ++ crypto/unstable_keystack.ts | 104 ++++++++++++++++++++++++++++++++++-- 4 files changed, 108 insertions(+), 5 deletions(-) diff --git a/_tools/check_docs.ts b/_tools/check_docs.ts index 9b96cbf84d2b..3d3d8c5741c9 100644 --- a/_tools/check_docs.ts +++ b/_tools/check_docs.ts @@ -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", diff --git a/crypto/crypto.ts b/crypto/crypto.ts index 5b47db4ffc63..3e9e8f14ff7e 100644 --- a/crypto/crypto.ts +++ b/crypto/crypto.ts @@ -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. diff --git a/crypto/timing_safe_equal.ts b/crypto/timing_safe_equal.ts index a374cf014713..169f8958e0e5 100644 --- a/crypto/timing_safe_equal.ts +++ b/crypto/timing_safe_equal.ts @@ -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"; @@ -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, diff --git a/crypto/unstable_keystack.ts b/crypto/unstable_keystack.ts index 175edfb79389..b6626d757b45 100644 --- a/crypto/unstable_keystack.ts +++ b/crypto/unstable_keystack.ts @@ -76,7 +76,7 @@ async function compare(a: Data, b: Data): Promise { * * This was inspired by {@link https://github.com/crypto-utils/keygrip/ | keygrip}. * - * @example + * @example Usage * ```ts * import { KeyStack } from "@std/crypto/unstable-keystack"; * @@ -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; } @@ -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"; + * + * 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. */ @@ -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"; + * + * 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 { const key = await this.#toCryptoKey(this.#keys[0]!); @@ -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"; + * + * 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 { return (await this.indexOf(data, digest)) > -1; @@ -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"; + * + * 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 { for (let i = 0; i < this.#keys.length; i++) { @@ -156,7 +223,20 @@ 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"; + * + * 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 { @@ -164,7 +244,23 @@ export class KeyStack { 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 From a530bdb84bb5d5a6ee56532d9f712b673d0584a4 Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Fri, 31 May 2024 08:07:22 +1000 Subject: [PATCH 2/3] tweaks --- crypto/unstable_keystack.ts | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/crypto/unstable_keystack.ts b/crypto/unstable_keystack.ts index b6626d757b45..02231997aab8 100644 --- a/crypto/unstable_keystack.ts +++ b/crypto/unstable_keystack.ts @@ -79,12 +79,13 @@ async function compare(a: Data, b: Data): Promise { * @example Usage * ```ts * import { KeyStack } from "@std/crypto/unstable-keystack"; + * import { assert } from "@std/assert/assert"; * * 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 + * assert(await rotatedStack.verify("some data", digest)); * ``` */ export class KeyStack { @@ -98,7 +99,8 @@ export class KeyStack { return this.#cryptoKeys.get(key)!; } - /** Number of keys + /** + * Number of keys * * @example Usage * ```ts @@ -116,23 +118,19 @@ export class KeyStack { } /** - * A class which accepts an array of keys that are used to sign and verify - * data and allows easy key rotation without invalidation of previously signed - * data. + * Constructs a new instance. * * @example Usage * ```ts * import { KeyStack } from "@std/crypto/unstable-keystack"; + * import { assertInstanceOf } from "@std/assert/assert-instance-of"; * * 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 + * assertInstanceOf(keyStack, KeyStack); * ``` * * @param keys An iterable of keys, of which the index 0 will be used to sign - * data, but verification can happen against any key. + * data, but verification can happen against any key. */ constructor(keys: Iterable) { const values = Array.isArray(keys) ? keys : [...keys]; @@ -150,12 +148,13 @@ export class KeyStack { * @example Usage * ```ts * import { KeyStack } from "@std/crypto/unstable-keystack"; + * import { assert } from "@std/assert/assert"; * * 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 + * assert(await rotatedStack.verify("some data", digest)); * ``` * * @param data The data to sign. @@ -174,12 +173,13 @@ export class KeyStack { * @example Usage * ```ts * import { KeyStack } from "@std/crypto/unstable-keystack"; + * import { assert } from "@std/assert/assert"; * * 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 + * assert(await rotatedStack.verify("some data", digest)); * ``` * * @param data The data to verify. @@ -198,12 +198,13 @@ export class KeyStack { * @example Usage * ```ts * import { KeyStack } from "@std/crypto/unstable-keystack"; + * import { assertEquals } from "@std/assert/assert-equals"; * * 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); + * assertEquals(await rotatedStack.indexOf("some data", digest), 2); * ``` * * @param data The data to verify. From 875a7a29e264a211e67ffcaaedbd7603c150d4f4 Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Fri, 31 May 2024 08:09:56 +1000 Subject: [PATCH 3/3] tweaks --- crypto/unstable_keystack.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crypto/unstable_keystack.ts b/crypto/unstable_keystack.ts index 02231997aab8..93936dbcd698 100644 --- a/crypto/unstable_keystack.ts +++ b/crypto/unstable_keystack.ts @@ -74,7 +74,8 @@ async function compare(a: Data, b: Data): Promise { * * Data is signed as SHA256 HMAC. * - * This was inspired by {@link https://github.com/crypto-utils/keygrip/ | keygrip}. + * This was inspired by + * {@linkcode https://www.npmjs.com/package/keygrip | npm:keygrip}. * * @example Usage * ```ts @@ -246,7 +247,8 @@ export class KeyStack { } /** - * 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