|
1 | 1 | import * as assert from 'assert'; |
2 | | - |
| 2 | +import { createHash } from 'crypto'; |
3 | 3 | import * as secp256k1 from '../src'; |
4 | 4 |
|
5 | 5 | describe('secp256k1', function () { |
@@ -42,4 +42,81 @@ describe('secp256k1', function () { |
42 | 42 | ); |
43 | 43 | }); |
44 | 44 | }); |
| 45 | + |
| 46 | + describe('ecc', function () { |
| 47 | + describe('recoverPublicKey', function () { |
| 48 | + const privKey = Buffer.from('1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', 'hex'); |
| 49 | + const message = Buffer.from('Hello, world!'); |
| 50 | + const messageHash = createHash('sha256').update(message).digest(); |
| 51 | + const signature = secp256k1.ecc.sign(messageHash, privKey); |
| 52 | + const publicKey = secp256k1.ecc.pointFromScalar(privKey, true); |
| 53 | + |
| 54 | + it('successfully recovers compressed public key', function () { |
| 55 | + // Test recovery with both possible recovery values (0 and 1) |
| 56 | + const recoveredKey0 = secp256k1.ecc.recoverPublicKey(messageHash, signature, 0, true); |
| 57 | + const recoveredKey1 = secp256k1.ecc.recoverPublicKey(messageHash, signature, 1, true); |
| 58 | + |
| 59 | + // One of the recovered keys should match our original compressed public key |
| 60 | + const pubKeyHex = Buffer.from(publicKey || []).toString('hex'); |
| 61 | + assert.ok( |
| 62 | + (recoveredKey0 && Buffer.from(recoveredKey0).toString('hex') === pubKeyHex) || |
| 63 | + (recoveredKey1 && Buffer.from(recoveredKey1).toString('hex') === pubKeyHex), |
| 64 | + 'Failed to recover the correct compressed public key' |
| 65 | + ); |
| 66 | + }); |
| 67 | + |
| 68 | + it('successfully recovers uncompressed public key', function () { |
| 69 | + // Test recovery with uncompressed format |
| 70 | + const recoveredKey0 = secp256k1.ecc.recoverPublicKey(messageHash, signature, 0, false); |
| 71 | + const recoveredKey1 = secp256k1.ecc.recoverPublicKey(messageHash, signature, 1, false); |
| 72 | + const uncompressedPubKey = secp256k1.ecc.pointFromScalar(privKey, false); |
| 73 | + |
| 74 | + // One of the recovered keys should match the uncompressed public key |
| 75 | + const pubKeyHex = Buffer.from(uncompressedPubKey || []).toString('hex'); |
| 76 | + assert.ok( |
| 77 | + (recoveredKey0 && Buffer.from(recoveredKey0).toString('hex') === pubKeyHex) || |
| 78 | + (recoveredKey1 && Buffer.from(recoveredKey1).toString('hex') === pubKeyHex), |
| 79 | + 'Failed to recover the correct uncompressed public key' |
| 80 | + ); |
| 81 | + }); |
| 82 | + |
| 83 | + it('returns null for invalid recovery param', function () { |
| 84 | + const result = secp256k1.ecc.recoverPublicKey(messageHash, signature, 2, true); |
| 85 | + assert.strictEqual(result, null); |
| 86 | + }); |
| 87 | + |
| 88 | + it('returns null for invalid signature', function () { |
| 89 | + const invalidSig = Buffer.alloc(64, 0); |
| 90 | + const result = secp256k1.ecc.recoverPublicKey(messageHash, invalidSig, 0, true); |
| 91 | + assert.strictEqual(result, null); |
| 92 | + }); |
| 93 | + |
| 94 | + it('returns null for invalid message hash', function () { |
| 95 | + // Create an invalid hash by using wrong length (should be 32 bytes) |
| 96 | + const invalidHash = Buffer.alloc(31, 1); // 31 bytes of 1s |
| 97 | + const result = secp256k1.ecc.recoverPublicKey(invalidHash, signature, 0, true); |
| 98 | + assert.strictEqual(result, null, 'Should return null for invalid message hash length'); |
| 99 | + |
| 100 | + // Also test with empty hash |
| 101 | + const emptyHash = Buffer.alloc(0); |
| 102 | + const resultEmpty = secp256k1.ecc.recoverPublicKey(emptyHash, signature, 0, true); |
| 103 | + assert.strictEqual(resultEmpty, null, 'Should return null for empty message hash'); |
| 104 | + }); |
| 105 | + |
| 106 | + it('handles compressed parameter correctly', function () { |
| 107 | + const compressedKey = secp256k1.ecc.recoverPublicKey(messageHash, signature, 0, true); |
| 108 | + const uncompressedKey = secp256k1.ecc.recoverPublicKey(messageHash, signature, 0, false); |
| 109 | + |
| 110 | + assert.ok(compressedKey, 'Should recover compressed key'); |
| 111 | + assert.ok(uncompressedKey, 'Should recover uncompressed key'); |
| 112 | + assert.notStrictEqual( |
| 113 | + Buffer.from(compressedKey).toString('hex'), |
| 114 | + Buffer.from(uncompressedKey).toString('hex'), |
| 115 | + 'Compressed and uncompressed keys should be different' |
| 116 | + ); |
| 117 | + assert.strictEqual(Buffer.from(compressedKey).length, 33, 'Compressed key should be 33 bytes'); |
| 118 | + assert.strictEqual(Buffer.from(uncompressedKey).length, 65, 'Uncompressed key should be 65 bytes'); |
| 119 | + }); |
| 120 | + }); |
| 121 | + }); |
45 | 122 | }); |
0 commit comments