diff --git a/.changeset/ed25519-jwk-key-length.md b/.changeset/ed25519-jwk-key-length.md new file mode 100644 index 0000000..3452a4e --- /dev/null +++ b/.changeset/ed25519-jwk-key-length.md @@ -0,0 +1,9 @@ +--- +"@agentcommercekit/keys": patch +--- + +`publicKeyBytesToJwk` now rejects Ed25519 public keys that are not 32 bytes, +as it already does for secp256k1 and secp256r1. The Ed25519 branch encoded +whatever bytes it was given, so `createDidPkhDocument` built a DID document +with a malformed `publicKeyJwk` for any Solana address that is valid base58 +but not a 32-byte key (for example `abc`) instead of failing. diff --git a/packages/did/src/methods/did-pkh.test.ts b/packages/did/src/methods/did-pkh.test.ts index 8279943..ca34088 100644 --- a/packages/did/src/methods/did-pkh.test.ts +++ b/packages/did/src/methods/did-pkh.test.ts @@ -187,6 +187,15 @@ describe("createDidPkhDocument", () => { ) }) + it("throws for a Solana address that is not a 32-byte Ed25519 key", () => { + expect(() => + createDidPkhDocument({ + address: "abc", + chainId: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", + }), + ).toThrow("Invalid Ed25519 public key length") + }) + it("creates did:pkh document with custom controller", () => { const result = createDidPkhDocument({ address: "0x1234567890123456789012345678901234567890", diff --git a/packages/keys/src/encoding/jwk.test.ts b/packages/keys/src/encoding/jwk.test.ts index c0979c7..ed38d0d 100644 --- a/packages/keys/src/encoding/jwk.test.ts +++ b/packages/keys/src/encoding/jwk.test.ts @@ -39,6 +39,15 @@ describe("JWK encoding", () => { expect(isBase64url(jwk.x)).toBe(true) }) + test("throws for an Ed25519 public key that is not 32 bytes", () => { + expect(() => publicKeyBytesToJwk(new Uint8Array(2), "Ed25519")).toThrow( + "Invalid Ed25519 public key length", + ) + expect(() => publicKeyBytesToJwk(new Uint8Array(33), "Ed25519")).toThrow( + "Invalid Ed25519 public key length", + ) + }) + test("converts secp256k1 public key to JWK", () => { const jwk = publicKeyBytesToJwk(secp256k1Bytes, "secp256k1") if (!isPublicKeyJwkSecp256k1(jwk)) { diff --git a/packages/keys/src/encoding/jwk.ts b/packages/keys/src/encoding/jwk.ts index fdae2e9..832360a 100644 --- a/packages/keys/src/encoding/jwk.ts +++ b/packages/keys/src/encoding/jwk.ts @@ -229,6 +229,10 @@ export function publicKeyBytesToJwk( ): PublicKeyJwk { switch (curve) { case "Ed25519": + if (bytes.length !== 32) { + throw new Error(`Invalid ${curve} public key length`) + } + return { kty: "OKP", crv: "Ed25519",