Skip to content

Commit

Permalink
[secp256k1] Support inputed compressed public keys
Browse files Browse the repository at this point in the history
  • Loading branch information
gregnazario committed Nov 25, 2024
1 parent e0ddd43 commit 6207704
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 5 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@
"typescript": "^5.6.2"
},
"version": "1.33.0"
}
}
66 changes: 65 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions src/core/crypto/secp256k1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export class Secp256k1PublicKey extends PublicKey {
// Secp256k1 ecdsa public keys contain a prefix indicating compression and two 32-byte coordinates.
static readonly LENGTH: number = 65;

// If it's compressed, it is only 33 bytes
static readonly COMPRESSED_LENGTH: number = 33;

// Hex value of the public key
private readonly key: Hex;

Expand All @@ -37,10 +40,17 @@ export class Secp256k1PublicKey extends PublicKey {
super();

const hex = Hex.fromHexInput(hexInput);
if (hex.toUint8Array().length !== Secp256k1PublicKey.LENGTH) {
throw new Error(`PublicKey length should be ${Secp256k1PublicKey.LENGTH}`);
const { length } = hex.toUint8Array();
if (length === Secp256k1PublicKey.LENGTH) {
this.key = hex;
} else if (length === Secp256k1PublicKey.COMPRESSED_LENGTH) {
const point = secp256k1.ProjectivePoint.fromHex(hex.toUint8Array());
this.key = Hex.fromHexInput(point.toRawBytes(false));
} else {
throw new Error(
`PublicKey length should be ${Secp256k1PublicKey.LENGTH} or ${Secp256k1PublicKey.COMPRESSED_LENGTH}, received ${length}`,
);
}
this.key = hex;
}

// region PublicKey
Expand Down
21 changes: 21 additions & 0 deletions tests/unit/secp256k1.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,27 @@ describe("Secp256k1PublicKey", () => {
expect(publicKey2.toUint8Array()).toEqual(hexUint8Array);
});

it("should work with compressed public keys", () => {
const expectedPublicKey = new Secp256k1PublicKey(secp256k1TestObject.publicKey);
const uncompressedPublicKey = Hex.fromHexInput(secp256k1TestObject.publicKey);
expect(uncompressedPublicKey.toUint8Array().length).toEqual(65);

const point = secp256k1.ProjectivePoint.fromHex(uncompressedPublicKey.toUint8Array());
const compressedPublicKey = point.toRawBytes(true);
const compressedPublicKeyHex = Hex.fromHexInput(compressedPublicKey);
expect(compressedPublicKey.length).toEqual(33);

const publicKey1 = new Secp256k1PublicKey(compressedPublicKeyHex.toString());
expect(publicKey1).toBeInstanceOf(Secp256k1PublicKey);
expect(publicKey1).toEqual(expectedPublicKey);

const publicKey2 = new Secp256k1PublicKey(compressedPublicKeyHex.toUint8Array());
expect(publicKey2).toBeInstanceOf(Secp256k1PublicKey);
expect(publicKey2).toEqual(expectedPublicKey);

expect(publicKey1).toEqual(publicKey2);
});

it("should throw an error with invalid hex input length", () => {
const invalidHexInput = "0123456789abcdef"; // Invalid length
expect(() => new Secp256k1PublicKey(invalidHexInput)).toThrowError(
Expand Down

0 comments on commit 6207704

Please sign in to comment.