{"id":19178046,"url":"https://github.com/cmdruid/crypto-tools","last_synced_at":"2025-05-07T20:43:31.435Z","repository":{"id":62055287,"uuid":"557471559","full_name":"cmdruid/crypto-tools","owner":"cmdruid","description":"A modern suite of cryptography tools, built for the plebian developer.","archived":false,"fork":false,"pushed_at":"2024-11-03T19:30:44.000Z","size":928,"stargazers_count":9,"open_issues_count":2,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-07T20:43:24.301Z","etag":null,"topics":["bip340","cryptography","ecdsa","ripemd160","schnorr","secp256k1","sha256","signatures"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cmdruid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-25T18:48:16.000Z","updated_at":"2024-12-23T13:43:49.000Z","dependencies_parsed_at":"2024-06-18T21:24:37.912Z","dependency_job_id":null,"html_url":"https://github.com/cmdruid/crypto-tools","commit_stats":null,"previous_names":["cmdruid/crypto-tools","cmdruid/crypto-utils"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmdruid%2Fcrypto-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmdruid%2Fcrypto-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmdruid%2Fcrypto-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmdruid%2Fcrypto-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cmdruid","download_url":"https://codeload.github.com/cmdruid/crypto-tools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252954140,"owners_count":21830894,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bip340","cryptography","ecdsa","ripemd160","schnorr","secp256k1","sha256","signatures"],"created_at":"2024-11-09T10:36:28.391Z","updated_at":"2025-05-07T20:43:31.412Z","avatar_url":"https://github.com/cmdruid.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# crypto-tools\n\nA modern suite of cryptography tools, built for the plebian developer.\n\n* All tools are written in typescript and simple to use.\n* Methods return a [Buff](https://github.com/cmdruid/buff) object for quick conversion between formats.\n* Library works in both node and the browser.\n* Uses the well-audited [@noble/curves](https://github.com/paulmillr/noble-curves) library for fast ecc operations.\n\n```ts\nimport {\n  ecdh,    // Basic methods for using the Elliptic-Curve Diffe-Hellman protocol.\n  hash,    // Includes sha256, sha512, hmac, ripemd, tagged hashing, and more.\n  hd,      // BIP-0032 based key derivation tool, with support for non-numeric paths.\n  keys,    // A suite of tools for generating and tweaking secp256k1 key pairs.\n  math,    // Bigint-based ecc math library, with added field and point arithmetic.\n  signer,  // BIP-0340 'schnorr' based signing library with an extensive API.\n  tree,    // A basic suite of tools for creating merkle trees and validating proofs.\n  Field,   // A feature-rich uint8 array class with built-in math operations.\n  Point    // A secp2561 point object with built-in math operations.\n} from '@cmdcode/crypto-tools'\n```\n\nMore documentation coming soon!  \n\n## How to Import\n\nThis library is designed to support classic and modern ESM imports, in both a nodejs and browser environment.\n\nExample install via NPM or yarn:\n\n```bash\nnpm install @cmdcode/crypto-tools || yarn add @cmdcode/crypto-tools\n```\n\nClassic import into a nodejs project:\n\n```ts\nconst { Field, Point } = require('@cmdcode/crypto-tools')\n```\n\nModern import into an nodejs project:\n\n```ts\nimport { Field, Point } from '@cmdcode/crypto-tools'\n```\n\nClassic import into a browser-based project:\n\n```html\n\u003cscript src=\"https://unpkg.com/@cmdcode/crypto-tools\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  const { Field, Point } = window.crypto_tools\n\u003c/script\u003e\n```\n\nModern import into a browser-based project:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import { Field, Point } from \"https://unpkg.com/@cmdcode/crypto-tools/dist/module.mjs\" \n\u003c/script\u003e\n```\n\n## How to Use\n\nThis suite is made up of individual tools.\n\nEach tool can be unpacked from the main library, or imported and unpacked directly.\n\n```ts\n// Import tool from main library, then unpack methods.\nimport { signer } from '@cmdcode/crypto-tools'\nconst { sign_msg, verify_sig } = signer\n// Import methods from the tool directly.\nimport { sign_msg, verify_sig } from '@cmdcode/crypto-tools/signer'\n```\n\nMany methods will accept a `Bytes` value type, and return a `Buff` object. The `Bytes` type covers any data type that can be converted into raw bytes.\n\n```ts\ntype Bytes = string | number | bigint | Uint8Array | Buff\n```\n\n`Buff` works in place of a standard `Uint8Array` and offers a number of quick convertion methods.\n\n```ts\nconst seckey = get_seckey('deadbeef'.repeat(4))\nconsole.log('secret raw :', seckey)\nconsole.log('secret hex :', seckey.hex)\nconsole.log('secret big :', seckey.big)\n```\n\nYou can read more about the `Buff` API [here](https://github.com/cmdruid/buff).\n\n### ECDH Tool\n\nDerive a shared secret from between two keys, using Elliptic-Curve Diffe-Hellman protocol.\n\n```ts\nimport {\n  get_shared_key   // Get the shared secret for a given secret / public key pairing.\n  get_shared_code  // Use the derived secret to sign a message with HMAC-512.\n} from '@cmdcode/crypto-tools/ecdh'\n```\n\n### Hash Tool\n\nUsed for performing SHA-256, SHA-512, HMAC-256, HMAC-512, and other useful hashing methods.\n\n```ts\nimport {\n  sha256,   // Uses standard SHA-256 algorithm.\n  sha512,   // Uses standard SHA-512 algorithm.\n  ripe160,  // Uses RIPEMD-160 algorithm.\n  hash160,  // A double-hash algorithm used in bitcoin.\n  hash256,  // A double-hash algorithm used in bitcoin.\n  hmac256,  // Hash and sign a message using HMAC and SHA-256.\n  hmac512,  // Hash and sign a message using HMAC and SHA-512.\n  taghash,  // Creates a BIP-0340 standard 'tag' hash.\n  hash340,  // Hashes an array of data using BIP-0340 standards.\n} from '@cmdcode/crypto-tools/hash'\n```\n\nExamples:\n\n```ts\n// Each hash tool can accept many byte-compatible values.\nconst hash = sha256('fda0', 1024n, new Uint8Array(0), 42)\n// Use the taghash tool to create a BIP-0340 standard hash commitment.\nconst challenge = hash340('BIP0340/challenge', sig, pubkey, msg)\n```\n\n## HD Tool\n\nGenerate a pair of keys from a BIP-0032 style derivation path.\n\n```ts\nimport {\n  derive_key,     // Derive a key-pair using a BIP-0032* path of deterministic key tweaks.\n  parse_tweaks,   // Helper method to convert a derivation path into an array of tweaks.\n  generate_code,  // Generator method used to create the hash-chain.\n  encode_extkey   // Export a derived key-pair as a base58-encoded extended key.\n  parse_extkey    // Parse a base58-encoded extended key into its keys and meta-data.\n  derive_extkey   // Parse an extended key, then use a path to derive a child key-pair.\n} from '@cmdcode/crypto-tools/hd'\n```\n\n\u003e Note : The derivation tool also supports using non-numeric characters in the derivation path.\n\nExamples:\n\n```ts\nimport { derive_key, encode_extkey } from '@cmdcode/crypto-tools/hd'\n// Define some sample data.\nconst seed = 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542'\nconst path = \"m/0/2147483647'/1/2147483646'/2\"\n// Derive the key using the seed and derivation path.\nconst key_data = derive_key(path, seed)\n// Resulting key data:\nconsole.log('link:', key_data)\nlink: {\n  seckey : 'bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23',\n  pubkey : '024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c',\n  code   : '9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271',\n  path   : \"m/0/2147483647'/1/2147483646'/2\",\n  prev   : '02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0'\n}\n// You can convert the key data into a base58 extended key.\nconst extkey = encode_extkey(keylink)\n// Resulting extkey:\n'extkey : xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j'\n```\n\n## KeyPair Tools\n\nMethods for working with key pairs on the secp256k1 curve.\n\n```ts\nimport {\n  get_seckey,     // Convert a number or byte value into a secp256k1 secret key.\n  get_pubkey,     // Generate a secp256k1 public key for a given secret key.\n  tweak_seckey,   // Apply an array of additional tweaks to a secret key.\n  tweak_pubkey,   // Apply an array of additional tweaks to a public key.\n  gen_seckey,     // Generate a random secret key (using Web Crypto API).\n  negate_seckey,  // Perform a field negation operation on a secret key.\n  gen_keypair,    // Generate a secp256k1 secret and public key pair.\n  get_keypair,    // Convert a number or byte value into a secp256k1 key pair.\n  convert_32b,    // Convert any public key into a 32-byte x-only key.\n  convert_33b,    // Convert any public key into a 33-byte compressed key.\n} from '@cmdcode/crypto-tools/keys'\n```\n\nExamples:\n\n```ts\nimport { gen_seckey, get_pubkey } from '../src/keys.js'\n// Configure a demo keypair and message.\nconst seckey = gen_seckey()\nconst pubkey = get_pubkey(seckey, true)\nconsole.log('seckey:', seckey.hex)\nconsole.log('pubkey:', pubkey.hex)\n```\n\n## Math Library\n\nA bigint math library for performing arithmetic and field / point operations.\n\n```ts\nimport {\n  fd,         // Perform various modulo arithmetic using secp256k1 field order N.\n  pt,         // Perform various point operations using secp256k1 field order P.\n  mod,        // Apply a modulo for a bigint value.\n  mod_n,      // Apply modulo N for a bigint value.\n  mod_p,      // Apply modulo P for a bigint value.\n  pow,        // Raise a number to a given power.\n  pow2,       // Raise a number 2x to a given power.\n  pow_n,      // Raise a number to a given power, modulo N.\n  sqrt_n,     // Perform a square root operation on a bigint value, modulo N.\n  sqrt_p,     // Perfrom a aquare root operation on a bigint value, modulo P.\n  invert,     // Invert / negate a bigint field value.\n  mod_bytes,  // Perform a modulo operation on a byte value.\n  in_field,   // Check if a number is within the secp256k1 field order N.\n  on_curve    // Check if a number is within the secp256k1 curve order P.\n} from '@cmdcode/crypto-tools/math'\n```\n\n## Proofing Tools\n\nA simplified data proofing system, compatible with Nostr NIP-01 signed events.\n\n```ts\nimport {\n  create_proof,    // Create a compact signature proof.\n  parse_proof,     // Parse a compact proof into JSON.\n  validate_proof,  // Validate the schema of a proof.\n  verify_proof,    // Verify the hash and signature of a proof.\n  create_event,    // Convert a proof into a NIP-01 nostr note.\n  parse_config     // Parse the proof configuration from params.\n} from '@cmdcode/crypto-tools/proof'\n```\n\nExamples:\n\n```ts\n// Setup a demo keypair and message.\nconst [ seckey, pubkey ] = gen_keypair()\n// Create a proof.\nconst data   = { name : 'bob', key : 'abcd' }\nconst stamp  = Math.floor(Date.now() / 1000)\nconst params = [[ 'kind', 10000 ], [ 'stamp', stamp ]]\nconst proof  = create_proof(seckey, data, params)\nconsole.log(proof)\n`e403621bae6dffd75c76b282cc3525da14bf55a4ee3c396279f35f766b4ad079749b45be02446dc32e4eab02be026eef1592a23c209eb8b571f4f78ac6a762405cc802eae19177096334c0d4e53add9c97dc200e3f2e5700bd17aee14beb01e983456c5cb3461f20c8f3d59e8386a0d8ad4c3d6f58cacb9fc85eef514b8fc1007c476558535de220aebc916b0974e8b76dd584ba14b479d947f9ee52c40333c8?kind=10000\u0026stamp=1694095593`\n// Verify a proof\nconst is_valid = verify_proof(proof, data)\nconsole.log('is_valid:', is_valid)\n`is_valid : true`\n// Parse a proof into a ProofData object\nconst proof_data = parse_proof(proof)\nconsole.log('proof data:', proof_data)\nproof data: {\n  ref: 'e403621bae6dffd75c76b282cc3525da14bf55a4ee3c396279f35f766b4ad079',\n  pub: '749b45be02446dc32e4eab02be026eef1592a23c209eb8b571f4f78ac6a76240',\n  pid: '5cc802eae19177096334c0d4e53add9c97dc200e3f2e5700bd17aee14beb01e9',\n  sig: '83456c5cb3461f20c8f3d59e8386a0d8ad4c3d6f58cacb9fc85eef514b8fc1007c476558535de220aebc916b0974e8b76dd584ba14b479d947f9ee52c40333c8',\n  params: [ [ 'kind', '10000' ], [ 'stamp', '1694095593' ] ]\n}\n// Convert a proof into a nostr note.\nconst event = create_event(proof, data)\nconsole.log('event:', event)\nevent: {\n  kind: 10000,\n  content: '{\"name\":\"bob\",\"key\":\"abcd\"}',\n  tags: [],\n  pubkey: '749b45be02446dc32e4eab02be026eef1592a23c209eb8b571f4f78ac6a76240',\n  id: '5cc802eae19177096334c0d4e53add9c97dc200e3f2e5700bd17aee14beb01e9',\n  sig: '83456c5cb3461f20c8f3d59e8386a0d8ad4c3d6f58cacb9fc85eef514b8fc1007c476558535de220aebc916b0974e8b76dd584ba14b479d947f9ee52c40333c8',\n  created_at: 1694095593\n}\n```\n\n## Signature Tools\n\nA basic signing tool for working with BIP-0340 'schnorr' based digital signatures.\n\n```ts\nimport {\n  sign_msg,    // Sign a message using BIP-0340 standard.\n  verify_sig,  // Verify a BIP-0340 signature, key and, message.\n  gen_nonce,   // Generate a nonce for a given message.\n  recover_key  // Recover the secret key from a signature using ECDH recovery.\n} from '@cmdcode/crypto-tools/signer'\n```\n\nThe `sign_msg`, `verify_msg`, and `gen_nonce` methods are configurable through an options object:\n\n```ts\nexport interface SignConfig {\n  // Specify the aux data to use as a seed. Default is random.\n  aux          ?: Bytes | null\n  // Apply an adaptor tweak to the nonce value.\n  adaptors     ?: Bytes[]\n  // Apply tweaks to the nonce value during generation.\n  nonce_tweaks ?: Bytes[]\n  // Specify a public key to be used in ECDH key recovery.\n  recovery_key ?: Bytes\n  // Apply tweaks to the signature value during signing.\n  key_tweaks   ?: Bytes[]\n  // If validation fails, throw an error instead of returning false.\n  throws        : boolean\n  // If keys used during the signing operation should be negated for even-ness.\n  xonly         : boolean\n}\n```\nExamples:\n\n```ts\nimport { gen_keypair }          from '../src/keys.js'\nimport { sign_msg, verify_sig } from '../src/sig.js'\n// Configure a demo keypair and message.\nconst [ seckey, pubkey ] = gen_keypair(true)\nconst message  = 'abcd1234'.repeat(4)\n// Sign the message, then validate the signature.\nconst sig      = sign_msg(message, seckey)\nconst is_valid = verify_sig(sig, message, pubkey)\n// Check the console output.\nconsole.log('signature:', sig.hex)\nconsole.log('is_valid:', is_valid)\n```\n\nKey recovery allows you to designate another key-pair that can recover your private key from a signature, using ECDH.\n\n```ts\n// Configure two pairs of keys and a test message.\nconst [ hot_sec, hot_pub ]   = gen_keypair(true)\nconst [ cold_sec, cold_pub ] = gen_keypair(true)\nconst message = 'feedcab123'\n// Sign a message with the 'cold' pubkey as an ECDH recovery key.\nconst sig = sign_msg(message, hot_sec, { recovery_key: cold_pub })\n```\n\nUnder the hood, key recovery will modify the nonce generation so that an ECDH shared secret is used instead of your private key.\n\n```ts\n// Normal BIP-0340 nonce generation.\nlet sec_nonce  = taghash('BIP0340/nonce', seckey, pubkey, message)\n// Modified nonce generation for ECDH key recovery:\nlet shared_key = ecdh.get_shared_key(seckey, rec_pubkey)\n    sec_nonce  = hash340('BIP0340/nonce', shared_key, pubkey, message)\n```\n\nThis allows the 'cold' seckey to compute the shared secret, and thus extract the 'hot' seckey from the signature.\n\n```ts\n// Use the signature and 'cold' seckey to recovery the secret key.\nconst rec_key = recover_key(sig, message, hot_pub, cold_sec)\n// The recovered 'hot' seckey will be negated, so we will also negate \n// the original key in order to compare it with the recovered key.\nconsole.log('recovered key  :', rec_key.hex)\n`recovered key  : c18d25e25c1b229d14bd97e0daf3e4453765c2e007d9023698458573517ccd55`\nconsole.log('hot secret key :', get_seckey(hot_sec, true).hex)\n`hot secret key : c18d25e25c1b229d14bd97e0daf3e4453765c2e007d9023698458573517ccd55`\n```\n\nThe formula for recovering a secret key via ECDH shared secret signing:\n\n```ts\nR_value   = sig.slice(0, 32)\ns_value   = sig.slice(32, 64)\nsec_nonce = hash340('BIP0340/nonce', shared_key, pubkey, message)\nchallenge = hash340('BIP0340/challenge', R_value, pubkey, message)\nsec_key   = (s_value - sec_nonce) / challenge\n```\n\n## Field\n\nThe `Field` class will convert a key or integer value into a field value under the secp256k1 curve. This field value includes a built-in API for performing math operations in a simple and readable manner.\n\nEach `Field` object is stored as raw bytes, and they are directly usable as an `Uint8Array`.\n\n**Example:**\n\n```ts\nimport { Field } from '@cmdcode/crypto-tools/ecc'\n\nconst seed    = 'dead'.repeat(16)\nconst tweak   = 'beef'.repeat(16)\nconst secret  = Field.mod(seed)\nconst pubkey  = secret.point\nconst twk_sec = secret.add(tweak)\nconst twk_pub = twk_sec.point\n\nconsole.log('original seckey :', secret.hex)\nconsole.log('original pubkey :', pubkey.hex)\nconsole.log('tweaked seckey  :', twk_sec.hex)\nconsole.log('tweaked pubkey  :', twk_pub.hex)\n```\n\nDocumentation for the `Field` API:\n\n```ts\n// Fields can be created from a variety of types (strings are treated as hex).\ntype FieldValue = string | number | bigint | Uint8Array | Field\n\n// The Field class is an extension of the uint8 data type.\nclass Field extends Uint8Array {\n  // Prime N reference.\n  static N: bigint\n  // Converts a value under secp256k1 field order N. Same as new Field(x).\n  static mod(x: bigint, n?: bigint): bigint\n  // Normalize input values into bytes.\n  static normalize(num: FieldValue): Uint8Array\n  // Checks if value is within the secp256k1 field order N.\n  static is_valid(num: bigint): boolean\n  // Convert into a variety of formats.\n  get buff    : Buff\n  get raw     : Uint8Array\n  get big     : bigint\n  get hex     : string\n  // Return point object.\n  get point   : Point\n  // Checks if the point value of the field has an odd y coordinate.\n  get hasOddY : boolean\n  // Auto-negates the field value if it has an odd y coordiante.\n  get negated : Field\n  // All basic operations are available.\n  gt  (big: FieldValue) : boolean\n  lt  (big: FieldValue) : boolean\n  eq  (big: FieldValue) : boolean\n  ne  (big: FieldValue) : boolean\n  add (big: FieldValue) : Field\n  sub (big: FieldValue) : Field\n  mul (big: FieldValue) : Field\n  pow (big: FieldValue) : Field\n  div (big: FieldValue) : Field\n  negate()              : Field\n  generate()            : Point\n}\n```\n\n## Point\n\nThe `Point` class will convert a key or integer value into a point value under the secp256k1 curve. This point value includes a built-in API for performing math operations in a simple and readable manner.\n\nEach `Point` object contains an `x` coordiante and a `y` coordinate, stored as bigint values.\n\n**Example:**\n\n```ts\nimport { Point } from '@cmdcode/crypto-tools/ecc'\n\nconst _pubkey  = Point.from_x(secret.point.raw)\nconst _twk_pub = pubkey.add(tweak)\n\nconsole.log('imported point  :', _pubkey)\nconsole.log('imported pubkey :', _pubkey.hex)\nconsole.log('tweaked  pubkey :', _twk_pub.hex)\n```\n\nDocumentation for the `Point` API:\n\n```ts\n// Points can be created from a variety of types (strings are treated as hex).\ntype PointValue = string | number | bigint | Uint8Array | Point\n// The Point class stores the x / y coordinates of a point on the secp256k1 curve.\nclass Point {\n  // Prime N reference.\n  static P : bigint\n  static G : Point\n  // Create a point from an existing compressed key.\n  static from_x(x: PointValue, xonly ?: boolean) : Point\n  // Generate a point from a field (scalar) value.\n  static generate(value: FieldValue) : Point\n  // Helper method for importing points from Noble library.\n  static import(point: Point | ECPoint) : Point\n  // Accepts a varity of x-only and compressed key inputs.\n  // Will also accept coordinate data (as bigint). \n  constructor (x: PointValue, y?: bigint)\n  // Convert into a variety of formats.\n  get x        : Buff       // Return a buff object.\n  get y        : Buff       // Return a buff object.\n  get buff     : Buff       // Returns compressed key as bytes.\n  get hex      : string     // Returns compressed key as hex.\n  get hasEvenY : boolean\n  get hasOddY  : boolean\n  // Auto-negates the point value if it has an odd y coordiante.\n  get negated  : Point\n  // Basic math operations available.\n  eq  (value: PointValue) : boolean\n  add (x: PointValue)     : Point\n  sub (x: PointValue)     : Point\n  mul (value: PointValue) : Point\n  negate(): Point;\n}\n```\n\nA `Point` can also be generated from a `Field` object, allowing you to perform complex elliptic curve operations using mostly the `Field` class.\n\nHere is simplified example of signing and verifing a BIP-0340 digital signature, using the `Field` class:\n\n```ts\nimport { Field }  from '@cmdcode/crypto-tools/ecc'\nimport { digest } from '@cmdcode/crypto-tools/hash'\n// Generate some hex strings to use as a secret key and message.\nconst message   = 'dead'.repeat(16)\nconst secret    = 'beef'.repeat(16)\n// Compute the pubkey, nonce, and challenge values.\nconst pubkey    = Field.mod(secret).negated.point\nconst nonce     = hash340('BIP0340/nonce', secret, pubkey.x, message)\nconst R_value   = Field.mod(nonce).negated.point\nconst challenge = hash340('BIP0340/challenge', R_value.x, pubkey.x, message)\n// Signature is composed of an R value and S value.\nconst s_value   = Field.mod(secret).negated.mul(challenge).add(nonce)\nconst r_value   = Field.mod(s_value).point.sub(pubkey.mul(challenge))\n// Print the signature to console and report its validity.\nconsole.log('signature :', R_value.x.hex + s_value.hex)\nconsole.log('is valid  :', R_value.hex === r_value.hex)\n```\n\n## Development / Testing\n\nThis library uses yarn for package management, tape for writing tests, and rollup for cross-platform releases. Here are a few scripts that are useful for development.\n\n```bash\n## Performs a basic stress test for benchmarking performance.\nyarn bench\n## Compiles types and builds a new release in /dist folder.\nyarn build\n## Runs linting rules using ESLint and Typescript.\nyarn lint\n## Runs all TAP tests from the test/src folder.\nyarn test\n## Full script for generating a new release candidate.\nyarn release\n```\n\n## Bugs / Issues\n\nIf you run into any bugs or have any questions, please submit an issue ticket.\n\n## Contribution\n\nFeel free to fork and make contributions. Suggestions are welcome!\n\n## License\n\nUse this library however you want!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmdruid%2Fcrypto-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcmdruid%2Fcrypto-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmdruid%2Fcrypto-tools/lists"}