Skip to content

Commit

Permalink
Signature Updates (#338)
Browse files Browse the repository at this point in the history
  • Loading branch information
csjones committed Apr 20, 2023
1 parent 8d033e8 commit d7ff2d3
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 186 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Long-term goals are:
This repository primarily uses Swift package manager as its build tool, so we recommend using that as well. Xcode comes with [built-in support](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app) 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:

```swift
.package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", .upToNextMajor(from: "0.10.0"))
.package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", from: "0.11.0"),
```

Try in a [playground](spi-playgrounds://open?dependencies=GigaBitcoin/secp256k1.swift) using the [SPI Playgrounds app](https://swiftpackageindex.com/try-in-a-playground) or 🏟 [Arena](https://github.com/finestructure/arena)
Expand All @@ -46,7 +46,7 @@ print(String(bytes: privateKey.publicKey.rawRepresentation))

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

// DER signature
print(try! signature.derRepresentation.base64EncodedString())
Expand All @@ -55,14 +55,14 @@ print(try! signature.derRepresentation.base64EncodedString())
## Schnorr

```swift
let privateKey = try! secp256k1.Signing.PrivateKey()
let privateKey = try! secp256k1.Schnorr.PrivateKey()

// 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.schnorr.signature(message: &messageDigest, auxiliaryRand: &auxRand)
let signature = try! privateKey.signature(message: &messageDigest, auxiliaryRand: &auxRand)
```

## Tweak
Expand Down Expand Up @@ -111,11 +111,11 @@ let privateTweak1 = try! sharedSecretSign1.add(xonly: privateSign1.publicKey.xon
## Recovery

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

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

// Recover an ECDSA public key from a signature
let publicKey = try! secp256k1.Recovery.PublicKey(messageData, signature: recoverySignature)
Expand All @@ -126,5 +126,5 @@ let signature = try! recoverySignature.normalize


# Danger
These APIs should not be considered stable and may change at any time, libsecp256k1 is still experimental and has not been formally released.
These APIs should not be considered stable and may change at any time.

30 changes: 0 additions & 30 deletions Sources/zkp/Asymmetric.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,6 @@ public extension secp256k1 {
baseKey.key
}

/// The ECDSA signing object.
///
/// You can use this object to create a digital signature for a given piece of data.
public var ecdsa: secp256k1.Signing.ECDSASigner {
ECDSASigner(signingKey: baseKey)
}

/// The Schnorr signing object.
///
/// You can use this object to create a digital signature for a given piece of data
/// using the Schnorr algorithm.
public var schnorr: secp256k1.Signing.SchnorrSigner {
SchnorrSigner(signingKey: baseKey)
}

/// The associated public key for verifying signatures created with this private key.
///
/// - Returns: The associated public key.
Expand Down Expand Up @@ -95,21 +80,6 @@ public extension secp256k1 {
baseKey.rawRepresentation
}

/// The ECDSA validating object.
///
/// You can use this object to verify digital signatures created by the corresponding private key.
public var ecdsa: secp256k1.Signing.ECDSAValidator {
ECDSAValidator(validatingKey: baseKey)
}

/// The Schnorr validating object.
///
/// You can use this object to verify digital signatures created by the corresponding private key
/// using the Schnorr algorithm.
public var schnorr: secp256k1.Signing.SchnorrValidator {
SchnorrValidator(validatingKey: baseKey)
}

/// The associated x-only public key for verifying Schnorr signatures.
///
/// - Returns: The associated x-only public key.
Expand Down
66 changes: 12 additions & 54 deletions Sources/zkp/ECDSA.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,36 +137,7 @@ public extension secp256k1.Signing {

// MARK: - secp256k1 + Signing Key

public extension secp256k1.Signing {
struct ECDSASigner {
/// Generated secp256k1 Signing Key.
var signingKey: PrivateKeyImplementation
}
}

extension secp256k1.Signing.ECDSASigner: DigestSigner, Signer {
/// Generates a recoverable ECDSA signature.
///
/// - Parameter digest: The digest to sign.
/// - Returns: The recoverable ECDSA Signature.
/// - Throws: If there is a failure producing the signature
public func recoverableSignature<D: Digest>(for digest: D) throws -> secp256k1.Recovery.ECDSASignature {
var signature = secp256k1_ecdsa_recoverable_signature()

guard secp256k1_ecdsa_sign_recoverable(
secp256k1.Context.raw,
&signature,
Array(digest),
Array(signingKey.rawRepresentation),
nil,
nil
).boolValue else {
throw secp256k1Error.underlyingCryptoError
}

return try secp256k1.Recovery.ECDSASignature(signature.dataValue)
}

extension secp256k1.Signing.PrivateKey: DigestSigner {
/// Generates an ECDSA signature over the secp256k1 elliptic curve.
///
/// - Parameter digest: The digest to sign.
Expand All @@ -179,7 +150,7 @@ extension secp256k1.Signing.ECDSASigner: DigestSigner, Signer {
secp256k1.Context.raw,
&signature,
Array(digest),
Array(signingKey.rawRepresentation),
Array(rawRepresentation),
nil,
nil
).boolValue else {
Expand All @@ -188,17 +159,9 @@ extension secp256k1.Signing.ECDSASigner: DigestSigner, Signer {

return try secp256k1.Signing.ECDSASignature(signature.dataValue)
}
}

/// Generates an ECDSA signature over the secp256k1 elliptic curve.
/// SHA256 is used as the hash function.
///
/// - Parameter data: The data to sign.
/// - Returns: The ECDSA Signature.
/// - Throws: If there is a failure producing the signature.
public func recoverableSignature<D: DataProtocol>(for data: D) throws -> secp256k1.Recovery.ECDSASignature {
try recoverableSignature(for: SHA256.hash(data: data))
}

extension secp256k1.Signing.PrivateKey: Signer {
/// Generates an ECDSA signature over the secp256k1 elliptic curve.
/// SHA256 is used as the hash function.
///
Expand All @@ -212,30 +175,25 @@ extension secp256k1.Signing.ECDSASigner: DigestSigner, Signer {

// MARK: - secp256k1 + Validating Key

public extension secp256k1.Signing {
struct ECDSAValidator {
/// Generated secp256k1 Validating Key.
var validatingKey: PublicKeyImplementation
}
}

extension secp256k1.Signing.ECDSAValidator: DigestValidator, DataValidator {
extension secp256k1.Signing.PublicKey: DigestValidator {
/// Verifies an ECDSA signature over the secp256k1 elliptic curve.
///
/// - Parameters:
/// - signature: The signature to verify
/// - digest: The digest that was signed.
/// - Returns: True if the signature is valid, false otherwise.
public func isValidSignature<D: Digest>(_ signature: secp256k1.Signing.ECDSASignature, for digest: D) -> Bool {
var secp256k1Signature = secp256k1_ecdsa_signature()
var secp256k1PublicKey = secp256k1_pubkey()
var ecdsaSignature = secp256k1_ecdsa_signature()
var publicKey = secp256k1_pubkey()

signature.rawRepresentation.copyToUnsafeMutableBytes(of: &secp256k1Signature.data)
signature.rawRepresentation.copyToUnsafeMutableBytes(of: &ecdsaSignature.data)

return secp256k1_ec_pubkey_parse(secp256k1.Context.raw, &secp256k1PublicKey, validatingKey.bytes, validatingKey.bytes.count).boolValue &&
secp256k1_ecdsa_verify(secp256k1.Context.raw, &secp256k1Signature, Array(digest), &secp256k1PublicKey).boolValue
return secp256k1_ec_pubkey_parse(secp256k1.Context.raw, &publicKey, bytes, bytes.count).boolValue &&
secp256k1_ecdsa_verify(secp256k1.Context.raw, &ecdsaSignature, Array(digest), &publicKey).boolValue
}
}

extension secp256k1.Signing.PublicKey: DataValidator {
/// Verifies an ECDSA signature over the secp256k1 elliptic curve.
/// SHA256 is used as the hash function.
///
Expand Down
Loading

0 comments on commit d7ff2d3

Please sign in to comment.