Curves p384 and p521 produce incorrect results
guidovranken opened this issue · 1 comments
guidovranken commented
Reproducer using Botan:
#include <botan/ecdsa.h>
#include <botan/system_rng.h>
#include <string>
#include <iostream>
static void PrivToPub(const std::string curve)
{
static ::Botan::System_RNG rng;
const ::Botan::EC_Group group(curve);
const ::Botan::BigInt priv_bn("12345");
const auto priv = std::make_unique<::Botan::ECDSA_PrivateKey>(::Botan::ECDSA_PrivateKey(rng, group, priv_bn));
std::cout << "Curve: " << curve << std::endl;
std::cout << "X: " << priv->public_point().get_affine_x().to_dec_string() << std::endl;
std::cout << "Y: " << priv->public_point().get_affine_y().to_dec_string() << std::endl;
std::cout << std::endl;
}
int main(void)
{
PrivToPub("secp256k1");
PrivToPub("secp224r1");
PrivToPub("secp384r1");
PrivToPub("secp521r1");
return 0;
}
Equivalent program using elliptic:
var elliptic = require('elliptic');
{
var ec = new elliptic.ec({curve: elliptic.curves.secp256k1});
var key = ec.keyFromPrivate('3039');
console.log('curve: secp256k1');
console.log('X: ' + key.getPublic().x.toString(10));
console.log('Y: ' + key.getPublic().y.toString(10));
console.log('');
}
{
var ec = new elliptic.ec({curve: elliptic.curves.p224});
var key = ec.keyFromPrivate('3039');
console.log('curve: p224');
console.log('X: ' + key.getPublic().x.toString(10));
console.log('Y: ' + key.getPublic().y.toString(10));
console.log('');
}
{
var ec = new elliptic.ec({curve: elliptic.curves.p384});
var key = ec.keyFromPrivate('3039');
console.log('curve: p384');
console.log('X: ' + key.getPublic().x.toString(10));
console.log('Y: ' + key.getPublic().y.toString(10));
console.log('');
}
{
var ec = new elliptic.ec({curve: elliptic.curves.p521});
var key = ec.keyFromPrivate('3039');
console.log('curve: p521');
console.log('X: ' + key.getPublic().x.toString(10));
console.log('Y: ' + key.getPublic().y.toString(10));
console.log('');
}
Botan reproducer prints:
Curve: secp256k1
X: 108607064596551879580190606910245687803607295064141551927605737287325610911759
Y: 6661302038839728943522144359728938428925407345457796456954441906546235843221
Curve: secp224r1
X: 3061900986193955425366457130965731838162532927611279465996423024034
Y: 18436067477095612653254216315762663287666664157889344177897564496249
Curve: secp384r1
X: 35772759585181787162268297474325652116815155765657644698345476493584618538330055829427528668512916462287191873719067
Y: 11136899713791192969974754349937219423803684580341842804433199322289941602306230647993576394757614557497720559657288
Curve: secp521r1
X: 99544213233443820423376623401842180038965950176775066024883365929328361117690710401394035951689292192082505666564905615167418780069649851129620356638766987
Y: 2400946881406844793138710845595355668053990247257733123230579507952350364035969673918344323836676104120174871607342463555389727042619568128535308503671291243
Elliptic reproducer prints:
curve: secp256k1
X: 108607064596551879580190606910245687803607295064141551927605737287325610911759
Y: 6661302038839728943522144359728938428925407345457796456954441906546235843221
curve: p224
X: 3061900986193955425366457130965731838162532927611279465996423024034
Y: 18436067477095612653254216315762663287666664157889344177897564496249
curve: p384
X: 15941129259703095806264506659575749372880183073752251579688675604437627307921357714103205186440293320524822325334223
Y: 22114920023073815056562105355911861035316317138200933415326341832754453118525583611873937475730301300025198969292291
curve: p521
X: 6719624281204685093485624880339661406616448960108927079674841988221937850012818464143226635650263055104211416481283153210468239891263449137663298022106688673
Y: 6149109476795150499310805847422629696752311120031290394754441545101372775372418633331331052611061203579528734291675940658254460750694406316130731176620134943
tiran commented
PyCA/cryptography gives the same results as Botan. PyCA/cryptography is Python package that wraps OpenSSL.
>>> for curve in [ec.SECP224R1(), ec.SECP256K1(), ec.SECP256R1(), ec.SECP384R1(), ec.SECP521R1()]:
... print(f"\ncurve: {curve.name}")
... private = ec.derive_private_key(12345, curve)
... pn = private.public_key().public_numbers()
... print(f"X: {pn.x}")
... print(f"Y: {pn.y}")
...
curve: secp224r1
X: 3061900986193955425366457130965731838162532927611279465996423024034
Y: 18436067477095612653254216315762663287666664157889344177897564496249
curve: secp256k1
X: 108607064596551879580190606910245687803607295064141551927605737287325610911759
Y: 6661302038839728943522144359728938428925407345457796456954441906546235843221
curve: secp256r1
X: 17611591551394103526348166819472991346437344487394483771310531299395461896210
Y: 65195855187618849542991473502236155813942564250927181129449382163772576288998
curve: secp384r1
X: 35772759585181787162268297474325652116815155765657644698345476493584618538330055829427528668512916462287191873719067
Y: 11136899713791192969974754349937219423803684580341842804433199322289941602306230647993576394757614557497720559657288
curve: secp521r1
X: 99544213233443820423376623401842180038965950176775066024883365929328361117690710401394035951689292192082505666564905615167418780069649851129620356638766987
Y: 2400946881406844793138710845595355668053990247257733123230579507952350364035969673918344323836676104120174871607342463555389727042619568128535308503671291243
I'm also getting wrong results for p256
:
> var elliptic = require('elliptic');
undefined
> {
... var ec = new elliptic.ec({curve: elliptic.curves.p256});
... var key = ec.keyFromPrivate('3039');
... console.log('curve: p256');
... console.log('X: ' + key.getPublic().x.toString(10));
... console.log('Y: ' + key.getPublic().y.toString(10));
... console.log('');
... }
curve: p256
X: 105003158266435578313975033833341595362026738309362563411293911691181582754198
Y: 1182522404204752220518975651306205864863731740355544177119796735558160832019
undefined