From 5cf870786f46f5966bc45f3bdb6147a7fe758ac3 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Wed, 1 Nov 2023 17:00:46 -0700 Subject: [PATCH] simplifying @dfinity/identity with agent exports --- packages/agent/src/actor.test.ts | 2 +- packages/agent/src/agent/http/http.test.ts | 12 +- packages/agent/src/agent/http/index.ts | 2 +- packages/agent/src/certificate.test.ts | 4 +- packages/agent/src/der.test.ts | 3 +- packages/agent/src/der.ts | 10 +- packages/agent/src/index.ts | 6 +- .../agent/src/{publicKey.ts => public_key.ts} | 0 packages/agent/src/utils/random.test.ts | 2 +- packages/identity/src/buffer.ts | 15 -- packages/identity/src/identity/delegation.ts | 13 +- packages/identity/src/identity/der.test.ts | 163 ----------------- packages/identity/src/identity/der.ts | 166 ------------------ packages/identity/src/identity/ecdsa.ts | 2 +- .../identity/src/identity/ed25519.test.ts | 17 +- packages/identity/src/identity/ed25519.ts | 15 +- packages/identity/tsconfig.json | 3 +- 17 files changed, 44 insertions(+), 391 deletions(-) rename packages/agent/src/{publicKey.ts => public_key.ts} (100%) delete mode 100644 packages/identity/src/buffer.ts delete mode 100644 packages/identity/src/identity/der.test.ts delete mode 100644 packages/identity/src/identity/der.ts diff --git a/packages/agent/src/actor.test.ts b/packages/agent/src/actor.test.ts index 4d29d7b12..f98b4fbbe 100644 --- a/packages/agent/src/actor.test.ts +++ b/packages/agent/src/actor.test.ts @@ -318,7 +318,7 @@ describe('makeActor', () => { try { await actor.greet('test'); } catch (error) { - expect(error.message).toBe( + expect((error as Error).message).toBe( "This identity has expired due this application's security policy. Please refresh your authentication.", ); } diff --git a/packages/agent/src/agent/http/http.test.ts b/packages/agent/src/agent/http/http.test.ts index 1cb32ea7e..bfdec18ea 100644 --- a/packages/agent/src/agent/http/http.test.ts +++ b/packages/agent/src/agent/http/http.test.ts @@ -733,8 +733,8 @@ describe('default host', () => { it('should use the existing host if the agent is used on a known hostname', () => { const knownHosts = ['ic0.app', 'icp0.io', '127.0.0.1', '127.0.0.1']; for (const host of knownHosts) { - delete window.location; - window.location = { + delete (window as any).location; + (window as any).location = { hostname: host, protocol: 'https:', } as any; @@ -745,8 +745,8 @@ describe('default host', () => { it('should correctly handle subdomains on known hosts', () => { const knownHosts = ['ic0.app', 'icp0.io', '127.0.0.1', '127.0.0.1']; for (const host of knownHosts) { - delete window.location; - window.location = { + delete (window as any).location; + (window as any).location = { host: `foo.${host}`, hostname: `rrkah-fqaaa-aaaaa-aaaaq-cai.${host}`, protocol: 'https:', @@ -758,9 +758,9 @@ describe('default host', () => { it('should handle port numbers for 127.0.0.1', () => { const knownHosts = ['127.0.0.1', '127.0.0.1']; for (const host of knownHosts) { - delete window.location; + delete (window as any).location; // hostname is different from host when port is specified - window.location = { + (window as any).location = { host: `${host}:4943`, hostname: `${host}`, protocol: 'http:', diff --git a/packages/agent/src/agent/http/index.ts b/packages/agent/src/agent/http/index.ts index a799234d4..3683f4752 100644 --- a/packages/agent/src/agent/http/index.ts +++ b/packages/agent/src/agent/http/index.ts @@ -30,7 +30,7 @@ import { AgentHTTPResponseError } from './errors'; import { request } from '../../canisterStatus'; import { CertificateVerificationError, SubnetStatus } from '../../certificate'; import { ed25519 } from '@noble/curves/ed25519'; -import { Ed25519PublicKey } from '../../publicKey'; +import { Ed25519PublicKey } from '../../public_key'; export * from './transforms'; export { Nonce, makeNonce } from './types'; diff --git a/packages/agent/src/certificate.test.ts b/packages/agent/src/certificate.test.ts index 7d800fb0b..5f537e2eb 100644 --- a/packages/agent/src/certificate.test.ts +++ b/packages/agent/src/certificate.test.ts @@ -174,7 +174,7 @@ test('delegation works for canisters within the subnet range', async () => { const rangeStart = Principal.fromHex('00000000002000000101'); const rangeInterior = Principal.fromHex('000000000020000C0101'); const rangeEnd = Principal.fromHex('00000000002FFFFF0101'); - async function verifies(canisterId) { + async function verifies(canisterId: Principal) { jest.setSystemTime(new Date(Date.parse('2022-02-23T07:38:00.652Z'))); await expect( Cert.Certificate.create({ @@ -197,7 +197,7 @@ test('delegation check fails for canisters outside of the subnet range', async ( // 0x00000000002FFFFF0101 const beforeRange = Principal.fromHex('00000000000000020101'); const afterRange = Principal.fromHex('00000000003000020101'); - async function certificateFails(canisterId) { + async function certificateFails(canisterId: Principal) { await expect( Cert.Certificate.create({ certificate: fromHex(SAMPLE_CERT), diff --git a/packages/agent/src/der.test.ts b/packages/agent/src/der.test.ts index 765451983..eef980d62 100644 --- a/packages/agent/src/der.test.ts +++ b/packages/agent/src/der.test.ts @@ -1,4 +1,5 @@ -import { bufEquals, encodeLenBytes, encodeLen, decodeLenBytes, decodeLen } from './der'; +import { encodeLenBytes, encodeLen, decodeLenBytes, decodeLen } from './der'; +import { bufEquals } from './utils/buffer'; describe('bufEquals tests', () => { test('equal buffers', () => { diff --git a/packages/agent/src/der.ts b/packages/agent/src/der.ts index be1ea858d..7e902dbb9 100644 --- a/packages/agent/src/der.ts +++ b/packages/agent/src/der.ts @@ -1,12 +1,4 @@ -export const bufEquals = (b1: ArrayBuffer, b2: ArrayBuffer): boolean => { - if (b1.byteLength !== b2.byteLength) return false; - const u1 = new Uint8Array(b1); - const u2 = new Uint8Array(b2); - for (let i = 0; i < u1.length; i++) { - if (u1[i] !== u2[i]) return false; - } - return true; -}; +import { bufEquals } from './utils/buffer'; export const encodeLenBytes = (len: number): number => { if (len <= 0x7f) { diff --git a/packages/agent/src/index.ts b/packages/agent/src/index.ts index b66009a3f..5d195a5e1 100644 --- a/packages/agent/src/index.ts +++ b/packages/agent/src/index.ts @@ -2,12 +2,14 @@ import { ActorSubclass } from './actor'; export * from './actor'; export * from './agent'; -export * from './auth'; -export * from './certificate'; export * from './agent/http/transforms'; export * from './agent/http/types'; +export * from './auth'; export * from './canisters/asset'; +export * from './certificate'; +export * from './der'; export * from './fetch_candid'; +export * from './public_key'; export * from './request_id'; export * from './utils/bls'; export * from './utils/buffer'; diff --git a/packages/agent/src/publicKey.ts b/packages/agent/src/public_key.ts similarity index 100% rename from packages/agent/src/publicKey.ts rename to packages/agent/src/public_key.ts diff --git a/packages/agent/src/utils/random.test.ts b/packages/agent/src/utils/random.test.ts index a25434f65..3c01f74e8 100644 --- a/packages/agent/src/utils/random.test.ts +++ b/packages/agent/src/utils/random.test.ts @@ -8,7 +8,7 @@ beforeEach(() => { (global as any).crypto = undefined; }); -function isInteger(num) { +function isInteger(num: number) { if (typeof num !== 'number') return false; if (isNaN(num)) return false; if (num % 1 !== 0) { diff --git a/packages/identity/src/buffer.ts b/packages/identity/src/buffer.ts deleted file mode 100644 index 37366061b..000000000 --- a/packages/identity/src/buffer.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Return an array buffer from its hexadecimal representation. - * @param hexString The hexadecimal string. - */ -export function fromHexString(hexString: string): ArrayBuffer { - return new Uint8Array((hexString.match(/.{1,2}/g) ?? []).map(byte => parseInt(byte, 16))).buffer; -} - -/** - * Returns an hexadecimal representation of an array buffer. - * @param bytes The array buffer. - */ -export function toHexString(bytes: ArrayBuffer): string { - return new Uint8Array(bytes).reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), ''); -} diff --git a/packages/identity/src/identity/delegation.ts b/packages/identity/src/identity/delegation.ts index 77ba4a4f9..aff46be71 100644 --- a/packages/identity/src/identity/delegation.ts +++ b/packages/identity/src/identity/delegation.ts @@ -1,14 +1,15 @@ import { DerEncodedPublicKey, + fromHex, HttpAgentRequest, PublicKey, requestIdOf, Signature, SignIdentity, + toHex, } from '@dfinity/agent'; import { Principal } from '@dfinity/principal'; import * as cbor from 'simple-cbor'; -import { fromHexString, toHexString } from '../buffer'; const domainSeparator = new TextEncoder().encode('\x1Aic-request-auth-delegation'); const requestDomainSeparator = new TextEncoder().encode('\x0Aic-request'); @@ -18,7 +19,7 @@ function _parseBlob(value: unknown): ArrayBuffer { throw new Error('Invalid public key.'); } - return fromHexString(value); + return fromHex(value); } /** @@ -51,7 +52,7 @@ export class Delegation { // with an OID). After de-hex, if it's not obvious what it is, it's an ArrayBuffer. return { expiration: this.expiration.toString(16), - pubkey: toHexString(this.pubkey), + pubkey: toHex(this.pubkey), ...(this.targets && { targets: this.targets.map(p => p.toHex()) }), }; } @@ -247,15 +248,15 @@ export class DelegationChain { return { delegation: { expiration: delegation.expiration.toString(16), - pubkey: toHexString(delegation.pubkey), + pubkey: toHex(delegation.pubkey), ...(targets && { targets: targets.map(t => t.toHex()), }), }, - signature: toHexString(signature), + signature: toHex(signature), }; }), - publicKey: toHexString(this.publicKey), + publicKey: toHex(this.publicKey), }; } } diff --git a/packages/identity/src/identity/der.test.ts b/packages/identity/src/identity/der.test.ts deleted file mode 100644 index 765451983..000000000 --- a/packages/identity/src/identity/der.test.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { bufEquals, encodeLenBytes, encodeLen, decodeLenBytes, decodeLen } from './der'; - -describe('bufEquals tests', () => { - test('equal buffers', () => { - const buf1 = Uint8Array.from([0, 0, 0, 1]).buffer; - const buf2 = Uint8Array.from([0, 0, 0, 1]).buffer; - expect(bufEquals(buf1, buf2)).toBe(true); - }); - test('rejects buffers with different lengths', () => { - const buf1 = Uint8Array.from([0, 0, 0, 0, 1]).buffer; - const buf2 = Uint8Array.from([0, 0, 0, 1]).buffer; - expect(bufEquals(buf1, buf2)).toBe(false); - }); - test('rejects buffers with different values', () => { - const buf1 = Uint8Array.from([0, 0, 0, 2]).buffer; - const buf2 = Uint8Array.from([0, 0, 0, 1]).buffer; - expect(bufEquals(buf1, buf2)).toBe(false); - }); -}); - -describe('encodeLenBytes', () => { - test('Length of up to 127', () => { - const byteLength = Uint8Array.from(new Array(127)).byteLength; - expect(encodeLenBytes(byteLength)).toEqual(1); - }); - test('Length of up to 255', () => { - const min = Uint8Array.from(new Array(128)).byteLength; - expect(encodeLenBytes(min)).toEqual(2); - const max = Uint8Array.from(new Array(255)).byteLength; - expect(encodeLenBytes(max)).toEqual(2); - }); - test('Length of up to 65536', () => { - const min = Uint8Array.from(new Array(256)).byteLength; - expect(encodeLenBytes(min)).toEqual(3); - const max = Uint8Array.from(new Array(65535)).byteLength; - expect(encodeLenBytes(max)).toEqual(3); - }); - test('Length of up to 16777215', () => { - // Using numbers directly for performance - const min = 65536; - expect(encodeLenBytes(min)).toEqual(4); - const max = 16777215; - expect(encodeLenBytes(max)).toEqual(4); - }); - test('Over maximum length', () => { - const shouldFail = () => encodeLenBytes(16777216); - expect(shouldFail).toThrowError('Length too long (> 4 bytes)'); - }); -}); - -describe('encodeLen', () => { - const buf = Uint8Array.from(new Array(256)); - test('Length of up to 127', () => { - const min = encodeLen(buf, 0, 1); - const max = encodeLen(buf, 0, 127); - expect(min).toEqual(1); - expect(max).toEqual(1); - }); - test('Length of up to 255', () => { - const min = encodeLen(buf, 0, 128); - const max = encodeLen(buf, 0, 255); - expect(min).toEqual(2); - expect(max).toEqual(2); - }); - test('Length of up to 65535', () => { - const min = encodeLen(buf, 0, 256); - const max = encodeLen(buf, 0, 65535); - expect(min).toEqual(3); - expect(max).toEqual(3); - }); - test('Length of up to 16777215', () => { - const min = encodeLen(buf, 0, 65536); - const max = encodeLen(buf, 0, 16777215); - expect(min).toEqual(4); - expect(max).toEqual(4); - }); - test('Length of up to 16777215', () => { - const min = encodeLen(buf, 0, 65536); - const max = encodeLen(buf, 0, 16777215); - expect(min).toEqual(4); - expect(max).toEqual(4); - }); - test('Over maximum length', () => { - const shouldFail = () => encodeLen(buf, 0, 16777216); - expect(shouldFail).toThrowError('Length too long (> 4 bytes)'); - }); -}); - -describe('DecodeLenBytes', () => { - test('encoded length of zero', () => { - // length of buf doesn't matter - const buf = Uint8Array.from(new Array(2)); - // 129 signifies a DER length of 2 - buf[0] = 128; - const shouldFail = () => decodeLenBytes(buf, 0); - expect(shouldFail).toThrowError('Invalid length 0'); - }); - test('encoded length of 1', () => { - const buf = Uint8Array.of(100); - expect(decodeLenBytes(buf, 0)).toBe(1); - }); - test('encoded length of 2', () => { - const buf = Uint8Array.from(new Array(2)); - // 129 signifies a DER length of 2 - buf[0] = 129; - expect(decodeLenBytes(buf, 0)).toBe(2); - }); - test('encoded length of 3', () => { - const buf = Uint8Array.from(new Array(2)); - // 130 signifies a DER length of 3 - buf[0] = 130; - expect(decodeLenBytes(buf, 0)).toBe(3); - }); - test('encoded length of 4', () => { - const buf = Uint8Array.from(new Array(2)); - // 131 signifies a DER length of 4 - buf[0] = 131; - expect(decodeLenBytes(buf, 0)).toBe(4); - }); - test('encoded length of 4', () => { - const buf = Uint8Array.from(new Array(2)); - buf[0] = 132; - const shouldFail = () => decodeLenBytes(buf, 0); - expect(shouldFail).toThrowError('Length too long'); - }); -}); - -describe('decodeLen', () => { - test('encoded length of 1', () => { - const buf = Uint8Array.of(1); - expect(decodeLen(buf, 0)).toBe(1); - }); - test('encoded length of 2', () => { - const buf = Uint8Array.from(new Array(10)); - buf[0] = 129; - // returns value stored at index 1 - buf[1] = 5; - - expect(decodeLen(buf, 0)).toBe(5); - }); - test('encoded length of 3', () => { - const buf = Uint8Array.from(new Array(10)); - buf[0] = 130; - buf[1] = 1; - buf[2] = 1; - expect(decodeLen(buf, 0)).toBe(257); - }); - test('encoded length of 4', () => { - const buf = Uint8Array.from(new Array(10)); - buf[0] = 131; - buf[1] = 1; - buf[2] = 1; - buf[3] = 1; - // returns value encoded by summing buf[offset + 3] and left-shifts of the values at index 1, and 2 - expect(decodeLen(buf, 0)).toBe(65793); - }); - test('length of over 4 bytes', () => { - const buf = Uint8Array.from(new Array(10)); - buf[0] = 133; - const shouldFail = () => decodeLen(buf, 0); - expect(shouldFail).toThrowError('Length too long'); - }); -}); diff --git a/packages/identity/src/identity/der.ts b/packages/identity/src/identity/der.ts deleted file mode 100644 index be1ea858d..000000000 --- a/packages/identity/src/identity/der.ts +++ /dev/null @@ -1,166 +0,0 @@ -export const bufEquals = (b1: ArrayBuffer, b2: ArrayBuffer): boolean => { - if (b1.byteLength !== b2.byteLength) return false; - const u1 = new Uint8Array(b1); - const u2 = new Uint8Array(b2); - for (let i = 0; i < u1.length; i++) { - if (u1[i] !== u2[i]) return false; - } - return true; -}; - -export const encodeLenBytes = (len: number): number => { - if (len <= 0x7f) { - return 1; - } else if (len <= 0xff) { - return 2; - } else if (len <= 0xffff) { - return 3; - } else if (len <= 0xffffff) { - return 4; - } else { - throw new Error('Length too long (> 4 bytes)'); - } -}; - -export const encodeLen = (buf: Uint8Array, offset: number, len: number): number => { - if (len <= 0x7f) { - buf[offset] = len; - return 1; - } else if (len <= 0xff) { - buf[offset] = 0x81; - buf[offset + 1] = len; - return 2; - } else if (len <= 0xffff) { - buf[offset] = 0x82; - buf[offset + 1] = len >> 8; - buf[offset + 2] = len; - return 3; - } else if (len <= 0xffffff) { - buf[offset] = 0x83; - buf[offset + 1] = len >> 16; - buf[offset + 2] = len >> 8; - buf[offset + 3] = len; - return 4; - } else { - throw new Error('Length too long (> 4 bytes)'); - } -}; - -export const decodeLenBytes = (buf: Uint8Array, offset: number): number => { - if (buf[offset] < 0x80) return 1; - if (buf[offset] === 0x80) throw new Error('Invalid length 0'); - if (buf[offset] === 0x81) return 2; - if (buf[offset] === 0x82) return 3; - if (buf[offset] === 0x83) return 4; - throw new Error('Length too long (> 4 bytes)'); -}; - -export const decodeLen = (buf: Uint8Array, offset: number): number => { - const lenBytes = decodeLenBytes(buf, offset); - if (lenBytes === 1) return buf[offset]; - else if (lenBytes === 2) return buf[offset + 1]; - else if (lenBytes === 3) return (buf[offset + 1] << 8) + buf[offset + 2]; - else if (lenBytes === 4) - return (buf[offset + 1] << 16) + (buf[offset + 2] << 8) + buf[offset + 3]; - throw new Error('Length too long (> 4 bytes)'); -}; - -/** - * A DER encoded `SEQUENCE(OID)` for DER-encoded-COSE - */ -export const DER_COSE_OID = Uint8Array.from([ - ...[0x30, 0x0c], // SEQUENCE - ...[0x06, 0x0a], // OID with 10 bytes - ...[0x2b, 0x06, 0x01, 0x04, 0x01, 0x83, 0xb8, 0x43, 0x01, 0x01], // DER encoded COSE -]); - -/** - * A DER encoded `SEQUENCE(OID)` for the Ed25519 algorithm - */ -export const ED25519_OID = Uint8Array.from([ - ...[0x30, 0x05], // SEQUENCE - ...[0x06, 0x03], // OID with 3 bytes - ...[0x2b, 0x65, 0x70], // id-Ed25519 OID -]); - -/** - * A DER encoded `SEQUENCE(OID)` for secp256k1 with the ECDSA algorithm - */ -export const SECP256K1_OID = Uint8Array.from([ - ...[0x30, 0x10], // SEQUENCE - ...[0x06, 0x07], // OID with 7 bytes - ...[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01], // OID ECDSA - ...[0x06, 0x05], // OID with 5 bytes - ...[0x2b, 0x81, 0x04, 0x00, 0x0a], // OID secp256k1 -]); - -/** - * Wraps the given `payload` in a DER encoding tagged with the given encoded `oid` like so: - * `SEQUENCE(oid, BITSTRING(payload))` - * - * @param payload The payload to encode as the bit string - * @param oid The DER encoded (and SEQUENCE wrapped!) OID to tag the payload with - */ -export function wrapDER(payload: ArrayBuffer, oid: Uint8Array): Uint8Array { - // The Bit String header needs to include the unused bit count byte in its length - const bitStringHeaderLength = 2 + encodeLenBytes(payload.byteLength + 1); - const len = oid.byteLength + bitStringHeaderLength + payload.byteLength; - let offset = 0; - const buf = new Uint8Array(1 + encodeLenBytes(len) + len); - // Sequence - buf[offset++] = 0x30; - // Sequence Length - offset += encodeLen(buf, offset, len); - - // OID - buf.set(oid, offset); - offset += oid.byteLength; - - // Bit String Header - buf[offset++] = 0x03; - offset += encodeLen(buf, offset, payload.byteLength + 1); - // 0 padding - buf[offset++] = 0x00; - buf.set(new Uint8Array(payload), offset); - - return buf; -} - -/** - * Extracts a payload from the given `derEncoded` data, and checks that it was tagged with the given `oid`. - * - * `derEncoded = SEQUENCE(oid, BITSTRING(payload))` - * - * @param derEncoded The DER encoded and tagged data - * @param oid The DER encoded (and SEQUENCE wrapped!) expected OID - * @returns The unwrapped payload - */ -export const unwrapDER = (derEncoded: ArrayBuffer, oid: Uint8Array): Uint8Array => { - let offset = 0; - const expect = (n: number, msg: string) => { - if (buf[offset++] !== n) { - throw new Error('Expected: ' + msg); - } - }; - - const buf = new Uint8Array(derEncoded); - expect(0x30, 'sequence'); - offset += decodeLenBytes(buf, offset); - - if (!bufEquals(buf.slice(offset, offset + oid.byteLength), oid)) { - throw new Error('Not the expected OID.'); - } - offset += oid.byteLength; - - expect(0x03, 'bit string'); - const payloadLen = decodeLen(buf, offset) - 1; // Subtracting 1 to account for the 0 padding - offset += decodeLenBytes(buf, offset); - expect(0x00, '0 padding'); - const result = buf.slice(offset); - if (payloadLen !== result.length) { - throw new Error( - `DER payload mismatch: Expected length ${payloadLen} actual length ${result.length}`, - ); - } - return result; -}; diff --git a/packages/identity/src/identity/ecdsa.ts b/packages/identity/src/identity/ecdsa.ts index 7f2a88dd2..dafa1bc42 100644 --- a/packages/identity/src/identity/ecdsa.ts +++ b/packages/identity/src/identity/ecdsa.ts @@ -1,4 +1,4 @@ -import { DerEncodedPublicKey, PublicKey, Signature, SignIdentity } from '@dfinity/agent'; +import { DerEncodedPublicKey, Signature, SignIdentity } from '@dfinity/agent'; /** * Options used in a {@link ECDSAKeyIdentity} diff --git a/packages/identity/src/identity/ed25519.test.ts b/packages/identity/src/identity/ed25519.test.ts index ff0eef802..0b991927a 100644 --- a/packages/identity/src/identity/ed25519.test.ts +++ b/packages/identity/src/identity/ed25519.test.ts @@ -1,5 +1,4 @@ -import { DerEncodedPublicKey } from '@dfinity/agent'; -import { fromHexString } from '../buffer'; +import { DerEncodedPublicKey, fromHex } from '@dfinity/agent'; import { Ed25519KeyIdentity, Ed25519PublicKey } from './ed25519'; const testVectors: Array<[string, string]> = [ @@ -20,16 +19,16 @@ const testVectors: Array<[string, string]> = [ describe('Ed25519PublicKey Tests', () => { test('DER encoding of ED25519 keys', async () => { testVectors.forEach(([rawPublicKeyHex, derEncodedPublicKeyHex]) => { - const publicKey = Ed25519PublicKey.fromRaw(fromHexString(rawPublicKeyHex)); - const expectedDerPublicKey = fromHexString(derEncodedPublicKeyHex); + const publicKey = Ed25519PublicKey.fromRaw(fromHex(rawPublicKeyHex)); + const expectedDerPublicKey = fromHex(derEncodedPublicKeyHex); expect(publicKey.toDer()).toEqual(expectedDerPublicKey); }); }); test('DER decoding of ED25519 keys', async () => { testVectors.forEach(([rawPublicKeyHex, derEncodedPublicKeyHex]) => { - const derPublicKey = fromHexString(derEncodedPublicKeyHex) as DerEncodedPublicKey; - const expectedPublicKey = fromHexString(rawPublicKeyHex); + const derPublicKey = fromHex(derEncodedPublicKeyHex) as DerEncodedPublicKey; + const expectedPublicKey = fromHex(rawPublicKeyHex); expect(new Uint8Array(Ed25519PublicKey.fromDer(derPublicKey).toRaw())).toEqual( new Uint8Array(expectedPublicKey), ); @@ -40,7 +39,7 @@ describe('Ed25519PublicKey Tests', () => { // Too short. expect(() => { Ed25519PublicKey.fromDer( - fromHexString( + fromHex( '302A300506032B6570032100B3997656BA51FF6DA37B61D8D549EC80717266ECF48FB5DA52B65441263484', ) as DerEncodedPublicKey, ); @@ -48,7 +47,7 @@ describe('Ed25519PublicKey Tests', () => { // Too long. expect(() => { Ed25519PublicKey.fromDer( - fromHexString( + fromHex( '302A300506032B6570032100B3997656BA51FF6DA37B61D8D549EC8071726' + '6ECF48FB5DA52B654412634844C00', ) as DerEncodedPublicKey, @@ -58,7 +57,7 @@ describe('Ed25519PublicKey Tests', () => { // Invalid DER-encoding. expect(() => { Ed25519PublicKey.fromDer( - fromHexString( + fromHex( '002A300506032B6570032100B3997656BA51FF6DA37B61D8D549EC80717266ECF48FB5DA52B654412634844C', ) as DerEncodedPublicKey, ); diff --git a/packages/identity/src/identity/ed25519.ts b/packages/identity/src/identity/ed25519.ts index fc2f01747..3c36c563a 100644 --- a/packages/identity/src/identity/ed25519.ts +++ b/packages/identity/src/identity/ed25519.ts @@ -5,10 +5,13 @@ import { Signature, SignIdentity, uint8ToBuf, + ED25519_OID, + unwrapDER, + wrapDER, + fromHex, + toHex, } from '@dfinity/agent'; import { ed25519 } from '@noble/curves/ed25519'; -import { fromHexString, toHexString } from '../buffer'; -import { ED25519_OID, unwrapDER, wrapDER } from './der'; export class Ed25519PublicKey implements PublicKey { public static from(key: PublicKey): Ed25519PublicKey { @@ -84,8 +87,8 @@ export class Ed25519KeyIdentity extends SignIdentity { public static fromParsedJson(obj: JsonnableEd25519KeyIdentity): Ed25519KeyIdentity { const [publicKeyDer, privateKeyRaw] = obj; return new Ed25519KeyIdentity( - Ed25519PublicKey.fromDer(fromHexString(publicKeyDer) as DerEncodedPublicKey), - fromHexString(privateKeyRaw), + Ed25519PublicKey.fromDer(fromHex(publicKeyDer) as DerEncodedPublicKey), + fromHex(privateKeyRaw), ); } @@ -124,7 +127,7 @@ export class Ed25519KeyIdentity extends SignIdentity { * Serialize this key to JSON. */ public toJSON(): JsonnableEd25519KeyIdentity { - return [toHexString(this.#publicKey.toDer()), toHexString(this.#privateKey)]; + return [toHex(this.#publicKey.toDer()), toHex(this.#privateKey)]; } /** @@ -176,7 +179,7 @@ export class Ed25519KeyIdentity extends SignIdentity { ) { const [signature, message, publicKey] = [sig, msg, pk].map(x => { if (typeof x === 'string') { - x = fromHexString(x); + x = fromHex(x); } if (x instanceof Uint8Array) { x = x.buffer; diff --git a/packages/identity/tsconfig.json b/packages/identity/tsconfig.json index 2dffec2ed..9613a1758 100644 --- a/packages/identity/tsconfig.json +++ b/packages/identity/tsconfig.json @@ -25,6 +25,5 @@ "index.d.ts", "../identity-secp256k1/src/secp256k1.test.ts", "../identity-secp256k1/hdkey.ts" - ], - "references": [{ "path": "../agent" }] + ] }