From 441b7428b0e8f6636c42118ad2aaa186d3c34c3f Mon Sep 17 00:00:00 2001 From: Kyle Den Hartog Date: Thu, 28 Jan 2021 22:42:27 +1300 Subject: [PATCH] ec: validate that a point before deriving keys This update checks to make sure that the public key passed in to ECDH is a point that actually exists on the curve. This is important to prevent a twist attack that can be used to reveal the private key of a party in an ECDH operation over a number of occurances. For more details on the attack see this blog post: https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md CVE: CVE-2020-28498 --- lib/elliptic/ec/key.js | 3 +++ test/ecdh-test.js | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/elliptic/ec/key.js b/lib/elliptic/ec/key.js index 8aa7451..55bf299 100644 --- a/lib/elliptic/ec/key.js +++ b/lib/elliptic/ec/key.js @@ -100,6 +100,9 @@ KeyPair.prototype._importPublic = function _importPublic(key, enc) { // ECDH KeyPair.prototype.derive = function derive(pub) { + if(!pub.validate()) { + assert(pub.validate(), 'public point not validated'); + } return pub.mul(this.priv).getX(); }; diff --git a/test/ecdh-test.js b/test/ecdh-test.js index aa28b75..47543b6 100644 --- a/test/ecdh-test.js +++ b/test/ecdh-test.js @@ -27,3 +27,17 @@ describe('ECDH', function() { test('ed25519'); test('secp256k1'); }); + +describe('ECDH twist attack', () => { + it('should be able to prevent a twist attack for secp256k1', () => { + var bobEcdh = new elliptic.ec('secp256k1'); + var malloryEcdh = new elliptic.ec('secp256k1'); + var bob = bobEcdh.genKeyPair(); + // This is a bad point that shouldn't be able to be passed to derive. + // If a bad point can be passed it's possible to perform a twist attack. + var mallory = malloryEcdh.keyFromPublic({ x: 14, y: 16 }); + assert.throws(function () { + bob.derive(mallory.getPublic()); + }); + }); +});