Skip to content

Commit 9e6c271

Browse files
authored
[BREAK API] ECDSA.Recoverable to ECDSAWithKeyRecovery & ECDSA.NonRecoverable to ECDSA (#34)
1 parent a54a100 commit 9e6c271

33 files changed

Lines changed: 332 additions & 243 deletions

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ The API of K1 maps almost 1:1 with Apple's [CryptoKit][ck], vendoring a set of k
1414
Just like that K1 vendors these key pairs:
1515
- `K1.KeyAgreement.PrivateKey` / `K1.KeyAgreement.PublicKey` for key agreement (ECDH)
1616
- `K1.Schnorr.PrivateKey` / `K1.Schnorr.PublicKey` for sign / verify methods using Schnorr signature scheme
17-
- `K1.ECDSA.Recoverable.PrivateKey` / `K1.ECDSA.Recoverable.PublicKey` for sign / verify methods using ECDSA (producing/validating signature where public key is recoverable)
18-
- `K1.ECDSA.NonRecoverable.PrivateKey` / `K1.ECDSA.NonRecoverable.PublicKey` for sign / verify methods using ECDSA (producing/validating signature where public key is **not** recoverable)
17+
- `K1.ECDSAWithKeyRecovery.PrivateKey` / `K1.ECDSAWithKeyRecovery.PublicKey` for sign / verify methods using ECDSA (producing/validating signature where public key is recoverable)
18+
- `K1.ECDSA.PrivateKey` / `K1.ECDSA.PublicKey` for sign / verify methods using ECDSA (producing/validating signature where public key is **not** recoverable)
1919

2020
Just like you can convert between e.g. `Curve25519.KeyAgreement.PrivateKey` and `Curve25519.Signing.PrivateKey` back and forth using any of the initializers and serializer, you can convert between all PrivateKeys and all PublicKeys of all features in K1.
2121

@@ -64,8 +64,8 @@ Furthermore, all PublicKeys's have these additional APIs:
6464
## ECDSA (Elliptic Curve Digital Signature Algorithm)
6565

6666
There exists two set of ECDSA key pairs:
67-
- A key pair for signatures from which you can recover the public key, specifically: `K1.ECDSA.Recoverable.PrivateKey` and `K1.ECDSA.Recoverable.PublicKey`
68-
- A key pair for signatures from which you can **not** recover the public key, specifically: `K1.ECDSA.NonRecoverable.PrivateKey` and `K1.ECDSA.NonRecoverable.PublicKey`
67+
- A key pair for signatures from which you can recover the public key, specifically: `K1.ECDSAWithKeyRecovery.PrivateKey` and `K1.ECDSAWithKeyRecovery.PublicKey`
68+
- A key pair for signatures from which you can **not** recover the public key, specifically: `K1.ECDSA.PrivateKey` and `K1.ECDSA.PublicKey`
6969

7070
For each private key there exists two different `signature:for:options` (one taking hashed data and taking `Digest` as argument) methods and one `signature:forUnhashed:options`.
7171

@@ -76,7 +76,7 @@ The `option` is a `K1.ECDSA.SigningOptions` struct, which by default specifies [
7676
#### Sign
7777

7878
```swift
79-
let alice = K1.ECDA.NonRecovarable.PrivateKey()
79+
let alice = K1.ECDSA.PrivateKey()
8080
```
8181

8282
##### Hashed (Data)
@@ -109,8 +109,8 @@ let signature = try alice.signature(forUnhashed: message)
109109

110110
```swift
111111
let hashedMessage: Data = // from somewhere
112-
let publicKey: K1.ECDSA.NonRecoverable.PublicKey = alice.publcKey
113-
let signature: K1.ECDSA.NonRecoverable.Signature // from above
112+
let publicKey: K1.ECDSA.PublicKey = alice.publcKey
113+
let signature: K1.ECDSA.Signature // from above
114114

115115
assert(
116116
publicKey.isValidSignature(signature, hashed: hashedMessage)
@@ -122,7 +122,7 @@ assert(
122122
```swift
123123
let message: Data = // from somewhere
124124
let digest = SHA256.hash(data: message)
125-
let signature: K1.ECDSA.NonRecoverable.Signature // from above
125+
let signature: K1.ECDSA.Signature // from above
126126

127127
assert(
128128
publicKey.isValidSignature(signature, digest: digest)
@@ -133,7 +133,7 @@ assert(
133133

134134
```swift
135135
let message: Data = // from somewhere
136-
let signature: K1.ECDSA.NonRecoverable.Signature // from above
136+
let signature: K1.ECDSA.Signature // from above
137137

138138
assert(
139139
publicKey.isValidSignature(signature, unhashed: message)
@@ -146,11 +146,11 @@ assert(
146146
All signing and validation APIs are identical to the `NonRecoverable` namespace.
147147

148148
```swift
149-
let alice = K1.ECDA.Recovarable.PrivateKey()
149+
let alice = K1.ECDSA.PrivateKey()
150150
let message: Data = // from somewhere
151151
let digest = SHA256.hash(data: message)
152-
let signature: K1.ECDSA.Recoverable.Signature = try alice.signature(for: digest)
153-
let publicKey: K1.ECDSA.Recoverable.PublicKey = alice.publicKey
152+
let signature: K1.ECDSAWithKeyRecovery.Signature = try alice.signature(for: digest)
153+
let publicKey: K1.ECDSAWithKeyRecovery.PublicKey = alice.publicKey
154154
assert(
155155
publicKey.isValidSignature(signature, digest: digest)
156156
) // PASS

Sources/K1/K1/ECDSA/ECDSA.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// MARK: - K1.ECDSA
22
extension K1 {
3-
/// A mechanism used to create or verify a cryptographic signature using the `secp256k1` elliptic curve digital signature algorithm (ECDSA).
3+
/// A mechanism used to create or verify a cryptographic signature using the `secp256k1` elliptic curve digital signature algorithm (ECDSA), signatures that do not offer recovery of the public key.
44
public enum ECDSA {}
55
}
66

Sources/K1/K1/ECDSA/ECDSASignatureNonRecoverable.swift

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,12 @@ import protocol CryptoKit.Digest
22
import struct CryptoKit.SHA256
33
import Foundation
44

5-
// MARK: - K1.ECDSA.NonRecoverable
5+
// MARK: - K1.ECDSA.Signature
66
extension K1.ECDSA {
7-
/// A mechanism used to create or verify a cryptographic signature using the `secp256k1` elliptic curve digital signature algorithm (ECDSA), signatures that do not offer recovery of the public key.
8-
public enum NonRecoverable {
9-
// Just a namespace
10-
}
11-
}
12-
13-
// MARK: - K1.ECDSA.NonRecoverable.Signature
14-
extension K1.ECDSA.NonRecoverable {
157
/// A `secp256k1` elliptic curve digital signature algorithm (ECDSA) signature,
168
/// from which users can recover a public key with the message that was signed.
179
public struct Signature: Sendable, Hashable, ContiguousBytes {
18-
typealias Wrapped = FFI.ECDSA.NonRecoverable.Wrapped
10+
typealias Wrapped = FFI.ECDSA.Wrapped
1911
internal let wrapped: Wrapped
2012

2113
init(wrapped: Wrapped) {
@@ -25,12 +17,12 @@ extension K1.ECDSA.NonRecoverable {
2517
}
2618

2719
// MARK: Inits
28-
extension K1.ECDSA.NonRecoverable.Signature {
20+
extension K1.ECDSA.Signature {
2921
/// Creates a `secp256k1` ECDSA signature from a Distinguished Encoding Rules (DER) encoded representation.
3022
/// - Parameter derRepresentation: A DER-encoded representation of the signature.
3123
public init(derRepresentation: some DataProtocol) throws {
3224
try self.init(
33-
wrapped: FFI.ECDSA.NonRecoverable.from(derRepresentation: [UInt8](derRepresentation))
25+
wrapped: FFI.ECDSA.from(derRepresentation: [UInt8](derRepresentation))
3426
)
3527
}
3628

@@ -44,20 +36,20 @@ extension K1.ECDSA.NonRecoverable.Signature {
4436
/// [rfc]: https://tools.ietf.org/html/rfc4754
4537
public init(rawRepresentation: some DataProtocol) throws {
4638
try self.init(
47-
wrapped: FFI.ECDSA.NonRecoverable.from(compactBytes: [UInt8](rawRepresentation))
39+
wrapped: FFI.ECDSA.from(compactBytes: [UInt8](rawRepresentation))
4840
)
4941
}
5042
}
5143

5244
// MARK: ContiguousBytes
53-
extension K1.ECDSA.NonRecoverable.Signature {
45+
extension K1.ECDSA.Signature {
5446
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
5547
try wrapped.withUnsafeBytes(body)
5648
}
5749
}
5850

5951
// MARK: Serialize
60-
extension K1.ECDSA.NonRecoverable.Signature {
52+
extension K1.ECDSA.Signature {
6153
var internalRepresentation: Data {
6254
Data(wrapped.bytes)
6355
}
@@ -68,7 +60,7 @@ extension K1.ECDSA.NonRecoverable.Signature {
6860
/// `libsecp256k1` this representation is called "compact".
6961
public var rawRepresentation: Data {
7062
do {
71-
return try FFI.ECDSA.NonRecoverable.compact(wrapped)
63+
return try FFI.ECDSA.compact(wrapped)
7264
} catch {
7365
fatalError("Should never fail to convert ECDSA signatures to rawRepresentation.")
7466
}
@@ -78,19 +70,19 @@ extension K1.ECDSA.NonRecoverable.Signature {
7870
/// `secp256k1` ECDSA non recoverable signature.
7971
public var derRepresentation: Data {
8072
do {
81-
return try FFI.ECDSA.NonRecoverable.der(wrapped)
73+
return try FFI.ECDSA.der(wrapped)
8274
} catch {
8375
fatalError("Should never fail to convert ECDSA signatures to DER representation.")
8476
}
8577
}
8678
}
8779

88-
extension K1.ECDSA.NonRecoverable.Signature {
89-
internal static let byteCount = FFI.ECDSA.Recoverable.byteCount
80+
extension K1.ECDSA.Signature {
81+
internal static let byteCount = FFI.ECDSAWithKeyRecovery.byteCount
9082
}
9183

9284
// MARK: Equatable
93-
extension K1.ECDSA.NonRecoverable.Signature {
85+
extension K1.ECDSA.Signature {
9486
/// Compares two ECDSA signatures.
9587
public static func == (lhs: Self, rhs: Self) -> Bool {
9688
lhs.wrapped.withUnsafeBytes { lhsBytes in
@@ -102,7 +94,7 @@ extension K1.ECDSA.NonRecoverable.Signature {
10294
}
10395

10496
// MARK: Hashable
105-
extension K1.ECDSA.NonRecoverable.Signature {
97+
extension K1.ECDSA.Signature {
10698
public func hash(into hasher: inout Hasher) {
10799
wrapped.withUnsafeBytes {
108100
hasher.combine(bytes: $0)

Sources/K1/K1/ECDSA/ECDSASignatureRecoverable.swift

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ import protocol CryptoKit.Digest
22
import struct CryptoKit.SHA256
33
import Foundation
44

5-
// MARK: - K1.ECDSA.Recoverable
6-
extension K1.ECDSA {
5+
// MARK: - K1.ECDSAWithKeyRecovery
6+
extension K1 {
77
/// A mechanism used to create or verify a cryptographic signature using the `secp256k1` elliptic curve digital signature algorithm (ECDSA), signatures that do offers recovery of the public key.
8-
public enum Recoverable {
8+
public enum ECDSAWithKeyRecovery {
99
// Just a namespace
1010
}
1111
}
1212

13-
// MARK: - K1.ECDSA.Recoverable.Signature
14-
extension K1.ECDSA.Recoverable {
13+
// MARK: - K1.ECDSAWithKeyRecovery.Signature
14+
extension K1.ECDSAWithKeyRecovery {
1515
/// A `secp256k1` elliptic curve digital signature algorithm (ECDSA) signature,
1616
/// from which users **cannot** recover the public key, not without the `RecoveryID`.
1717
public struct Signature: Sendable, Hashable, ContiguousBytes {
18-
typealias Wrapped = FFI.ECDSA.Recoverable.Wrapped
18+
typealias Wrapped = FFI.ECDSAWithKeyRecovery.Wrapped
1919
internal let wrapped: Wrapped
2020

2121
internal init(wrapped: Wrapped) {
@@ -25,11 +25,11 @@ extension K1.ECDSA.Recoverable {
2525
}
2626

2727
// MARK: Init
28-
extension K1.ECDSA.Recoverable.Signature {
28+
extension K1.ECDSAWithKeyRecovery.Signature {
2929
/// Compact aka `IEEE P1363` aka `R||S`.
3030
public init(compact: Compact) throws {
3131
try self.init(
32-
wrapped: FFI.ECDSA.Recoverable.deserialize(
32+
wrapped: FFI.ECDSAWithKeyRecovery.deserialize(
3333
compact: [UInt8](compact.compact),
3434
recoveryID: compact.recoveryID.recid
3535
)
@@ -40,27 +40,27 @@ extension K1.ECDSA.Recoverable.Signature {
4040
internalRepresentation: some DataProtocol
4141
) throws {
4242
try self.init(
43-
wrapped: FFI.ECDSA.Recoverable.deserialize(rawRepresentation: internalRepresentation)
43+
wrapped: FFI.ECDSAWithKeyRecovery.deserialize(rawRepresentation: internalRepresentation)
4444
)
4545
}
4646
}
4747

4848
// MARK: ContiguousBytes
49-
extension K1.ECDSA.Recoverable.Signature {
49+
extension K1.ECDSAWithKeyRecovery.Signature {
5050
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
5151
try wrapped.withUnsafeBytes(body)
5252
}
5353
}
5454

5555
// MARK: Serialize
56-
extension K1.ECDSA.Recoverable.Signature {
56+
extension K1.ECDSAWithKeyRecovery.Signature {
5757
internal var internalRepresentation: Data {
5858
Data(wrapped.bytes)
5959
}
6060

6161
/// Compact aka `IEEE P1363` aka `R||S` and `V` (`RecoveryID`).
6262
public func compact() throws -> Compact {
63-
let (rs, recid) = try FFI.ECDSA.Recoverable.serializeCompact(
63+
let (rs, recid) = try FFI.ECDSAWithKeyRecovery.serializeCompact(
6464
wrapped
6565
)
6666
return try .init(
@@ -92,7 +92,7 @@ extension K1.ECDSA.Recoverable.Signature {
9292
}
9393
}
9494

95-
extension K1.ECDSA.Recoverable.Signature.Compact {
95+
extension K1.ECDSAWithKeyRecovery.Signature.Compact {
9696
public static let byteCountRS = 2 * Curve.Field.byteCount
9797
public static let byteCount = Self.byteCountRS + 1
9898

@@ -162,7 +162,7 @@ extension K1.ECDSA.Recoverable.Signature.Compact {
162162
}
163163
}
164164

165-
extension K1.ECDSA.Recoverable.Signature.RecoveryID {
165+
extension K1.ECDSAWithKeyRecovery.Signature.RecoveryID {
166166
var vData: Data {
167167
Data(
168168
[UInt8(rawValue)]
@@ -171,7 +171,7 @@ extension K1.ECDSA.Recoverable.Signature.RecoveryID {
171171
}
172172

173173
// MARK: Recovery
174-
extension K1.ECDSA.Recoverable.Signature {
174+
extension K1.ECDSAWithKeyRecovery.Signature {
175175
/// Recovers a public key from a `secp256k1` this ECDSA signature and the message signed.
176176
///
177177
/// - Parameters:
@@ -180,27 +180,27 @@ extension K1.ECDSA.Recoverable.Signature {
180180
/// signature by signing the `message`.
181181
public func recoverPublicKey(
182182
message: some DataProtocol
183-
) throws -> K1.ECDSA.Recoverable.PublicKey {
184-
let wrapped = try FFI.ECDSA.Recoverable.recover(wrapped, message: [UInt8](message))
183+
) throws -> K1.ECDSAWithKeyRecovery.PublicKey {
184+
let wrapped = try FFI.ECDSAWithKeyRecovery.recover(wrapped, message: [UInt8](message))
185185
let impl = K1._PublicKeyImplementation(wrapped: wrapped)
186-
return K1.ECDSA.Recoverable.PublicKey(
186+
return K1.ECDSAWithKeyRecovery.PublicKey(
187187
impl: impl
188188
)
189189
}
190190
}
191191

192192
// MARK: Conversion
193-
extension K1.ECDSA.Recoverable.Signature {
193+
extension K1.ECDSAWithKeyRecovery.Signature {
194194
/// Converts this recoverable ECDSA signature to a non-recoverable version.
195-
public func nonRecoverable() throws -> K1.ECDSA.NonRecoverable.Signature {
196-
try K1.ECDSA.NonRecoverable.Signature(
197-
wrapped: FFI.ECDSA.Recoverable.nonRecoverable(self.wrapped)
195+
public func nonRecoverable() throws -> K1.ECDSA.Signature {
196+
try K1.ECDSA.Signature(
197+
wrapped: FFI.ECDSAWithKeyRecovery.nonRecoverable(self.wrapped)
198198
)
199199
}
200200
}
201201

202202
// MARK: Equatable
203-
extension K1.ECDSA.Recoverable.Signature {
203+
extension K1.ECDSAWithKeyRecovery.Signature {
204204
/// Compares two ECDSA signatures.
205205
public static func == (lhs: Self, rhs: Self) -> Bool {
206206
lhs.wrapped.withUnsafeBytes { lhsBytes in
@@ -212,7 +212,7 @@ extension K1.ECDSA.Recoverable.Signature {
212212
}
213213

214214
// MARK: Hashable
215-
extension K1.ECDSA.Recoverable.Signature {
215+
extension K1.ECDSAWithKeyRecovery.Signature {
216216
public func hash(into hasher: inout Hasher) {
217217
wrapped.withUnsafeBytes {
218218
hasher.combine(bytes: $0)

Sources/K1/K1/ECDSA/RecoveryID.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Foundation
22

3-
// MARK: - K1.ECDSA.Recoverable.Signature.RecoveryID
4-
extension K1.ECDSA.Recoverable.Signature {
3+
// MARK: - K1.ECDSAWithKeyRecovery.Signature.RecoveryID
4+
extension K1.ECDSAWithKeyRecovery.Signature {
55
public enum RecoveryID: UInt8, Sendable, Hashable, Codable {
66
case _0 = 0
77
case _1 = 1
@@ -14,7 +14,7 @@ extension K1.ECDSA.Recoverable.Signature {
1414
}
1515
}
1616

17-
extension K1.ECDSA.Recoverable.Signature.RecoveryID {
17+
extension K1.ECDSAWithKeyRecovery.Signature.RecoveryID {
1818
public init(byte: UInt8) throws {
1919
guard let self_ = Self(rawValue: byte) else {
2020
throw K1.Error.invalidParameter

0 commit comments

Comments
 (0)