UNPKG

@smartledger/elliptic-fix

Version:

Security fix for signature malleability vulnerability in Elliptic package v6.5.5 used by bsv@1.5.6

68 lines (55 loc) 2.55 kB
const elliptic = require('elliptic'); const BN = require('bn.js'); const ed = new elliptic.eddsa('ed25519'); // Test data const key = ed.keyFromSecret('0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'); const msg = Buffer.from('test message'); // Create a valid signature const validSig = key.sign(msg); // Create a malleable signature by modifying the internal representation const validSigBytes = Buffer.from(validSig.toHex(), 'hex'); const R = validSigBytes.slice(0, 32); // First 32 bytes are R // Create a malleable S value just slightly larger than the curve order const curveOrder = ed.curve.n; const malleableS = curveOrder.addn(1); // n + 1 const malleableSBytes = malleableS.toArrayLike(Buffer, 'le', 32); // Combine R and malleable S const malleableSig = Buffer.concat([R, malleableSBytes]); const malleableSigHex = malleableSig.toString('hex'); console.log('\nTesting signature malleability vulnerability:'); console.log('Curve order:', curveOrder.toString(16)); console.log('Malleable S value:', malleableS.toString(16)); console.log('Is S >= curve order?', malleableS.gte(curveOrder)); // Store original verify function const originalVerify = ed.verify; console.log('\nOriginal behavior (without fix):'); console.log('Valid signature verification:', originalVerify.call(ed, msg, validSig.toHex(), key.getPublic())); try { console.log('Malleable signature verification:', originalVerify.call(ed, msg, malleableSigHex, key.getPublic())); } catch (e) { console.log('Malleable signature failed:', e.message); } // Apply our fix to the verify function ed.verify = function patchedVerify(message, sig, pub) { try { const signature = this.makeSignature(sig); const S = signature.S(); // Check if S is >= curve order or negative if (S.gte(this.curve.n) || S.isNeg()) { console.log('Rejecting signature: S value is >= curve order or negative'); return false; } // If S is valid, proceed with original verification return originalVerify.call(this, message, sig, pub); } catch (e) { console.log('Invalid signature format:', e.message); return false; } }; console.log('\nBehavior with fix applied:'); console.log('Valid signature verification:', ed.verify(msg, validSig.toHex(), key.getPublic())); try { console.log('Malleable signature verification:', ed.verify(msg, malleableSigHex, key.getPublic())); } catch (e) { console.log('Malleable signature failed:', e.message); }