jonericcook
Generate public/private keys and sign messages
Hello,
I am trying write elixir code to recreate the behavior from this python script.
import bech32
import ecdsa
from ecdsa.curves import SECP256k1
from ecdsa.util import sigencode_der
private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
private_key_bytes = private_key.to_string()
print("Private Key: ", private_key_bytes.hex())
verifying_key = private_key.get_verifying_key()
public_key_compressed_bytes = verifying_key.to_string("compressed")
print("Public Key: ", public_key_compressed_bytes.hex())
readdr_bytes = b"\x04" + public_key_compressed_bytes
readdr_bytes5 = bech32.convertbits(readdr_bytes, 8, 5)
wallet_address = bech32.bech32_encode("rdx", readdr_bytes5)
print("Wallet Address: ", wallet_address)
blob_to_sign = "42244f5ac531a551a8ffd6f6c9e63e481fe1cf30b7bc42676840c3149695445b"
signature_der = private_key.sign_digest(
bytearray.fromhex(blob_to_sign), sigencode=sigencode_der).hex()
print("SignatureDER: ", signature_der)
I have this code written so far but am not able to get the same signatureDER.
defmodule Keypair do
def sign(data, private_key) do
{:ok, private_key} = Curvy.Util.decode(private_key, :hex)
Curvy.sign(data, private_key, encoding: :hex)
end
def from_private_key(private_key) do
{:ok, private_key} = Curvy.Util.decode(private_key, :hex)
private_key
|> Curvy.Key.from_privkey()
|> format_keys()
end
defp format_keys(keypair) do
public_key = Curvy.Key.to_pubkey(keypair)
radix_address = Bech32.encode("rdx", <<4>> <> public_key)
public_key = Curvy.Util.encode(public_key, :hex)
private_key =
keypair
|> Curvy.Key.to_privkey()
|> Curvy.Util.encode(:hex)
%{radix_address: radix_address, public_key: public_key, private_key: private_key}
end
end
Im using Curvy for generating keys and signing Curvy — Curvy v0.3.0 and bech32 | Hex to convert the public key to the desired address format.
Below is the console print outs.
PYTHON OUTPUT
Private Key: 2574132b032927dad619dcfe3508646e54400b6a9437ba501e78e51e488be1be
Public Key: 027d637e3a6f331ef1ff00912dd1cddf246f887522f3d805136bf1d377296e35f7
Wallet Address: rdx1qsp86cm78fhnx8h3luqfztw3eh0jgmugw5308kq9zd4lr5mh99hrtac2dmtpr
SignatureDER: 304502210086d9d7a8a9d5f47a4bd6947cd083622c0a08bd430b6feb0e5364a9663423d16a0220479fcdcbeb6d80e697fd71846008cfa659fa724f27d5632ee1267cc8ab54cdf2
ELIXIR OUTPUT
iex(1)> Keypair.from_private_key("2574132b032927dad619dcfe3508646e54400b6a9437ba501e78e51e488be1be")
%{
private_key: "2574132b032927dad619dcfe3508646e54400b6a9437ba501e78e51e488be1be",
public_key: "027d637e3a6f331ef1ff00912dd1cddf246f887522f3d805136bf1d377296e35f7",
radix_address: "rdx1qsp86cm78fhnx8h3luqfztw3eh0jgmugw5308kq9zd4lr5mh99hrtac2dmtpr"
}
iex(2)> Keypair.sign("42244f5ac531a551a8ffd6f6c9e63e481fe1cf30b7bc42676840c3149695445b","2574132b032927dad619dcfe3508646e54400b6a9437ba501e78e51e488be1be")
"304402201b1151bff7543ef6ed3e0f76d84f22327bd6d8a34743db1f15b9f56339a9177002202be2797a2d541713aa35f5f7ddbe07974dac00e5cf4624f47d496e90338b1bac"
I also tried the Elixir sign function like this but it did not produce the same signature.
def sign(data, private_key) do
{:ok, private_key} = Curvy.Util.decode(private_key, :hex)
{:ok, data} = Curvy.Util.decode(data, :hex)
Curvy.sign(data, private_key, encoding: :hex)
end
For more context - this endeavor started from these two doc pages.
Here he creates an address Creating a Radix Wallet Address for Development Purposes - RadixPool Technical
Here he creates an address and signs a message with it Unregister a Validator Node using the Keystore File - RadixPool Technical
I believe the issue is in how Curvy does signing? I’m leaning towards using libsecp256k1 | Hex but cant find docs on how to use it. What do y’all think? Could my goals be achieved by using libsecp256k1?
Thank you for taking the time to help 
Marked As Solved
jonericcook
Changing the sign function to this worked!
def sign(data, private_key) do
{:ok, private_key} = Curvy.Util.decode(private_key, :hex)
{:ok, data} = Curvy.Util.decode(data, :hex)
Curvy.sign(data, private_key, encoding: :hex, hash: :none)
end







