Making secp256k1
public keys with a given private key in different languages and different libraries
Using Bouncy Castle in C#
using System;
using System.Collections;
using System.Linq;
using System.Text;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
namespace Program.Main
{
class Program
{
public static readonly X9ECParameters _ecparameters = SecNamedCurves.GetByName("secp256k1");
public static readonly ECDomainParameters domain = new ECDomainParameters(_ecparameters.Curve, _ecparameters.G, _ecparameters.N, _ecparameters.H);
public static string ByteArrayToString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
public static (string,string) GetPublicKey(BigInteger privKeyInt)
{
var publicParams = new ECPublicKeyParameters(qa, domain);
byte[] publicKeyByteArray = publicParams.Q.GetEncoded();
int size = (publicKeyByteArray.Length - 1) / 2;
byte[] publicX = publicKeyByteArray.Skip(1).Take(size).ToArray();
byte[] publicY = publicKeyByteArray.Skip(1+size).Take(size).ToArray();
return (ByteArrayToString(publicX),ByteArrayToString(publicY));
}
static void Main()
{
string pKeyStr = "7511fcc16faa2e06b7e0672e258f2d3721a8191e1553444b21e16e95609e1030";
string expectedX = "7afa3a377b5808e4223dd62542a6e7e46ab0be95873464520193c1857ec2bb8f";
string expectedY = "58b050b73f31f1b8b98c0b04513257433bdad2a51188642d8b0e515fbfb3125f";
BigInteger privKeyInt = new BigInteger(pKeyStr,16);
var (pubXStr,pubYStr) = GetPublicKey(privKeyInt);
// compare x on public key
Console.Write($"X:{pubXStr == expectedX}");
// compare y on public key
Console.Write($"Y:{pubYStr == expectedY}");
}
}
}
Using pyecdsa
in python
from ecdsa import SECP256k1, SigningKey
pkey_str = "7511fcc16faa2e06b7e0672e258f2d3721a8191e1553444b21e16e95609e1030"
expected_x = int("7afa3a377b5808e4223dd62542a6e7e46ab0be95873464520193c1857ec2bb8f",16)
expected_y = int("58b050b73f31f1b8b98c0b04513257433bdad2a51188642d8b0e515fbfb3125f",16)
aa = SigningKey.from_string(bytes(bytearray.fromhex(pkey_str)),curve=SECP256k1)
# sanity check on private key
print("p:{}".format(aa.privkey.secret_multiplier == int(pkey_str,16)))
# compare x on public key
print("x:{}".format(aa.privkey.public_key.point.x() == expected_x))
# compare y on public key
print("y:{}".format(aa.privkey.public_key.point.y() == expected_y))
Using a python wrapper for libsecp256k1
import secp256k1
pkey_str = "7511fcc16faa2e06b7e0672e258f2d3721a8191e1553444b21e16e95609e1030"
expected_x = "7afa3a377b5808e4223dd62542a6e7e46ab0be95873464520193c1857ec2bb8f"
expected_y = "58b050b73f31f1b8b98c0b04513257433bdad2a51188642d8b0e515fbfb3125f"
aa = secp256k1.PrivateKey(bytes.fromhex(pkey_str), raw=True)
bb = aa.pubkey.serialize(compressed=False)
bb = bb[1:] # get rid of the first byte
bx = bb[:len(bb)//2]
by = bb[len(bb)//2:]
print("x:{}".format(bx.hex() == expected_x))
print("y:{}".format(by.hex() == expected_y))
Using elliptic
in nodeJS
const EC = require('elliptic').ec;
const ec = new EC('secp256k1');
const pKeyStr = "7511fcc16faa2e06b7e0672e258f2d3721a8191e1553444b21e16e95609e1030";
const expectedX = "7afa3a377b5808e4223dd62542a6e7e46ab0be95873464520193c1857ec2bb8f";
const expectedY = "58b050b73f31f1b8b98c0b04513257433bdad2a51188642d8b0e515fbfb3125f";
aa = ec.keyFromPrivate(pKeyStr,'hex')
bb = aa.getPublic()
console.log(`x:${bb.x.toBuffer().toString('hex') === expectedX}`)
console.log(`y:${bb.y.toBuffer().toString('hex') === expectedY}`)
Using a nodeJS wrapper for libsecp256k1
const secp256k1 = require('secp256k1')
const pKeyStr = "7511fcc16faa2e06b7e0672e258f2d3721a8191e1553444b21e16e95609e1030";
const expectedX = "7afa3a377b5808e4223dd62542a6e7e46ab0be95873464520193c1857ec2bb8f";
const expectedY = "58b050b73f31f1b8b98c0b04513257433bdad2a51188642d8b0e515fbfb3125f";
// get the public key in a compressed format
const pubKey = secp256k1.publicKeyCreate(Buffer.from(pKeyStr,"hex"),false)
const bb = pubKey.slice(1) // get rid of the first byte
const bx = bb.slice(0,bb.length/2)
const by = bb.slice(bb.length/2)
console.log(`x:${bx.toString('hex') === expectedX}`)
console.log(`y:${by.toString('hex') === expectedY}`)
ECPublicKeyParameters(qa, domain); parameter qa ?