Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API BREAK] Remove recoverPublicKey from K1.ECDSA.NonRecoverable.Signature and remove an init from K1.ECDSA.Recoverable.Signature #36

Merged
merged 2 commits into from
Mar 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 0 additions & 24 deletions Sources/K1/K1/ECDSA/ECDSASignatureNonRecoverable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,30 +85,6 @@ extension K1.ECDSA.NonRecoverable.Signature {
}
}

// MARK: Recover
extension K1.ECDSA.NonRecoverable.Signature {
/// Recovers a public key from a `secp256k1` ECDSA signature, the message signed
/// and a `recoveryID`.
///
/// - Parameters:
/// - recoveryID: The recoveryID produced when a recoverable signature was produced.
/// - message: The message that was signed to produce this ECDSA signature.
/// - Returns: The public key which corresponds to the private key which used to produce this
/// signature by signing the `message`.
public func recoverPublicKey(
recoveryID: K1.ECDSA.Recoverable.Signature.RecoveryID,
message: some DataProtocol
) throws -> K1.ECDSA.NonRecoverable.PublicKey {
let wrapped = try FFI.ECDSA.NonRecoverable.recoverPublicKey(
self.wrapped,
recoveryID: recoveryID.recid,
message: [UInt8](message)
)
let impl = K1._PublicKeyImplementation(wrapped: wrapped)
return K1.ECDSA.NonRecoverable.PublicKey(impl: impl)
}
}

extension K1.ECDSA.NonRecoverable.Signature {
internal static let byteCount = FFI.ECDSA.Recoverable.byteCount
}
Expand Down
29 changes: 20 additions & 9 deletions Sources/K1/K1/ECDSA/ECDSASignatureRecoverable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ extension K1.ECDSA.Recoverable.Signature {
)
}

/// Compact aka `IEEE P1363` aka `R||S`.
public init(compact: Data, recoveryID: RecoveryID) throws {
try self.init(compact: .init(compact: compact, recoveryID: recoveryID))
}

init(
internalRepresentation: some DataProtocol
) throws {
Expand All @@ -63,7 +58,7 @@ extension K1.ECDSA.Recoverable.Signature {
Data(wrapped.bytes)
}

/// Compact aka `IEEE P1363` aka `R||S` with `RecoveryID`
/// Compact aka `IEEE P1363` aka `R||S` and `V` (`RecoveryID`).
public func compact() throws -> Compact {
let (rs, recid) = try FFI.ECDSA.Recoverable.serializeCompact(
wrapped
Expand All @@ -74,7 +69,9 @@ extension K1.ECDSA.Recoverable.Signature {
)
}

/// A tuple of `R||S` and `recoveryID` from a recoverable ECDSA signature.
/// A tuple of `R||S` and `V` (`RecoveryID`) from a recoverable ECDSA signature.
///
/// Can be serialized into data using `serialize:format` method.
public struct Compact: Sendable, Hashable {
/// Compact aka `IEEE P1363` aka `R||S`.
public let compact: Data
Expand All @@ -99,7 +96,10 @@ extension K1.ECDSA.Recoverable.Signature.Compact {
public static let byteCountRS = 2 * Curve.Field.byteCount
public static let byteCount = Self.byteCountRS + 1

/// Takes either `R || S || V` data or `V || R || S` data, as per specification of `format`.
/// Creates a compact recoverable ECDSA signature from a `rawRepresentation` on `format`,
/// either `R || S || V` or `V || R || S`.
///
/// You can initialize a `K1.ECDSA.Recoverable.Signature` by using the `init:compact` initializer.
public init(
rawRepresentation: some DataProtocol,
format: SerializationFormat
Expand All @@ -121,6 +121,11 @@ extension K1.ECDSA.Recoverable.Signature.Compact {
}
}

/// A serialization format of a `K1.ECDSA.Recoverable.Signature.Compact`, use to
/// deserialize data into such a type, or used to serialize from that type into data.
///
/// Controls the order of the three components `R`, `S` and `V` (`RecoveryID`), specifyin
/// either `R || S || V` called `.rsv` or `V || R || S` called `vrs`.
public enum SerializationFormat {
/// `R || S || V` - the format `libsecp256k1` v0.3.0 uses as internal representation
/// This is the default value of this library.
Expand All @@ -141,7 +146,13 @@ extension K1.ECDSA.Recoverable.Signature.Compact {
compact
}

func serialize(format: SerializationFormat) -> Data {
/// Serializes this compact recoverable ECDSA signature to Data on either `rsv` or `vsr` according to `format`
///
/// Returns 65 bytes on either format `R || S || V` or `V || R || S`.
///
/// - Parameter format: Specified of order of `R`, `S` and `RecoveryID` (`V`), either `R || S || V` or `V || R || S`.
/// - Returns: Serialized data representation of the signature.
public func serialize(format: SerializationFormat) -> Data {
switch format {
case .rsv:
return rs + v
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ final class ECDASignaturePublicKeyRecoveryTests: XCTestCase {
XCTAssertEqual(compactRecoverableSig.recoveryID, recid)

let compactRecoverableSigRS = try Data(hex: compactRecoverableSigRSHex)
try XCTAssertEqual(K1.ECDSA.Recoverable.Signature(compact: compactRecoverableSigRS, recoveryID: recid), K1.ECDSA.Recoverable.Signature(compact: compactRecoverableSig))
try XCTAssertEqual(K1.ECDSA.Recoverable.Signature(compact: .init(compact: compactRecoverableSigRS, recoveryID: recid)), K1.ECDSA.Recoverable.Signature(compact: compactRecoverableSig))
try XCTAssertEqual(K1.ECDSA.Recoverable.Signature.Compact(compact: compactRecoverableSigRS, recoveryID: recid), compactRecoverableSig)

let nonRecoverable = try K1.ECDSA.NonRecoverable.Signature(rawRepresentation: compactRecoverableSig.compact)
Expand Down Expand Up @@ -89,12 +89,6 @@ private extension ECDASignaturePublicKeyRecoveryTests {

XCTAssertTrue(recoveredPublicKey.isValidSignature(recoverableSig, hashed: hashedMessage))

let recoveredWithID = try recoverableSig.nonRecoverable().recoverPublicKey(
recoveryID: vector.recoveryID,
message: hashedMessage
)
try XCTAssertEqual(expectedPublicKey, .init(x963Representation: recoveredWithID.x963Representation))

numberOfTestsRun += 1
}
return .init(numberOfTestsRun: numberOfTestsRun, idsOmittedTests: [])
Expand Down