Guide

Working with Keys

Private keys, public keys, compression, and the one chain that speaks two curves.

A private key

Every chain uses the same generator. You get 32 bytes of randomness as a 64 character hex string, nothing more.

import { useBlockchain } from "@agntn/keys";
import Bitcoin from "@agntn/keys/blockchains/bitcoin";

const chain = useBlockchain(new Bitcoin());
const privateKey = chain.generateKeyPrivate();

console.log(privateKey); // '7f9e5b9e3bbed34a4c28c8c1665525fc2cd7afb4fdc7edca3eb93ddf8a31ef56'

secp256k1 chains ask @noble/curves for a key that is guaranteed to sit inside the curve order. ed25519 chains take raw bytes from crypto.getRandomValues, because any 32 bytes are a valid ed25519 seed. Both work in Node and in the browser, which is what the Keyspace explorer relies on.

The public key

const publicKey = chain.getKeyPublic(privateKey);

console.log(publicKey); // '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc'

On secp256k1 chains this is the compressed form: 33 bytes, starting with 02 or 03. That is what Bitcoin, Ethereum, and TRON expect today. If you need the uncompressed 65 byte key, ask for it:

const uncompressed = chain.getKeyPublic(privateKey, { compressed: false });
// '04a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc7513...'

ed25519 chains have no compression flag. The public key is always 32 bytes.

Both at once

const keyPair = chain.generateKeys();

keyPair.keys.private;
keyPair.keys.public;

The same options apply, so chain.generateKeys({ compressed: false }) gives you an uncompressed pair.

The shape you get back

interface Keys {
  keys: {
    private: string;
    public: string;
  };
}

Hex strings everywhere. Sizes by curve:

CurvePrivatePublic
secp256k164 hex chars66 hex chars compressed, 130 uncompressed
ed2551964 hex chars64 hex chars

Sui speaks two curves

Sui accepts ed25519 and secp256k1 keys on the same chain. The private key is the same 32 bytes either way. The scheme option decides which curve turns it into a public key:

import Sui from "@agntn/keys/blockchains/sui";

const suiChain = useBlockchain(new Sui());

const ed25519PublicKey = suiChain.getKeyPublic(privateKey); // default
const secp256k1PublicKey = suiChain.getKeyPublic(privateKey, { scheme: "secp256k1" });

Pick the scheme once and carry it through to getAddress, otherwise the address will not match the key. The Sui page shows the full round trip.

Under the hood

Curves come from @noble/curves, hashes from @noble/hashes. There is no second crypto implementation anywhere in the package, and adding one is the first thing a review would reject. EVM chains share everything through AbstractEVMBlockchain, so Ethereum and Base are the same code with a different name and coin type.

@agntn/keys·MIT license· Keys never leave the browser.