Files
herolib/lib/crypt/secp256k1
2024-12-25 12:38:51 +01:00
..
2024-12-25 12:38:51 +01:00
2024-12-25 12:38:51 +01:00
2024-12-25 12:38:51 +01:00
2024-12-25 12:38:51 +01:00
2024-12-25 12:38:51 +01:00
2024-12-25 12:38:51 +01:00

libsecp256k1

This is a lib256k1 binding for vlang.

Requirements

make sure the lib is installed

macOS

brew install secp256k1

Ubuntu

Compile latest release, version included in Ubuntu is outdated.

apt-get install -y build-essential wget autoconf libtool

wget https://github.com/bitcoin-core/secp256k1/archive/refs/tags/v0.3.2.tar.gz
tar -xvf v0.3.2.tar.gz

cd secp256k1-0.3.2/
./autogen.sh
./configure
make -j 5
make install

Arch

pacman -Su extra/libsecp256k1

Gentoo

emerge dev-libs/libsecp256k1

Features

  • Generate EC keys
  • Load existing EC keys
  • Serialize keys
  • Derivate shared key
  • Sign using ECDSA
  • Verify ECDSA signature
  • Sign using Schnorr
  • Verify a Schnorr signature
  • Support multi-signature with Schnorr

How to use

There are 4 differents things / features to understand in this secp256k1 implementation (wrapper).

Public and Privaye keys for secp256k1

This is a simple private/public key schema. This wrapper deals with hexdump of keys.

  • Private key is 32 bytes long (eg: 0x4a21f247ff3744e211e95ec478d5aba94a1d6d8bed613e8a9faece6d048399fc)
  • Public key is 33 bytes long (eg: 0x02df72fc4fa607ca3478446750bf9f8510242c4fa5849e77373d71104cd0c82ea0)

In this library, you can instanciate a secp256k1 object from 3 ways:

import freeflowuniverse.herolib.crypt.secp256k1
secp256k1.new()

Constructor without any arguments, will generate a new private and public key

secp256k1.new(privkey: '0x4a21f247ff3744e211e95ec478d5aba94a1d6d8bed613e8a9faece6d048399fc')

Using privkey argument, this will create an object from private key and generate corresponding public key

secp256k1.new(pubkey: '0x02df72fc4fa607ca3478446750bf9f8510242c4fa5849e77373d71104cd0c82ea0')

Using privkey argument, this will create an object with only the public key, which can be used for shared key or signature verification

Shared Keys

Library secp256k1 have one feature which allows you to derivate a shared intermediate common key from the private key of one party and the public key from the other party.

Example:

  • Shared key from Bob Private Key + Alice Public Key = Shared Key
  • Shared key from Alice Private Key + Bob Public Key = Shared Key (the same)

Using this feature, with your private key and target public key, you can derivate a shared (secret) key that only you both knows. This is really interresting to switch to a symetric encryption using that key as encryption key or use any well known secret without exchanging it.

To use the shared key feature, just call the sharedkeys() method:

bob := secp256k1.new(privhex: '0x478b45390befc3097e3e6e1a74d78a34a113f4b9ab17deb87e9b48f43893af83')!
alicepub := secp256k1.new(pubkey: '0x034a87ad6fbf83d89a91c257d4cc038828c6ed9104738ffd4bb7e5069858d4767b')!

shared := bob.sharedkeys(alicepub)
// shared = 0xf114df29d930f0cd37f62cbca36c46773a42bf87e12edcb35d47c4bfbd20514d

This works the same in the opposite direction:

alice := secp256k1.new(privhex: '0x8225825815f42e1c24a2e98714d99fee1a20b5ac864fbcb7a103cd0f37f0ffec')!
bobpub := secp256k1.new(pubkey: '0x03310ec949bd4f7fc24f823add1394c78e1e9d70949ccacf094c027faa20d99e21')!

shared := alice.sharedkeys(bobpub)
// shared = 0xf114df29d930f0cd37f62cbca36c46773a42bf87e12edcb35d47c4bfbd20514d (same shared key)

ECDSA Signature

This is the default signature method. When doing a signature, you don't sign the actual data but you have to sign a hash (sha256) of the data. This payload needs to be fixed length. The return signature is a 64 bytes long response.

When doing a signature using ecdsa method, you sign using the private key and verify using the public key of the same party. If Bob sign something, you have to verify using Bob public key is the signature matches.

If signature matches, that mean that is really Bob who signed the hash. Here, you need the signature and the message separately.

sstr := alice.sign_str("Hello World !")
valid := alicepub.verify_str(sstr, "Hello World !")
// valid = true

Schnorr Signature

This is the new prefered signature method. In theory, this method can in addition be able to sign using multiple parties without storing signature of everyone, signature can be chained but this is not implemented in this wrapper (lack of source documentation and understanding).

In practice, code wide, wrapper take care to handle everything for you and this really looks like the same way than ecdsa.

schnorr_sstr := alice.schnorr_sign_str("Hello World !")
valid := alicepub.schnorr_verify_str(schnorr_sstr, "Hello World !")
// valid = true