credo-ts icon indicating copy to clipboard operation
credo-ts copied to clipboard

Support X.509 certificate revocation list creating and verification

Open TimoGlastra opened this issue 9 months ago • 1 comments

TimoGlastra avatar Mar 13 '25 10:03 TimoGlastra

@TimoGlastra Here is a snippet of code from the OGCIO digital wallet that handles CLR generation, for reference:

import * as x509 from '@peculiar/x509'
import {
  AgentContext,
  BaseLogger,
  CredoWebCrypto,
  CredoWebCryptoKey,
  DidKey
} from '@credo-ts/core'
import { credoKeyTypeIntoCryptoKeyAlgorithm } from '@credo-ts/core/build/crypto/webcrypto/utils/keyAlgorithmConversion'
import { FastifyBaseLogger } from 'fastify'
import { CRL_EXPIRATION_DAYS } from '@digital-wallet/common'
/**
 * Creates a Certificate Revocation List (CRL) for the agent.
 *
 * @export
 * @async
 * @param {BaseLogger | FastifyBaseLogger} logger - The logger instance used for logging.
 * @param {CredoWebCryptoKey} publicKey
 * @returns {Promise<void>}
 * @throws Will throw an error if the CRL creation process fails.
 */
export async function createCertificateRevocationList({
  logger,
  entityName,
  context,
  didKey,
  publicKey
}: {
  logger: BaseLogger | FastifyBaseLogger
  entityName: string
  context: AgentContext
  didKey: DidKey
  publicKey: CredoWebCryptoKey
}) {
  try {
    if (!didKey || !didKey.key) {
      throw new Error('Missing or invalid keys')
    }

    const webCrypto = new CredoWebCrypto(context)
    const cryptoKeyAlgorithm = credoKeyTypeIntoCryptoKeyAlgorithm(
      didKey.key.keyType
    )
    const privateKey = new CredoWebCryptoKey(
      didKey.key,
      cryptoKeyAlgorithm,
      false,
      'private',
      ['sign']
    )
    logger.info('Creating Certificate Revocation List')
    const authorityKeyIdentifierExtension =
      await x509.AuthorityKeyIdentifierExtension.create(
        publicKey,
        false, // mark extension as non-critical
        webCrypto
      )
    const crlNumberExtension = new x509.Extension(
      '2.5.29.20', // CRL Number OID
      false, // mark extension as non-critical
      new Uint8Array([0x02, 0x01, 0x01]) // ASN.1 INTEGER with value 1
    )
    const crl = await x509.X509CrlGenerator.create(
      {
        signingKey: privateKey,
        issuer: `CN=${entityName},C=IE`,
        thisUpdate: new Date(),
        nextUpdate: new Date(
          Date.now() + CRL_EXPIRATION_DAYS * 24 * 60 * 60 * 1000
        ),
        extensions: [authorityKeyIdentifierExtension, crlNumberExtension],
        signingAlgorithm: {
          name: 'ECDSA',
          hash: { name: 'SHA-256' }
        }
      },
      webCrypto
    )
    logger.info('Certificate Revocation List created')
    return { crl, privateKey }
  } catch (error) {
    logger.error(`Error creating Certificate Revocation List: ${error.message}`)
    throw new Error(
      `Error creating Certificate Revocation List: ${error.message}`
    )
  }
}

williamlines avatar Apr 02 '25 13:04 williamlines