diff --git a/packages/auto-id/package.json b/packages/auto-id/package.json index c3a70e4c..792d403c 100644 --- a/packages/auto-id/package.json +++ b/packages/auto-id/package.json @@ -12,6 +12,8 @@ "@autonomys/auto-utils": "workspace:*", "@peculiar/asn1-schema": "^2.3.8", "@peculiar/asn1-x509": "^2.3.8", + "@peculiar/webcrypto": "^1.5.0", + "@peculiar/x509": "^1.11.0", "asn1js": "^3.0.5" }, "files": [ @@ -26,4 +28,4 @@ "ts-node": "^10.9.2", "typescript": "^5.4.5" } -} +} \ No newline at end of file diff --git a/packages/auto-id/src/certificateManager.ts b/packages/auto-id/src/certificateManager.ts new file mode 100644 index 00000000..1687c9db --- /dev/null +++ b/packages/auto-id/src/certificateManager.ts @@ -0,0 +1,344 @@ +//! For key generation, management, `keyManagement.ts` file is used using "crypto" library. +//! And for certificate related, used "@peculiar/x509" library. + +import { + blake2b_256, + concatenateUint8Arrays, + save, + stringToUint8Array, +} from '@autonomys/auto-utils' +import { AsnConvert } from '@peculiar/asn1-schema' +import { AttributeTypeAndValue, GeneralNames } from '@peculiar/asn1-x509' +import { Crypto } from '@peculiar/webcrypto' +import * as x509 from '@peculiar/x509' +import { KeyObject, createPublicKey } from 'crypto' +import { doPublicKeysMatch, pemToPublicKey } from './keyManagement' + +const crypto = new Crypto() +x509.cryptoProvider.set(crypto) + +interface SigningParams { + privateKey: CryptoKey + algorithm: 'sha256' | null // Only 'sha256' or null for Ed25519 +} + +export const OID_COMMON_NAME = '2.5.4.3' // OID for Common Name, not available in the library. +const OID_SUBJECT_ALT_NAME = '2.5.29.17' // OID for Subject Alternative Name, not available in the library. + +export class CertificateManager { + private certificate: x509.X509Certificate | null + private privateKey: CryptoKey | null + private publicKey: CryptoKey | null + + constructor( + certificate: x509.X509Certificate | null = null, + privateKey: CryptoKey | null = null, + publicKey: CryptoKey | null = null, + ) { + this.certificate = certificate + this.privateKey = privateKey + this.publicKey = publicKey + } + + protected prepareSigningParams(): SigningParams { + const privateKey = this.privateKey + + if (!privateKey) { + throw new Error('Private key is not set.') + } + + if (privateKey.algorithm.name === 'Ed25519') { + return { privateKey: privateKey, algorithm: null } + } + + if (privateKey.algorithm.name === 'rsa') { + return { privateKey: privateKey, algorithm: 'sha256' } + } + + throw new Error('Unsupported key type for signing.') + } + + protected static toCommonName(subjectName: string): x509.Name { + const commonNameAttr = new AttributeTypeAndValue({ + type: OID_COMMON_NAME, + value: subjectName, + }) + return new x509.Name([[commonNameAttr]]) + } + + static prettyPrintCertificate(cert: x509.X509Certificate): void { + console.log('Certificate:') + console.log('============') + console.log(`Subject: ${cert.subject}`) + console.log(`Issuer: ${cert.issuer}`) + console.log(`Serial Number: ${cert.serialNumber}`) + console.log(`Not Valid Before: ${cert.notBefore}`) + console.log(`Not Valid After: ${cert.notAfter}`) + + console.log('\nExtensions:') + cert.extensions.forEach((ext) => { + console.log(` - ${ext.type}: ${JSON.stringify(ext.value)}`) + }) + console.log('\nPublic Key:') + console.log(cert.publicKey) + } + + static certificateToPem(cert: x509.X509Certificate): string { + return cert.toString('pem') + } + + static pemToCertificate(pem: string): x509.X509Certificate { + return new x509.X509Certificate(pem) + } + + static getSubjectCommonName(subject: x509.Name): string | undefined { + const commonNames = subject.getField(OID_COMMON_NAME) // OID for commonName + return commonNames.length > 0 ? commonNames[0] : undefined + } + + static getCertificateAutoId(certificate: x509.X509Certificate): string | undefined { + const sanExtension = certificate.extensions.find((ext) => ext.type === OID_SUBJECT_ALT_NAME) + + if (sanExtension && sanExtension.value) { + // Deserialize the ArrayBuffer to GeneralNames ASN.1 object + const san = AsnConvert.parse(sanExtension.value, GeneralNames) + + for (const name of san) { + if ( + name.uniformResourceIdentifier && + name.uniformResourceIdentifier.startsWith('autoid:auto:') + ) { + return name.uniformResourceIdentifier.split(':').pop() + } + } + } + return undefined + } + + async createCSR(subjectName: string): Promise { + const privateKey = this.privateKey + const publicKey = this.publicKey + + if (!privateKey || !publicKey) { + throw new Error('Private or public key is not set.') + } + + // Set the signing algorithm based on the key type + let signingAlgorithm: Algorithm | EcdsaParams + if (privateKey.algorithm.name === 'Ed25519') { + signingAlgorithm = { name: 'Ed25519' } + } else if (privateKey.algorithm.name === 'rsa') { + signingAlgorithm = { name: 'RSASSA-PKCS1-v1_5', hash: { name: 'SHA-256' } } + } else { + throw new Error('Unsupported key type for signing') + } + + const csr = await x509.Pkcs10CertificateRequestGenerator.create({ + name: `CN=${subjectName}`, + keys: { + privateKey: privateKey, + publicKey: publicKey, + }, + signingAlgorithm: signingAlgorithm, + }) + + return csr + } + + async signCSR(csr: x509.Pkcs10CertificateRequest): Promise { + const privateKey = this.privateKey + if (!privateKey) { + throw new Error('Private key is not set.') + } + + const _signingParams = this.prepareSigningParams() + + const derBuffer = csr.rawData + const signature = await crypto.subtle.sign(privateKey.algorithm.name, privateKey, derBuffer) + csr.signature = new Uint8Array(signature) + + return csr + } + + async createAndSignCSR(subjectName: string): Promise { + const csr = await this.createCSR(subjectName) + return this.signCSR(csr) + } + + // TODO: later on move to "keyManagement.ts" + private static publicKeyToKeyObject(publicKey: x509.PublicKey): KeyObject { + // Export the key data to ArrayBuffer + const keyData = publicKey.rawData // DER format + + // Create a KeyObject from the key data + const keyObject = createPublicKey({ + key: Buffer.from(keyData), + format: 'der', + type: 'spki', + }) + + return keyObject + } + + async issueCertificate( + csr: x509.Pkcs10CertificateRequest, + validityPeriodDays: number = 365, + ): Promise { + const privateKey = this.privateKey + const publicKey = this.publicKey + if (!privateKey || !publicKey) { + throw new Error('Private or public key is not set.') + } + + let issuerName: x509.Name + let autoId: string + const certificate = this.certificate + if (!certificate) { + issuerName = csr.subjectName + const subjectCommonName = CertificateManager.getSubjectCommonName(issuerName) + if (!subjectCommonName) { + throw new Error('Subject common name not found in CSR.') + } + autoId = blake2b_256(stringToUint8Array(subjectCommonName)) + } else { + if ( + // FIXME: modify + !doPublicKeysMatch( + CertificateManager.publicKeyToKeyObject(certificate.publicKey), + pemToPublicKey(await cryptoKeyToPem(publicKey)), + ) + ) { + throw new Error( + 'Issuer certificate public key does not match the private key used for signing.', + ) + } + + issuerName = certificate.subjectName + const certificateAutoId = CertificateManager.getCertificateAutoId(certificate) || '' + const certificateSubjectCommonName = + CertificateManager.getSubjectCommonName(certificate.subjectName) || '' + if (certificateAutoId === '' || certificateSubjectCommonName === '') { + throw new Error( + 'Issuer certificate does not have either an auto ID or a subject common name or both.', + ) + } + autoId = blake2b_256( + concatenateUint8Arrays( + stringToUint8Array(certificateAutoId), + stringToUint8Array(certificateSubjectCommonName), + ), + ) + } + + // Prepare the certificate builder with information from the CSR + const notBefore = new Date() + const notAfter = new Date() + notAfter.setDate(notBefore.getDate() + validityPeriodDays) + + let certificateBuilder = await x509.X509CertificateGenerator.create({ + issuer: csr.subject, + subject: csr.subject, + notBefore, + notAfter, + signingAlgorithm: privateKey.algorithm, + publicKey: publicKey, + signingKey: privateKey, + }) + + const autoIdSan = `autoid:auto:${Buffer.from(autoId).toString('hex')}` + + const sanExtensions = csr.extensions.filter((ext) => ext.type === OID_SUBJECT_ALT_NAME) // OID for subjectAltName + if (sanExtensions.length) { + // const existingSan = sanExtensions[0].value + const existingSan = sanExtensions[0] as x509.SubjectAlternativeNameExtension + + const generalNames = existingSan.names.toJSON() + + // Add autoIdSan to generalNames + generalNames.push({ + type: 'url' as x509.GeneralNameType, + value: autoIdSan, + }) + + // const newSanExtension = existingSan + CertificateManager.stringToArrayBuffer(autoIdSan) + const newSanExtension = new x509.SubjectAlternativeNameExtension( + generalNames, + existingSan.critical, + ) + certificateBuilder.extensions.push(newSanExtension) + } else { + // certificateBuilder.extensions.push( + // new x509.SubjectAlternativeNameExtension([autoIdSan]), + // false, + // ) + + certificateBuilder.extensions.push( + new x509.SubjectAlternativeNameExtension([ + { type: 'url' /* as x509.GeneralNameType */, value: autoIdSan }, + ]), + ) + } + + // Copy all extensions from the CSR to the certificate + for (const ext of csr.extensions) { + // certificateBuilder.extensions.push(new x509.Extension(ext.value, ext.critical)) + certificateBuilder.extensions.push(ext) + } + + const certificateSigned = await x509.X509CertificateGenerator.create({ + serialNumber: certificateBuilder.serialNumber, + issuer: certificateBuilder.issuer, + subject: certificateBuilder.subject, + notBefore: certificateBuilder.notBefore, + notAfter: certificateBuilder.notAfter, + extensions: certificateBuilder.extensions, + publicKey: certificateBuilder.publicKey, + signingAlgorithm: certificateBuilder.signatureAlgorithm, + signingKey: privateKey, + }) + + return certificateSigned + } + + async selfIssueCertificate( + subjectName: string, + validityPeriodDays: number = 365, + ): Promise { + if (!this.privateKey || !this.publicKey) { + throw new Error('Private or public key is not set.') + } + + const csr = await this.createAndSignCSR(subjectName) + const certificate = await this.issueCertificate(csr, validityPeriodDays) + + this.certificate = certificate + return certificate + } + + async saveCertificate(filePath: string): Promise { + if (!this.certificate) { + throw new Error('No certificate available to save.') + } + + const certificatePem = CertificateManager.certificateToPem(this.certificate) + await save(filePath, certificatePem) + } +} + +function arrayBufferToBase64(buffer: ArrayBuffer): string { + let binary = '' + const bytes = new Uint8Array(buffer) + const len = bytes.byteLength + for (let i = 0; i < len; i++) { + binary += String.fromCharCode(bytes[i]) + } + return btoa(binary) +} + +async function cryptoKeyToPem(key: CryptoKey): Promise { + const exported = await crypto.subtle.exportKey(key.type === 'private' ? 'pkcs8' : 'spki', key) + const base64 = arrayBufferToBase64(exported) + const type = key.type === 'private' ? 'PRIVATE KEY' : 'PUBLIC KEY' + const pem = `-----BEGIN ${type}-----\n${base64.match(/.{1,64}/g)?.join('\n')}\n-----END ${type}-----` + return pem +} diff --git a/packages/auto-id/src/index.ts b/packages/auto-id/src/index.ts index 55276676..953fd9ca 100644 --- a/packages/auto-id/src/index.ts +++ b/packages/auto-id/src/index.ts @@ -1,2 +1,3 @@ +export * from './certificateManager' export * from './keyManagement' export * from './utils' diff --git a/packages/auto-id/src/keyManagement.ts b/packages/auto-id/src/keyManagement.ts index 391f2618..a8f92a87 100644 --- a/packages/auto-id/src/keyManagement.ts +++ b/packages/auto-id/src/keyManagement.ts @@ -19,6 +19,24 @@ export function generateRsaKeyPair(keySize: number = 2048): [string, string] { return [privateKey, publicKey] } +import { Crypto } from '@peculiar/webcrypto' +import * as x509 from '@peculiar/x509' +const crypto = new Crypto() + +// FIXME: keep one function. need to modify the tests. +export async function generateEd25519KeyPair2(): Promise<[CryptoKey, CryptoKey]> { + const keyPair = await crypto.subtle.generateKey( + { + name: 'Ed25519', + namedCurve: 'Ed25519', + }, + true, + ['sign', 'verify'], + ) + + return [keyPair.privateKey, keyPair.publicKey] +} + /** * Generates an Ed25519 key pair. * @returns A tuple containing the Ed25519 private key and public key. @@ -167,7 +185,7 @@ export async function loadPrivateKey(filePath: string, password?: string): Promi try { const keyData = await read(filePath) const privateKey = pemToPrivateKey(keyData, password) - return privateKey; + return privateKey } catch (error: any) { throw new Error(`Failed to load private key: ${error.message}`) } @@ -286,4 +304,42 @@ export function doPublicKeysMatch(publicKey1: KeyObject, publicKey2: KeyObject): // Compare the serialized public key data return publicKey1Der.equals(publicKey2Der) -} \ No newline at end of file +} + +// TODO: finalize which function is to keep (from node's crypto or webcrypto) +// This can be done only after completing the AutoID package and testing +// it to see which one is useful. +// export async function doPublicKeysMatch( +// publicKey1: CryptoKey, +// publicKey2: CryptoKey, +// ): Promise { +// const publicKey1Raw = new Uint8Array(await crypto.subtle.exportKey('spki', publicKey1)) +// const publicKey2Raw = new Uint8Array(await crypto.subtle.exportKey('spki', publicKey2)) + +// const publicKey1Hex = Array.from(new Uint8Array(publicKey1Raw)) +// .map((byte) => byte.toString(16).padStart(2, '0')) +// .join('') +// const publicKey2Hex = Array.from(publicKey2Raw) +// .map((byte) => byte.toString(16).padStart(2, '0')) +// .join('') + +// return publicKey1Hex === publicKey2Hex +// } + +export async function validateCertificatePublicKey( + certPublicKey: x509.PublicKey, + derivedPublicKey: CryptoKey, +): Promise { + const derivedPublicKeyRaw = new Uint8Array( + await crypto.subtle.exportKey('spki', derivedPublicKey), + ) + + const certPublicKeyHex = Array.from(new Uint8Array(certPublicKey.rawData)) + .map((byte) => byte.toString(16).padStart(2, '0')) + .join('') + const derivedPublicKeyHex = Array.from(derivedPublicKeyRaw) + .map((byte) => byte.toString(16).padStart(2, '0')) + .join('') + + return certPublicKeyHex === derivedPublicKeyHex +} diff --git a/packages/auto-id/src/utils.ts b/packages/auto-id/src/utils.ts index 62093fe2..e7ac9a94 100644 --- a/packages/auto-id/src/utils.ts +++ b/packages/auto-id/src/utils.ts @@ -1,4 +1,5 @@ import { ObjectIdentifier } from 'asn1js' +import { randomBytes } from 'crypto' /** * Encodes a given string representation of an OID into its DER format. @@ -21,3 +22,9 @@ export function derEncodeSignatureAlgorithmOID(oid: string): Uint8Array { return new Uint8Array([...sequenceHeader, ...new Uint8Array(berArrayBuffer), ...nullParameter]) } + +export function addDaysToCurrentDate(days: number): Date { + const currentDate = new Date() // This gives you the current date and time + currentDate.setUTCDate(currentDate.getUTCDate() + days) // Adds the specified number of days + return currentDate +} diff --git a/packages/auto-id/tests/certificateManager.test.ts b/packages/auto-id/tests/certificateManager.test.ts new file mode 100644 index 00000000..442e4242 --- /dev/null +++ b/packages/auto-id/tests/certificateManager.test.ts @@ -0,0 +1,140 @@ +import { AsnConvert } from '@peculiar/asn1-schema' +import { Certificate } from '@peculiar/asn1-x509' +import { Crypto } from '@peculiar/webcrypto' +import * as x509 from '@peculiar/x509' +import { CertificateManager, OID_COMMON_NAME } from '../src/certificateManager' +import { generateEd25519KeyPair2, validateCertificatePublicKey } from '../src/keyManagement' + +const crypto = new Crypto() + +function getTbsCertificate(cert: x509.X509Certificate): ArrayBuffer { + const asn1 = AsnConvert.parse(cert.rawData, Certificate) + return AsnConvert.serialize(asn1.tbsCertificate) +} + +describe('CertificateManager', () => { + it('create and sign CSR', async () => { + // Generate an Ed25519 key pair + const [privateKey, publicKey] = await generateEd25519KeyPair2() + + // Instantiate CertificateManager with the generated private key + const certificateManager = new CertificateManager(null, privateKey, publicKey) + + // Create and sign a CSR + const subjectName = 'Test' + const csr = await certificateManager.createAndSignCSR(subjectName) + expect(csr).not.toBeNull() + + // Assert that the CSR subject name matches the provided subject name + const commonNameField = csr.subjectName.getField(OID_COMMON_NAME)[0] + expect(commonNameField).toEqual(subjectName) + + expect(await validateCertificatePublicKey(csr.publicKey, publicKey)).toBe(true) + }) + + it('issue certificate', async () => { + // Generate an Ed25519 key pair + const [issuerPrivateKey, issuerPublicKey] = await generateEd25519KeyPair2() + const [subjectPrivateKey, subjectPublicKey] = await generateEd25519KeyPair2() + + const issuer = new CertificateManager(null, issuerPrivateKey, issuerPublicKey) + const _issuerCertificate = await issuer.selfIssueCertificate('issuer') + + // Define the subject name for the certificate + const subjectName = 'Test' + const csrCreator = new CertificateManager(null, subjectPrivateKey, subjectPublicKey) + + // Call the createCSR function to generate a CSR + const csr = await csrCreator.createAndSignCSR(subjectName) + + // Issue a certificate using the CSR + const certificate = await issuer.issueCertificate(csr) + + // Assert that the certificate is not null + expect(certificate).not.toBeNull() + + // Assert that the certificate subject name matches the provided subject name + const commonNameField = csr.subjectName.getField(OID_COMMON_NAME)[0] + expect(commonNameField).toEqual(subjectName) + + // Assert that the certificate public key matches the private key's public key + expect(await validateCertificatePublicKey(csr.publicKey, subjectPublicKey)).toBe(true) + + const tbsCertificateBytes = getTbsCertificate(certificate) + const signature = certificate.signature + + const isValidSignature = await crypto.subtle.verify( + { + name: 'Ed25519', + }, + issuerPublicKey, + signature, + tbsCertificateBytes, + ) + expect(isValidSignature).toBe(true) + }) + + it('self issue certificate', async () => { + // Create a private key for testing + const [privateKey, publicKey] = await generateEd25519KeyPair2() + const selfIssuer = new CertificateManager(null, privateKey, publicKey) + const certificate = await selfIssuer.selfIssueCertificate('Test') + + // Define the subject name for the certificate + const subjectName = 'Test' + + // Assert that the certificate is not null + expect(certificate).not.toBeNull() + + // Assert that the certificate subject name matches the provided subject name + const commonNameField = certificate.subjectName.getField(OID_COMMON_NAME)[0] + expect(commonNameField).toEqual(subjectName) + + // Assert that the certificate public key matches the private key's public key + expect(await validateCertificatePublicKey(certificate.publicKey, publicKey)).toBe(true) + + const tbsCertificateBytes = getTbsCertificate(certificate) + const signature = certificate.signature + + const isValidSignature = await crypto.subtle.verify( + { + name: 'Ed25519', + }, + publicKey, + signature, + tbsCertificateBytes, + ) + expect(isValidSignature).toBe(true) + }) + + it('get subject common name', async () => { + // Create a private key for testing + const [privateKey, publicKey] = await generateEd25519KeyPair2() + const selfIssuer = new CertificateManager(null, privateKey, publicKey) + const certificate = await selfIssuer.selfIssueCertificate('Test') + + // Define the subject name for the certificate + const subjectName = 'Test' + + // Retrieve the common name from the certificate + const commonName = CertificateManager.getSubjectCommonName(certificate.subjectName) + + // Assert that the common name matches the provided subject name + expect(commonName).toEqual(subjectName) + }) + + it('Certificate to Pem and back', async () => { + // Create a private key for testing + const [privateKey, publicKey] = await generateEd25519KeyPair2() + const selfIssuer = new CertificateManager(null, privateKey, publicKey) + // Define the subject name for the certificate + const subjectName = 'Test' + const certificate = await selfIssuer.selfIssueCertificate(subjectName) + const pemCertificate = CertificateManager.certificateToPem(certificate) + + // Convert the PEM back to a certificate + const certificateFromPem = CertificateManager.pemToCertificate(pemCertificate) + + expect(certificate).toEqual(certificateFromPem) + }) +}) diff --git a/packages/auto-utils/__test__/crypto.test.ts b/packages/auto-utils/__test__/crypto.test.ts index 636aa132..31c83385 100644 --- a/packages/auto-utils/__test__/crypto.test.ts +++ b/packages/auto-utils/__test__/crypto.test.ts @@ -1,4 +1,4 @@ -import { blake2b_256, stringToUint8Array } from '../src/crypto' +import { blake2b_256, concatenateUint8Arrays, stringToUint8Array } from '../src/crypto' describe('Verify crypto functions', () => { test('Check blake2b_256 return the hash of the data', async () => { @@ -8,9 +8,31 @@ describe('Verify crypto functions', () => { expect(hash).toEqual('0xb5da441cfe72ae042ef4d2b17742907f675de4da57462d4c3609c2e2ed755970') }) - test('Check stringToUint8Array return the byte array of the string', async () => { - const message = 'Hello, world!' - const byteArray = stringToUint8Array(message) - expect(byteArray).toBeInstanceOf(Uint8Array) + test('should encode strings to Uint8Arrays and concatenate them correctly', () => { + // Define test strings + const string1 = 'Hello' + const string2 = 'World' + + // Encode strings to Uint8Arrays + const encodedString1 = stringToUint8Array(string1) + const encodedString2 = stringToUint8Array(string2) + + // Manually create expected encoded arrays if known (for illustration) + const expectedEncoded1 = new Uint8Array([72, 101, 108, 108, 111]) // ASCII values for "Hello" + const expectedEncoded2 = new Uint8Array([87, 111, 114, 108, 100]) // ASCII values for "World" + + // Test individual encoding + expect(encodedString1).toEqual(expectedEncoded1) + expect(encodedString2).toEqual(expectedEncoded2) + + // Concatenate encoded arrays + const concatenatedArrays = concatenateUint8Arrays(encodedString1, encodedString2) + + // Manually create the expected concatenated result + const expectedConcatenation = new Uint8Array([72, 101, 108, 108, 111, 87, 111, 114, 108, 100]) // Combined ASCII + + // Test concatenation result + expect(concatenatedArrays).toEqual(expectedConcatenation) + expect(concatenatedArrays.length).toBe(encodedString1.length + encodedString2.length) }) }) diff --git a/packages/auto-utils/src/crypto.ts b/packages/auto-utils/src/crypto.ts index 1dce5c74..ae513c9f 100644 --- a/packages/auto-utils/src/crypto.ts +++ b/packages/auto-utils/src/crypto.ts @@ -29,3 +29,13 @@ export function stringToUint8Array(text: string): Uint8Array { const encoder = new TextEncoder() // Create a new TextEncoder instance return encoder.encode(text) // Encode the string to a Uint8Array using UTF-8 encoding } + +/** + * Concatenates two Uint8Array instances into a single Uint8Array. + */ +export function concatenateUint8Arrays(array1: Uint8Array, array2: Uint8Array): Uint8Array { + const combined = new Uint8Array(array1.length + array2.length) + combined.set(array1) + combined.set(array2, array1.length) + return combined +} diff --git a/packages/auto-utils/src/save.ts b/packages/auto-utils/src/save.ts index 5fa575a6..27a2718c 100644 --- a/packages/auto-utils/src/save.ts +++ b/packages/auto-utils/src/save.ts @@ -16,7 +16,7 @@ export const saveOnFileSystem = async (key: string, value: any) => { // save on file system const fs = await import('fs/promises') // Check if value is already a string to avoid unnecessary JSON string conversion - const data = typeof value === 'string' ? value : JSON.stringify(value); + const data = typeof value === 'string' ? value : JSON.stringify(value) await fs.writeFile(key, JSON.stringify(data)) } else throw new Error('This function can only be used in node') -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index d0d265f0..72b84312 100644 --- a/yarn.lock +++ b/yarn.lock @@ -36,6 +36,8 @@ __metadata: "@autonomys/auto-utils": "workspace:*" "@peculiar/asn1-schema": "npm:^2.3.8" "@peculiar/asn1-x509": "npm:^2.3.8" + "@peculiar/webcrypto": "npm:^1.5.0" + "@peculiar/x509": "npm:^1.11.0" "@types/jest": "npm:^29.5.12" "@types/node": "npm:^20.12.12" asn1js: "npm:^3.0.5" @@ -925,6 +927,97 @@ __metadata: languageName: node linkType: hard +"@peculiar/asn1-cms@npm:^2.3.8": + version: 2.3.8 + resolution: "@peculiar/asn1-cms@npm:2.3.8" + dependencies: + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/asn1-x509": "npm:^2.3.8" + "@peculiar/asn1-x509-attr": "npm:^2.3.8" + asn1js: "npm:^3.0.5" + tslib: "npm:^2.6.2" + checksum: 10c0/e330c8f23df45f8bacd05a314ea62b54a375e1c3bf05875bf69a4c971ad8e4f1f389e0c0c261a770d3841dad71c8a15141ec488d8ddce74ebcfb8e63f479f02f + languageName: node + linkType: hard + +"@peculiar/asn1-csr@npm:^2.3.8": + version: 2.3.8 + resolution: "@peculiar/asn1-csr@npm:2.3.8" + dependencies: + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/asn1-x509": "npm:^2.3.8" + asn1js: "npm:^3.0.5" + tslib: "npm:^2.6.2" + checksum: 10c0/1ba2414ba0679277f691e857de84b8543310af5a8e6385e2f27d672fc9179d143f9ed98cd752b775fd3d9aa4d54c2d120b157136aea0d00b1d7343cdabe74310 + languageName: node + linkType: hard + +"@peculiar/asn1-ecc@npm:^2.3.8": + version: 2.3.8 + resolution: "@peculiar/asn1-ecc@npm:2.3.8" + dependencies: + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/asn1-x509": "npm:^2.3.8" + asn1js: "npm:^3.0.5" + tslib: "npm:^2.6.2" + checksum: 10c0/88a1e34e3afc9f60ec89ae6d716e7e9fe92ae841e2758fc07b997c7325e0770cf605170031113c055086b93ed3eb8d12c8f64425bad576aafe74474410bb0ae9 + languageName: node + linkType: hard + +"@peculiar/asn1-pfx@npm:^2.3.8": + version: 2.3.8 + resolution: "@peculiar/asn1-pfx@npm:2.3.8" + dependencies: + "@peculiar/asn1-cms": "npm:^2.3.8" + "@peculiar/asn1-pkcs8": "npm:^2.3.8" + "@peculiar/asn1-rsa": "npm:^2.3.8" + "@peculiar/asn1-schema": "npm:^2.3.8" + asn1js: "npm:^3.0.5" + tslib: "npm:^2.6.2" + checksum: 10c0/8591281d081e3f22aa5575908188ff0560ea218f9e30af7ed9c4d24bf34d682f3dc8091b1f78bb44cceb4b0ad3198e83bc938a0e0b56be4e274bcd7c13eaa334 + languageName: node + linkType: hard + +"@peculiar/asn1-pkcs8@npm:^2.3.8": + version: 2.3.8 + resolution: "@peculiar/asn1-pkcs8@npm:2.3.8" + dependencies: + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/asn1-x509": "npm:^2.3.8" + asn1js: "npm:^3.0.5" + tslib: "npm:^2.6.2" + checksum: 10c0/33db038165f3a96a6bcbb20a2774b816a772652c4b6d67a814ecf68d3806743b75c4b2f758fecc2f5d134d18bee2864e0f42afee962e3052e4742e50e238a237 + languageName: node + linkType: hard + +"@peculiar/asn1-pkcs9@npm:^2.3.8": + version: 2.3.8 + resolution: "@peculiar/asn1-pkcs9@npm:2.3.8" + dependencies: + "@peculiar/asn1-cms": "npm:^2.3.8" + "@peculiar/asn1-pfx": "npm:^2.3.8" + "@peculiar/asn1-pkcs8": "npm:^2.3.8" + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/asn1-x509": "npm:^2.3.8" + "@peculiar/asn1-x509-attr": "npm:^2.3.8" + asn1js: "npm:^3.0.5" + tslib: "npm:^2.6.2" + checksum: 10c0/6a500939366169540223570b4ff48eca4b718e40616c3cc9086bffd66ac2f6a37041a9577f029040797ad42520c3dd5e29d7e2fd35d440d5171a4f5c48a86a8d + languageName: node + linkType: hard + +"@peculiar/asn1-rsa@npm:^2.3.8": + version: 2.3.8 + resolution: "@peculiar/asn1-rsa@npm:2.3.8" + dependencies: + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/asn1-x509": "npm:^2.3.8" + asn1js: "npm:^3.0.5" + tslib: "npm:^2.6.2" + checksum: 10c0/39b1a7597a210acd07c4d78bb2d55b9aedf05e3ab28fccde86ca6978322dcba35a483f2d84c155e18953ad15b728184e379010d11b01245ac2a2cbf1457a0dba + languageName: node + linkType: hard + "@peculiar/asn1-schema@npm:^2.3.8": version: 2.3.8 resolution: "@peculiar/asn1-schema@npm:2.3.8" @@ -936,6 +1029,18 @@ __metadata: languageName: node linkType: hard +"@peculiar/asn1-x509-attr@npm:^2.3.8": + version: 2.3.8 + resolution: "@peculiar/asn1-x509-attr@npm:2.3.8" + dependencies: + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/asn1-x509": "npm:^2.3.8" + asn1js: "npm:^3.0.5" + tslib: "npm:^2.6.2" + checksum: 10c0/0a7c92024c326267ed16a3eb3d3956061546838acf6d8ca54bdc5c105b4139ee4cf2bffe01c3685012d1cfcf5a48c06feb7a664bd88cbeda2d61dc990dcf90d0 + languageName: node + linkType: hard + "@peculiar/asn1-x509@npm:^2.3.8": version: 2.3.8 resolution: "@peculiar/asn1-x509@npm:2.3.8" @@ -949,6 +1054,47 @@ __metadata: languageName: node linkType: hard +"@peculiar/json-schema@npm:^1.1.12": + version: 1.1.12 + resolution: "@peculiar/json-schema@npm:1.1.12" + dependencies: + tslib: "npm:^2.0.0" + checksum: 10c0/202132c66dcc6b6aca5d0af971c015be2e163da2f7f992910783c5d39c8a7db59b6ec4f4ce419459a1f954b7e1d17b6b253f0e60072c1b3d254079f4eaebc311 + languageName: node + linkType: hard + +"@peculiar/webcrypto@npm:^1.5.0": + version: 1.5.0 + resolution: "@peculiar/webcrypto@npm:1.5.0" + dependencies: + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/json-schema": "npm:^1.1.12" + pvtsutils: "npm:^1.3.5" + tslib: "npm:^2.6.2" + webcrypto-core: "npm:^1.8.0" + checksum: 10c0/4f6f24b2c52c2155b9c569b6eb1d57954cb5f7bd2764a50cdaed7aea17a6dcf304b75b87b57ba318756ffec8179a07d9a76534aaf77855912b838543e5ff8983 + languageName: node + linkType: hard + +"@peculiar/x509@npm:^1.11.0": + version: 1.11.0 + resolution: "@peculiar/x509@npm:1.11.0" + dependencies: + "@peculiar/asn1-cms": "npm:^2.3.8" + "@peculiar/asn1-csr": "npm:^2.3.8" + "@peculiar/asn1-ecc": "npm:^2.3.8" + "@peculiar/asn1-pkcs9": "npm:^2.3.8" + "@peculiar/asn1-rsa": "npm:^2.3.8" + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/asn1-x509": "npm:^2.3.8" + pvtsutils: "npm:^1.3.5" + reflect-metadata: "npm:^0.2.2" + tslib: "npm:^2.6.2" + tsyringe: "npm:^4.8.0" + checksum: 10c0/528b37ccc291b7d78d6ba912946fbb045cf65da325d69c8910ef5ef8e32f0eca26f52db2c8e0d36092774b3ee2ca7cf4cf677f0b0c56c9e029737388c08ca527 + languageName: node + linkType: hard + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -1867,7 +2013,7 @@ __metadata: languageName: node linkType: hard -"asn1js@npm:^3.0.5": +"asn1js@npm:^3.0.1, asn1js@npm:^3.0.5": version: 3.0.5 resolution: "asn1js@npm:3.0.5" dependencies: @@ -4390,6 +4536,13 @@ __metadata: languageName: node linkType: hard +"reflect-metadata@npm:^0.2.2": + version: 0.2.2 + resolution: "reflect-metadata@npm:0.2.2" + checksum: 10c0/1cd93a15ea291e420204955544637c264c216e7aac527470e393d54b4bb075f10a17e60d8168ec96600c7e0b9fcc0cb0bb6e91c3fbf5b0d8c9056f04e6ac1ec2 + languageName: node + linkType: hard + "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -4892,6 +5045,20 @@ __metadata: languageName: node linkType: hard +"tslib@npm:^1.9.3": + version: 1.14.1 + resolution: "tslib@npm:1.14.1" + checksum: 10c0/69ae09c49eea644bc5ebe1bca4fa4cc2c82b7b3e02f43b84bd891504edf66dbc6b2ec0eef31a957042de2269139e4acff911e6d186a258fb14069cd7f6febce2 + languageName: node + linkType: hard + +"tslib@npm:^2.0.0, tslib@npm:^2.4.0, tslib@npm:^2.6.1": + version: 2.6.3 + resolution: "tslib@npm:2.6.3" + checksum: 10c0/2598aef53d9dbe711af75522464b2104724d6467b26a60f2bdac8297d2b5f1f6b86a71f61717384aa8fd897240467aaa7bcc36a0700a0faf751293d1331db39a + languageName: node + linkType: hard + "tslib@npm:^2.1.0, tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" @@ -4899,10 +5066,12 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.4.0, tslib@npm:^2.6.1": - version: 2.6.3 - resolution: "tslib@npm:2.6.3" - checksum: 10c0/2598aef53d9dbe711af75522464b2104724d6467b26a60f2bdac8297d2b5f1f6b86a71f61717384aa8fd897240467aaa7bcc36a0700a0faf751293d1331db39a +"tsyringe@npm:^4.8.0": + version: 4.8.0 + resolution: "tsyringe@npm:4.8.0" + dependencies: + tslib: "npm:^1.9.3" + checksum: 10c0/e13810e8ff39c4093acd0649bc5db3c164825827631e1522cd9d5ca8694a018447fa1c24f059ea54e93b1020767b1131b9dc9ce598dabfc9aa41c11544bbfe19 languageName: node linkType: hard @@ -5038,6 +5207,19 @@ __metadata: languageName: node linkType: hard +"webcrypto-core@npm:^1.8.0": + version: 1.8.0 + resolution: "webcrypto-core@npm:1.8.0" + dependencies: + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/json-schema": "npm:^1.1.12" + asn1js: "npm:^3.0.1" + pvtsutils: "npm:^1.3.5" + tslib: "npm:^2.6.2" + checksum: 10c0/d4158af402500eb26d0de6e088baa0fbef41c43a3e3b5f53b8326c8c517e55037b3d8a17672cf48bdccfd13526599857544ea8485e2172bb14c9ee4561d706a5 + languageName: node + linkType: hard + "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2"