A collection of useful crypto utilities for Polkadot ecosystem projects
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Signing and verification functions for multiple cryptographic schemes with automatic signature format detection. Supports sr25519, ed25519, secp256k1, and Ethereum-style signatures.
Sr25519 signing and verification with support for Schnorr signatures and VRF.
/**
* Sign a message using sr25519
* @param message - Message string or bytes to sign
* @param keypair - Keypair object with publicKey and secretKey
* @returns 64-byte signature
*/
function sr25519Sign(message: string | Uint8Array, keypair: Partial<Keypair>): Uint8Array;
/**
* Verify sr25519 signature
* @param message - Original message bytes
* @param signature - 64-byte signature to verify
* @param publicKey - 32-byte public key
* @returns true if signature is valid
*/
function sr25519Verify(message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean;Usage Example:
import { sr25519PairFromSeed, sr25519Sign, sr25519Verify } from "@polkadot/util-crypto";
const seed = new Uint8Array(32);
const pair = sr25519PairFromSeed(seed);
const message = new TextEncoder().encode("Hello Polkadot");
// Sign message
const signature = sr25519Sign(message, pair);
// Verify signature
const isValid = sr25519Verify(message, signature, pair.publicKey);
console.log("Signature valid:", isValid);VRF signing and verification for randomness generation with proof.
/**
* Generate VRF signature and proof
* @param secretKey - 64-byte secret key
* @param context - Context bytes for VRF
* @param message - Message to sign
* @param extra - Optional extra randomness
* @returns VRF signature and proof
*/
function sr25519VrfSign(secretKey: Uint8Array, context: Uint8Array, message: Uint8Array, extra?: Uint8Array): Uint8Array;
/**
* Verify VRF signature and proof
* @param publicKey - 32-byte public key
* @param context - Context bytes for VRF
* @param message - Original message
* @param proof - VRF proof to verify
* @param extra - Optional extra randomness
* @returns true if VRF proof is valid
*/
function sr25519VrfVerify(publicKey: Uint8Array, context: Uint8Array, message: Uint8Array, proof: Uint8Array, extra?: Uint8Array): boolean;Ed25519 signing and verification with deterministic signatures.
/**
* Sign a message using ed25519
* @param publicKey - 32-byte public key
* @param secretKey - 32 or 64-byte secret key
* @param message - Message bytes to sign
* @returns 64-byte signature
*/
function ed25519Sign(publicKey: Uint8Array, secretKey: Uint8Array, message: Uint8Array): Uint8Array;
/**
* Verify ed25519 signature
* @param message - Original message bytes
* @param signature - 64-byte signature to verify
* @param publicKey - 32-byte public key
* @returns true if signature is valid
*/
function ed25519Verify(message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean;Usage Example:
import { ed25519PairFromSeed, ed25519Sign, ed25519Verify } from "@polkadot/util-crypto";
const seed = new Uint8Array(32);
const pair = ed25519PairFromSeed(seed);
const message = new TextEncoder().encode("Hello World");
// Sign message
const signature = ed25519Sign(pair.publicKey, pair.secretKey, message);
// Verify signature
const isValid = ed25519Verify(message, signature, pair.publicKey);Secp256k1 signing, verification, and public key recovery for Ethereum compatibility.
/**
* Sign message hash using secp256k1
* @param msgHash - 32-byte message hash
* @param secretKey - 32-byte private key
* @returns Signature with recovery info
*/
function secp256k1Sign(msgHash: Uint8Array, secretKey: Uint8Array): Uint8Array;
/**
* Verify secp256k1 signature
* @param msgHash - 32-byte message hash
* @param signature - Signature bytes
* @param publicKey - Public key for verification
* @returns true if signature is valid
*/
function secp256k1Verify(msgHash: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean;
/**
* Recover public key from signature
* @param msgHash - 32-byte message hash
* @param signature - Signature bytes
* @param recovery - Recovery parameter (0-3)
* @returns Recovered public key
*/
function secp256k1Recover(msgHash: Uint8Array, signature: Uint8Array, recovery: number): Uint8Array;
/**
* Compress secp256k1 public key from uncompressed (65 bytes) to compressed (33 bytes)
* @param publicKey - Public key to compress (33 or 65 bytes)
* @param onlyJs - Force JavaScript implementation
* @returns Compressed public key (33 bytes)
*/
function secp256k1Compress(publicKey: Uint8Array, onlyJs?: boolean): Uint8Array;
/**
* Expand secp256k1 public key from compressed (33 bytes) to uncompressed coordinates (64 bytes)
* @param publicKey - Public key to expand (33 or 65 bytes)
* @param onlyJs - Force JavaScript implementation
* @returns Uncompressed public key coordinates (64 bytes, without 0x04 prefix)
*/
function secp256k1Expand(publicKey: Uint8Array, onlyJs?: boolean): Uint8Array;
/**
* Add a tweak to a secp256k1 private key
* @param seckey - Private key (32 bytes)
* @param tweak - Tweak value (32 bytes)
* @param onlyBn - Force BN.js implementation
* @returns Modified private key (32 bytes)
*/
function secp256k1PrivateKeyTweakAdd(seckey: Uint8Array, tweak: Uint8Array, onlyBn?: boolean): Uint8Array;Usage Example:
import {
secp256k1PairFromSeed,
secp256k1Sign,
secp256k1Verify,
secp256k1Recover,
secp256k1Compress,
secp256k1Expand,
secp256k1PrivateKeyTweakAdd,
keccak256AsU8a
} from "@polkadot/util-crypto";
const seed = new Uint8Array(32);
const pair = secp256k1PairFromSeed(seed);
const message = new TextEncoder().encode("Hello Ethereum");
const messageHash = keccak256AsU8a(message);
// Sign message hash
const signature = secp256k1Sign(messageHash, pair.secretKey);
// Verify signature
const isValid = secp256k1Verify(messageHash, signature, pair.publicKey);
// Recover public key
const recoveredKey = secp256k1Recover(messageHash, signature, 0);
// Compress public key
const compressedKey = secp256k1Compress(pair.publicKey);
// Expand compressed key to coordinates
const expandedKey = secp256k1Expand(compressedKey);
// Add tweak to private key
const tweak = new Uint8Array(32);
const tweakedPrivateKey = secp256k1PrivateKeyTweakAdd(pair.secretKey, tweak);Automatic detection and verification of different signature formats.
/**
* Verify signature with automatic format detection
* @param message - Original message bytes
* @param signature - Signature in any supported format
* @param addressOrPublicKey - Address string or public key bytes
* @returns Verification result with details
*/
function signatureVerify(
message: Uint8Array,
signature: Uint8Array | string,
addressOrPublicKey: string | Uint8Array
): VerifyResult;
interface VerifyResult {
/** The detected crypto interface, or 'none' if not detected */
crypto: 'none' | KeypairType;
/** The validity for this result, false if invalid */
isValid: boolean;
/** Flag to indicate if the passed data was wrapped in <Bytes>...</Bytes> */
isWrapped: boolean;
/** The extracted publicKey */
publicKey: Uint8Array;
}Usage Example:
import { signatureVerify } from "@polkadot/util-crypto";
const message = new TextEncoder().encode("Test message");
const signature = "0x..."; // Any signature format
const address = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";
const result = signatureVerify(message, signature, address);
console.log("Crypto scheme:", result.crypto);
console.log("Is valid:", result.isValid);
console.log("Public key:", result.publicKey);Hard and soft key derivation for hierarchical signing.
/**
* Derive sr25519 public key (soft derivation)
* @param publicKey - Parent public key
* @param chainCode - Chain code for derivation
* @returns Derived public key
*/
function sr25519DerivePublic(publicKey: Uint8Array, chainCode: Uint8Array): Uint8Array;
/**
* Derive sr25519 key pair (soft derivation)
* @param pair - Parent key pair
* @param chainCode - Chain code for derivation
* @returns Derived key pair
*/
function sr25519DeriveSoft(pair: Keypair, chainCode: Uint8Array): Keypair;
/**
* Hard derivation for sr25519
* @param seed - Parent seed
* @param chainCode - Chain code for derivation
* @returns Derived seed
*/
function sr25519DeriveHard(seed: Uint8Array, chainCode: Uint8Array): Uint8Array;
/**
* Sr25519 Diffie-Hellman agreement
* @param publicKey - Other party's public key
* @param secretKey - Own secret key
* @returns Shared secret
*/
function sr25519Agreement(publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array;/**
* Hard derivation for ed25519
* @param seed - Parent seed
* @param chainCode - Chain code for derivation
* @returns Derived seed
*/
function ed25519DeriveHard(seed: Uint8Array, chainCode: Uint8Array): Uint8Array;signatureVerify handles automatic detectionInstall with Tessl CLI
npx tessl i tessl/npm-polkadot--util-crypto