Description
a native library implementing secp256k1 purely for the crystal language. `secp256k1` is the elliptic curve used in the public-private-key cryptography required by bitcoin and ethereum.
this library allows for key generation of:
* private keys (from secure random within the elliptic curve field size)
* mini private keys (short 30-char base-57 keys)
* wallet import format (checksummed private keys)
* public keys, prefixed, compressed (from private)
* public keys, unprefixed and prefixed, uncompressed (from private)
* conversion between the different public key formats
this library allows for address generation of:
* bitcoin address, compressed and uncompressed (from private or public key)
* any other bitcoin-based address by passing a `version` byte
* ethereum address, checksummed and unchecksummed (from private or public key)
* any other ethereum-based address
furthermore, this library allows for:
* signing `(r, s)` and verification of arbitrary messages and message-hashes (with key pairs)
* managing `enode` addresses as per `devp2p` specification for ethereum nodes
secp256k1.cr alternatives and similar shards
Based on the "Blockchain" category.
Alternatively, view secp256k1.cr alternatives based on common mentions on social networks and blogs.
Get performance insights in less than 4 minutes
Do you think we are missing an alternative of secp256k1.cr or a related project?
README
secp256k1.cr
a native library implementing secp256k1
purely for the crystal language. secp256k1
is the elliptic curve used in the public-private-key cryptography required by bitcoin and ethereum.
this library allows for key generation of:
- private keys (from secure random within the elliptic curve field size)
- mini private keys (short 30-char base-56 keys)
- wallet import format (checksummed base-58 private keys)
- public keys, prefixed, compressed (from private)
- public keys, unprefixed and prefixed, uncompressed (from private)
- conversion between the different public key formats
this library allows for address generation of:
- bitcoin address, compressed and uncompressed (from private or public key)
- any other bitcoin-based address by passing a
version
byte - ethereum address, checksummed and unchecksummed (from private or public key)
- any other ethereum-based address
furthermore, this library allows for:
- signing
(r, s)
and verification of arbitrary messages and message-hashes (with key pairs) - managing
enode
addresses as perdevp2p
specification for ethereum nodes
installation
add the secp256k1
library to your shard.yml
dependencies:
secp256k1:
github: q9f/secp256k1.cr
version: "~> 0.3"
usage
tl;dr, check out [crystal run ./try.cr
](./try.cr)!
# import secp256k1
require "secp256k1"
this library exposes the following modules (in logical order):
Secp256k1
: necessary constants and data structures, including:Secp256k1::Keypair
: for managing private-public key-pairsSecp256k1::ECPoint
: for handling of secp256k1 elliptic curve points (public keys)Secp256k1::ECDSASignature
: for secp256k1 ecdsa signatures
Secp256k1::Core
: the entire core mathematics behind the elliptic curve cryptographySecp256k1::Util
: all tools for the handling of private-public key-pairsSecp256k1::Hash
: implementation of various hashing algorithms for convenienceSecp256k1::Signature
: allows for signing messages and verifying signaturesSecp256k1::Bitcoin
: for the generation of bitcoin addresses, including:Secp256k1::Bitcoin::Account
: for bitcoin account management
Secp256k1::Ethereum
: for the generation of ethereum addresses, includingSecp256k1::Ethereum::Account
: for ethereum account managementSecp256k1::Ethereum::Enode
: for devp2p enode address management
basic usage:
# generates a new keypair
key = Secp256k1::Keypair.new
# => #<Secp256k1::Keypair:0x7f8be5611d80>
# gets the private key
key.get_secret
# => "53d77137b39427a35d8c4b187f532d3912e1e7135985e730633e1e3c1b87ce97"
# gets the compressed public key with prefix
compressed = Secp256k1::Util.public_key_compressed_prefix key.public_key
# => "03e097fc69f0b92f711620511c07fefdd648e469df46b1e4385a00a1786f6bc55b"
generate a compressed bitcoin mainnet address:
# generates a new keypair
key = Secp256k1::Keypair.new
# => #<Secp256k1::Keypair:0x7f8be5611d80>
# generates a compressed bitcoin account from the keypair
btc = Secp256k1::Bitcoin::Account.new key, "00", true
# => #<Secp256k1::Bitcoin::Account:0x7f81ef21ab80>
# gets the wallet-import format (checksummed private key)
btc.wif
# => "Kz2grUzxEAxNopiREbNpVbjoitAGQVXnUZY4n8pNdmWdVqub99qu"
# gets the compressed bitcoin addresss
btc.address
# => "1Q1zbmPZtS2chwxpviqz6qHgoM8UUuviGN"
generate a checksummed ethereum address:
# generates a new keypair
key = Secp256k1::Keypair.new
# => #<Secp256k1::Keypair:0x7f81ef21ad00>
# generates an ethereum account from the keypair
eth = Secp256k1::Ethereum::Account.new key
# => #<Secp256k1::Ethereum::Account:0x7f81ef1faac0>
# gets the private key
eth.get_secret
# => "53d77137b39427a35d8c4b187f532d3912e1e7135985e730633e1e3c1b87ce97"
# gets the ethereum addresss
eth.address
# => "0x224008a0F3d3cB989c807F568c7f99Bf451328A6"
documentation
the full library documentation can be found here: q9f.github.io/secp256k1.cr
generate a local copy with:
crystal docs
testing
the library is entirely specified through tests in ./spec
; run:
crystal spec --verbose
understand
private keys are just scalars and public keys are points with x
and y
coordinates.
bitcoin public keys can be uncompressed #{p}#{x}#{y}
or compressed #{p}#{x}
. both come with a prefix p
which is useless for uncompressed keys but necessary for compressed keys to recover the y
coordinate on the secp256k1
elliptic curve.
ethereum public keys are uncompressed #{x}#{y}
without any prefix. the last 20 bytes slice of the y
coordinate is actually used as address without any checksum. a checksum was later added in eip-55 using a keccak256
hash and indicating character capitalization.
neither bitcoin nor ethereum allow for recovering public keys from an address unless there exists a transaction with a valid signature on the blockchain.
known issues
note: this library should not be used in production without proper auditing.
- this library is not constant time and might be subject to side-channel attacks. (#4)
- this library does unnecessary big-integer math and should someday rather correctly implement the secp256k1 prime field (#5)
found another issue? report it: github.com/q9f/secp256k1.cr/issues
contribute
create a pull request, and make sure tests and linter passes.
this pure crystal implementation is based on the python implementation wobine/blackboard101 which is also used as reference to write tests against. it's a complete rewrite of the abandoned packetzero/bitcoinutils for educational purposes.
honerable mention for the bitcoin wiki and the ethereum stackexchange for providing so many in-depth resources that supported this project in reimplementing everything.
license: apache license v2.0
*Note that all licence references and agreements mentioned in the secp256k1.cr README section above
are relevant to that project's source code only.