diff --git a/Sources/Crypto/Keys/EC/Ed25519.swift b/Sources/Crypto/Keys/EC/Ed25519.swift index 14d11ca23..f8ed8d5db 100644 --- a/Sources/Crypto/Keys/EC/Ed25519.swift +++ b/Sources/Crypto/Keys/EC/Ed25519.swift @@ -57,7 +57,7 @@ extension Curve25519 { } } - public struct PublicKey { + public struct PublicKey: Equatable { private var baseKey: Curve25519.Signing.Curve25519PublicKeyImpl public init(rawRepresentation: D) throws { @@ -75,6 +75,10 @@ extension Curve25519 { var keyBytes: [UInt8] { return self.baseKey.keyBytes } + + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.rawRepresentation == rhs.rawRepresentation + } } } } diff --git a/Sources/Crypto/Keys/EC/X25519Keys.swift b/Sources/Crypto/Keys/EC/X25519Keys.swift index 250eec355..acdc3a40d 100644 --- a/Sources/Crypto/Keys/EC/X25519Keys.swift +++ b/Sources/Crypto/Keys/EC/X25519Keys.swift @@ -26,7 +26,7 @@ extension Curve25519 { typealias Curve25519PublicKeyImpl = Curve25519.KeyAgreement.OpenSSLCurve25519PublicKeyImpl #endif - public struct PublicKey: ECPublicKey { + public struct PublicKey: ECPublicKey, Equatable { fileprivate var baseKey: Curve25519PublicKeyImpl /// Initializes a Curve25519 Key for Key Agreement. @@ -54,6 +54,10 @@ extension Curve25519 { private func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R { return try self.baseKey.keyBytes.withUnsafeBytes(body) } + + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.rawRepresentation == rhs.rawRepresentation + } } public struct PrivateKey: ECPrivateKey, DiffieHellmanKeyAgreement { diff --git a/Tests/CryptoTests/Signatures/EdDSA/EdDSATests.swift b/Tests/CryptoTests/Signatures/EdDSA/EdDSATests.swift index 233e30146..75ed69e76 100644 --- a/Tests/CryptoTests/Signatures/EdDSA/EdDSATests.swift +++ b/Tests/CryptoTests/Signatures/EdDSA/EdDSATests.swift @@ -75,4 +75,39 @@ class EdDSATests: XCTestCase { // This signature should be invalid XCTAssertFalse(privateKey.publicKey.isValidSignature(DispatchData.empty, for: DispatchData.empty)) } + + func testCurve25519SigningPublicKeyEquatable() throws { + // Equality + let publicKey = Curve25519.Signing.PrivateKey().publicKey + XCTAssertEqual(publicKey, publicKey) + + // Inequality + + // The probability of this inequality check loop + // accidentally failing is... 1/2^246, i.e. low. + for _ in 0..<1024 { + XCTAssertNotEqual( + publicKey, + Curve25519.Signing.PrivateKey().publicKey + ) + } + + } + + func testCurve25519KeyAgreementPublicKeyEquatable() throws { + // Equality + let publicKey = Curve25519.KeyAgreement.PrivateKey().publicKey + XCTAssertEqual(publicKey, publicKey) + + // Inequality + + // The probability of this inequality check loop + // accidentally failing is... 1/2^246, i.e. low. + for _ in 0..<1024 { + XCTAssertNotEqual( + publicKey, + Curve25519.KeyAgreement.PrivateKey().publicKey + ) + } + } }