Elliptic Curve operations, Schnorr, and ZKP for Bitcoin. Supports iOS macOS tvOS watchOS + Linux.

What's New

Taproot Tweaks



What's Changed

  • Bump Submodules/secp256k1 from 7d4f86d to 83186db by @dependabot in #362
  • Bump Submodules/secp256k1-zkp from edcba04 to ff33018 by @dependabot in #363

Full Changelog: 0.12.1...0.12.2

Build Status Build Status

🔐 secp256k1.swift

Swift package with elliptic curve public key cryptography, ECDSA, Schnorr Signatures for Bitcoin and C bindings from libsecp256k1.


Long-term goals are:

  • Lightweight ECDSA & Schnorr Signatures functionality
  • Built for simple or advance usage with things like BIP340
  • Exposed C bindings to take full control of the secp256k1 implementation
  • Familiar API design by modeling after Swift Crypto
  • Automatic updates for Swift and libsecp256k1
  • Availability for Linux and Apple platform ecosystems

Getting Started

This repository primarily uses Swift package manager as its build tool, so we recommend using that as well. Xcode comes with built-in support for Swift packages. From the menu bar, goto: File > Add Packages... If you manage packages via a Package.swift file, simply add secp256k1.swift as a dependencies' clause in your Swift manifest:

.package(url: "", from: "0.11.0"),

Try in a playground using the SPI Playgrounds app or 🏟 Arena

arena GigaBitcoin/secp256k1.swift

Example Usage


import secp256k1

//  Private key
let privateBytes = try! "14E4A74438858920D8A35FB2D88677580B6A2EE9BE4E711AE34EC6B396D87B5C".bytes
let privateKey = try! secp256k1.Signing.PrivateKey(rawRepresentation: privateBytes)

//  Public key
print(String(bytes: privateKey.publicKey.rawRepresentation))

let messageData = "We're all Satoshi.".data(using: .utf8)!
let signature = try! privateKey.signature(for: messageData)

//  DER signature
print(try! signature.derRepresentation.base64EncodedString())


// Disable BIP340 to enable Schnorr signatures of variable length messages
let privateKey = try! secp256k1.Schnorr.PrivateKey(strict: false)

// Extra params for custom signing
var auxRand = try! "C87AA53824B4D7AE2EB035A2B5BBBCCC080E76CDC6D1692C4B0B62D798E6D906".bytes
var messageDigest = try! "7E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C".bytes

// API allows for signing variable length messages
let signature = try! privateKey.signature(message: &messageDigest, auxiliaryRand: &auxRand)


let privateKey = try! secp256k1.Signing.PrivateKey()

// Adding a tweak to the private key and public key
let tweak = try! "5f0da318c6e02f653a789950e55756ade9f194e1ec228d7f368de1bd821322b6".bytes
let tweakedPrivateKey = try! privateKey.add(tweak)
let tweakedPublicKeyKey = try! privateKey.publicKey.add(tweak)

Elliptic Curve Diffie Hellman

let privateKey = try! secp256k1.KeyAgreement.PrivateKey()
let publicKey = try! secp256k1.KeyAgreement.PrivateKey().publicKey

// Create a shared secret with a private key from only a public key
let sharedSecret = try! privateKey.sharedSecretFromKeyAgreement(with: publicKey)

Silent Payments

let privateSign1 = try! secp256k1.Signing.PrivateKey()
let privateSign2 = try! secp256k1.Signing.PrivateKey()

let privateKey1 = try! secp256k1.KeyAgreement.PrivateKey(rawRepresentation: privateSign1.rawRepresentation)
let privateKey2 = try! secp256k1.KeyAgreement.PrivateKey(rawRepresentation: privateSign2.rawRepresentation)

let sharedSecret1 = try! privateKey1.sharedSecretFromKeyAgreement(with: privateKey2.publicKey)
let sharedSecret2 = try! privateKey2.sharedSecretFromKeyAgreement(with: privateKey1.publicKey)

let sharedSecretSign1 = try! secp256k1.Signing.PrivateKey(rawRepresentation: sharedSecret1.bytes)
let sharedSecretSign2 = try! secp256k1.Signing.PrivateKey(rawRepresentation: sharedSecret2.bytes)

// Payable Silent Payment public key
let xonlyTweak2 = try! sharedSecretSign2.publicKey.xonly.add(privateSign1.publicKey.xonly.bytes)

// Spendable Silent Payment private key
let privateTweak1 = try! sharedSecretSign1.add(xonly: privateSign1.publicKey.xonly.bytes)


let privateKey = try! secp256k1.Recovery.PrivateKey()
let messageData = "We're all Satoshi.".data(using: .utf8)!

// Create a recoverable ECDSA signature
let recoverySignature = try! privateKey.signature(for: messageData)

// Recover an ECDSA public key from a signature
let publicKey = try! secp256k1.Recovery.PublicKey(messageData, signature: recoverySignature)

// Convert a recoverable signature into a normal signature
let signature = try! recoverySignature.normalize


These APIs should not be considered stable and may change at any time.


  • Swift Tools 5.6.0
View More Packages from this Author


  • None
Last updated: Fri Jun 02 2023 02:55:19 GMT-0500 (GMT-05:00)