The CryptoApi interface integrates key generation, hashing, and signing functionalities, designed for use with a Key Management System (KMS). It extends AsymmetricKeyGenerator for generating asymmetric keys, Hasher for hash digest computations, and Signer for signing and verifying operations.

Concrete implementations of this interface are intended to be used with a KMS, which is responsible for generating and storing cryptographic keys. The KMS is also responsible for performing cryptographic operations using the keys it manages. The KMS is typically a cloud service, but it can also be a hardware device or software application.

Guidelines for implementing this interface:

  • Must use JSON Web Keys (JWK) as the key format.
  • Must IANA registered JSON Object Signing and Encryption {@ link https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms | (JOSE)} names for algorithm, curves, etc. whenever possible.
  • All I/O that interacts with private or secret keys must be done via reference using a KeyIdentifier. Implementations can use any string as the key identifier (e.g. JWK thumbprint, UUID generated by hosted KMS, etc.).
  • Must support key generation, hashing, signing, and verifying operations.
  • May be extended to support other cryptographic operations.
  • Implementations of the CryptoApi interface can be passed as an argument to the public API methods of Web5 libraries that involve key material (e.g., DID creation, VC signing, arbitrary data signing/verification, etc.).

Implements

Constructors

Properties

_algorithmInstances: Map<typeof EdDsaAlgorithm | typeof EcdsaAlgorithm | typeof Sha2Algorithm, CryptoAlgorithm> = ...

A private map that stores instances of cryptographic algorithm implementations. Each key in this map is an AlgorithmConstructor, and its corresponding value is an instance of a class that implements a specific cryptographic algorithm. This map is used to cache and reuse instances for performance optimization, ensuring that each algorithm is instantiated only once.

_keyStore: KeyValueStore<string, Jwk>

The _keyStore private variable in LocalKeyManager is a KeyValueStore instance used for storing and managing cryptographic keys. It allows the LocalKeyManager class to save, retrieve, and handle keys efficiently within the local Key Management System (KMS) context. This variable can be configured to use different storage backends, like in-memory storage or persistent storage, providing flexibility in key management according to the application's requirements.

Methods

  • Generates a hash digest of the provided data.

    Parameters

    Returns Promise<Uint8Array>

    A Promise which will be fulfilled with the hash digest.

    Remarks

    A digest is the output of the hash function. It's a fixed-size string of bytes that uniquely represents the data input into the hash function. The digest is often used for data integrity checks, as any alteration in the input data results in a significantly different digest.

    It takes the algorithm identifier of the hash function and data to digest as input and returns the digest of the data.

    Example

    const keyManager = new LocalKeyManager();
    const data = new Uint8Array([...]);
    const digest = await keyManager.digest({ algorithm: 'SHA-256', data });
  • Exports a private key identified by the provided key URI from the local KMS.

    Parameters

    Returns Promise<Jwk>

    A Promise resolving to the JWK representation of the exported key.

    Remarks

    This method retrieves the key from the key store and returns it. It is primarily used for extracting keys for backup or transfer purposes.

    Example

    const keyManager = new LocalKeyManager();
    const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
    const privateKey = await keyManager.exportKey({ keyUri });
  • Generates a new cryptographic key in the local KMS with the specified algorithm and returns a unique key URI which can be used to reference the key in subsequent operations.

    Parameters

    Returns Promise<string>

    A Promise that resolves to the key URI, a unique identifier for the generated key.

    Example

    const keyManager = new LocalKeyManager();
    const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
    console.log(keyUri); // Outputs the key URI
  • Retrieves an algorithm implementation instance based on the provided algorithm name.

    Parameters

    • params: {
          algorithm: "SHA-256" | "Ed25519" | "secp256k1" | "secp256r1";
      }

      The parameters for retrieving the algorithm implementation.

      • algorithm: "SHA-256" | "Ed25519" | "secp256k1" | "secp256r1"

        The name of the algorithm to retrieve.

    Returns CryptoAlgorithm

    An instance of the requested algorithm implementation.

    Remarks

    This method checks if the requested algorithm is supported and returns a cached instance if available. If an instance does not exist, it creates and caches a new one. This approach optimizes performance by reusing algorithm instances across cryptographic operations.

    Example

    const signer = this.getAlgorithm({ algorithm: 'Ed25519' });
    

    Throws

    Error if the requested algorithm is not supported.

  • Determines the name of the algorithm based on the key's properties.

    Parameters

    • params: {
          key: {
              alg?: string;
              crv?: string;
          };
      }

      The parameters for determining the algorithm name.

      • key: {
            alg?: string;
            crv?: string;
        }

        A JWK containing the alg or crv properties.

        • Optional alg?: string
        • Optional crv?: string

    Returns "SHA-256" | "Ed25519" | "secp256k1" | "secp256r1"

    The name of the algorithm associated with the key.

    Remarks

    This method facilitates the identification of the correct algorithm for cryptographic operations based on the alg or crv properties of a JWK.

    Example

    const publicKey = { ... }; // Public key in JWK format
    const algorithm = this.getAlgorithmName({ key: publicKey });

    Throws

    Error if the algorithm cannot be determined from the provided input.

  • Computes the Key URI for a given public JWK (JSON Web Key).

    Parameters

    Returns Promise<string>

    A Promise that resolves to the key URI as a string.

    Remarks

    This method generates a URI (Uniform Resource Identifier) for the given JWK, which uniquely identifies the key across all CryptoApi implementations. The key URI is constructed by appending the JWK thumbprint to the prefix urn:jwk:. The JWK thumbprint is deterministically computed from the JWK and is consistent regardless of property order or optional property inclusion in the JWK. This ensures that the same key material represented as a JWK will always yield the same thumbprint, and therefore, the same key URI.

    Example

    const keyManager = new LocalKeyManager();
    const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
    const publicKey = await keyManager.getPublicKey({ keyUri });
    const keyUriFromPublicKey = await keyManager.getKeyUri({ key: publicKey });
    console.log(keyUri === keyUriFromPublicKey); // Outputs `true`
  • Retrieves a private key from the key store based on the provided key URI.

    Parameters

    • params: {
          keyUri: string;
      }

      Parameters for retrieving the private key.

      • keyUri: string

        The key URI identifying the private key to retrieve.

    Returns Promise<Jwk>

    A Promise resolving to the JWK representation of the private key.

    Example

    const privateKey = this.getPrivateKey({ keyUri: 'urn:jwk:...' });
    

    Throws

    Error if the key is not found in the key store.

  • Retrieves the public key associated with a previously generated private key, identified by the provided key URI.

    Parameters

    Returns Promise<Jwk>

    A Promise that resolves to the public key in JWK format.

    Example

    const keyManager = new LocalKeyManager();
    const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
    const publicKey = await keyManager.getPublicKey({ keyUri });
  • Imports a private key into the local KMS.

    Parameters

    Returns Promise<string>

    A Promise resolving to the key URI, uniquely identifying the imported key.

    Remarks

    This method stores the provided JWK in the key store, making it available for subsequent cryptographic operations. It is particularly useful for initializing the KMS with pre-existing keys or for restoring keys from backups.

    Note that, if defined, the kid (key ID) property of the JWK is used as the key URI for the imported key. If the kid property is not provided, the key URI is computed from the JWK thumbprint of the key.

    Example

    const keyManager = new LocalKeyManager();
    const privateKey = { ... } // A private key in JWK format
    const keyUri = await keyManager.importKey({ key: privateKey });
  • Signs the provided data using the private key identified by the provided key URI.

    Parameters

    Returns Promise<Uint8Array>

    A Promise resolving to the digital signature as a Uint8Array.

    Remarks

    This method uses the signature algorithm determined by the alg and/or crv properties of the private key identified by the provided key URI to sign the provided data. The signature can later be verified by parties with access to the corresponding public key, ensuring that the data has not been tampered with and was indeed signed by the holder of the private key.

    Example

    const keyManager = new LocalKeyManager();
    const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
    const data = new TextEncoder().encode('Message to sign');
    const signature = await keyManager.sign({ keyUri, data });
  • Verifies a digital signature associated the provided data using the provided key.

    Parameters

    Returns Promise<boolean>

    A Promise resolving to a boolean indicating whether the signature is valid.

    Remarks

    This method uses the signature algorithm determined by the alg and/or crv properties of the provided key to check the validity of a digital signature against the original data. It confirms whether the signature was created by the holder of the corresponding private key and that the data has not been tampered with.

    Example

    const keyManager = new LocalKeyManager();
    const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
    const data = new TextEncoder().encode('Message to sign');
    const signature = await keyManager.sign({ keyUri, data });
    const isSignatureValid = await keyManager.verify({ keyUri, data, signature });