diff --git a/Sources/Crypto/Key Agreement/ECDH.swift b/Sources/Crypto/Key Agreement/ECDH.swift index a93126e1..9108f0f7 100644 --- a/Sources/Crypto/Key Agreement/ECDH.swift +++ b/Sources/Crypto/Key Agreement/ECDH.swift @@ -132,6 +132,14 @@ extension P256 { let pemDocument = ASN1.PEMDocument(type: "PUBLIC KEY", derBytes: self.derRepresentation) return pemDocument.pemString } + + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.rawRepresentation == rhs.rawRepresentation + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(rawRepresentation) + } } /// A P-256 private key used to create cryptographic signatures. @@ -347,6 +355,14 @@ extension P256 { let pemDocument = ASN1.PEMDocument(type: "PUBLIC KEY", derBytes: self.derRepresentation) return pemDocument.pemString } + + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.rawRepresentation == rhs.rawRepresentation + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(rawRepresentation) + } } /// A P-256 private key used for key agreement. @@ -561,6 +577,14 @@ extension P384 { let pemDocument = ASN1.PEMDocument(type: "PUBLIC KEY", derBytes: self.derRepresentation) return pemDocument.pemString } + + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.rawRepresentation == rhs.rawRepresentation + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(rawRepresentation) + } } /// A P-384 private key used to create cryptographic signatures. @@ -776,6 +800,14 @@ extension P384 { let pemDocument = ASN1.PEMDocument(type: "PUBLIC KEY", derBytes: self.derRepresentation) return pemDocument.pemString } + + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.rawRepresentation == rhs.rawRepresentation + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(rawRepresentation) + } } /// A P-384 private key used for key agreement. @@ -990,6 +1022,14 @@ extension P521 { let pemDocument = ASN1.PEMDocument(type: "PUBLIC KEY", derBytes: self.derRepresentation) return pemDocument.pemString } + + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.rawRepresentation == rhs.rawRepresentation + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(rawRepresentation) + } } /// A P-521 private key used to create cryptographic signatures. @@ -1205,6 +1245,14 @@ extension P521 { let pemDocument = ASN1.PEMDocument(type: "PUBLIC KEY", derBytes: self.derRepresentation) return pemDocument.pemString } + + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.rawRepresentation == rhs.rawRepresentation + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(rawRepresentation) + } } /// A P-521 private key used for key agreement. diff --git a/Sources/Crypto/Key Agreement/ECDH.swift.gyb b/Sources/Crypto/Key Agreement/ECDH.swift.gyb index 7dd4d437..0092b55f 100644 --- a/Sources/Crypto/Key Agreement/ECDH.swift.gyb +++ b/Sources/Crypto/Key Agreement/ECDH.swift.gyb @@ -151,6 +151,14 @@ extension ${CURVE} { let pemDocument = ASN1.PEMDocument(type: "PUBLIC KEY", derBytes: self.derRepresentation) return pemDocument.pemString } + + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.rawRepresentation == rhs.rawRepresentation + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(rawRepresentation) + } } % if FUNC == "Signing": diff --git a/Sources/Crypto/Keys/EC/NISTCurvesKeys.swift b/Sources/Crypto/Keys/EC/NISTCurvesKeys.swift index e6129404..8ab7dd6d 100644 --- a/Sources/Crypto/Keys/EC/NISTCurvesKeys.swift +++ b/Sources/Crypto/Keys/EC/NISTCurvesKeys.swift @@ -32,7 +32,7 @@ protocol ECPrivateKey { var publicKey: PK { get } } -protocol NISTECPublicKey: ECPublicKey { +protocol NISTECPublicKey: ECPublicKey, Hashable { init(compactRepresentation: Bytes) throws init(compressedRepresentation: Bytes) throws init(x963Representation: Bytes) throws diff --git a/Tests/CryptoTests/Signatures/ECDSA/ECDSASignatureTests.swift b/Tests/CryptoTests/Signatures/ECDSA/ECDSASignatureTests.swift index 4a6c8cb6..7688c7dc 100644 --- a/Tests/CryptoTests/Signatures/ECDSA/ECDSASignatureTests.swift +++ b/Tests/CryptoTests/Signatures/ECDSA/ECDSASignatureTests.swift @@ -398,6 +398,138 @@ class SignatureTests: XCTestCase { let compressedX963Positive = Data(base64Encoded: "A+QHCXtGd5WWSQgp37FBPXMy+nnSwFK79QQD0ZeNMv7L")! XCTAssertThrowsError(try P256.Signing.PublicKey(x963Representation: compressedX963Positive)) } - + + func testP256SigningPublicKeyEquatable() throws { + // Equality + let publicKey = P256.Signing.PrivateKey().publicKey + XCTAssertEqual(publicKey, publicKey) + + // Inequality + for _ in 0..<32 { + XCTAssertNotEqual( + publicKey, + P256.Signing.PrivateKey().publicKey + ) + } + } + + func testP256KeyAgreementPublicKeyEquatable() throws { + // Equality + let publicKey = P256.KeyAgreement.PrivateKey().publicKey + XCTAssertEqual(publicKey, publicKey) + + // Inequality + for _ in 0..<32 { + XCTAssertNotEqual( + publicKey, + P256.KeyAgreement.PrivateKey().publicKey + ) + } + } + + func testP384SigningPublicKeyEquatable() throws { + // Equality + let publicKey = P384.Signing.PrivateKey().publicKey + XCTAssertEqual(publicKey, publicKey) + + // Inequality + for _ in 0..<32 { + XCTAssertNotEqual( + publicKey, + P384.Signing.PrivateKey().publicKey + ) + } + } + + func testP384KeyAgreementPublicKeyEquatable() throws { + // Equality + let publicKey = P384.KeyAgreement.PrivateKey().publicKey + XCTAssertEqual(publicKey, publicKey) + + // Inequality + for _ in 0..<32 { + XCTAssertNotEqual( + publicKey, + P384.KeyAgreement.PrivateKey().publicKey + ) + } + } + + func testP521SigningPublicKeyEquatable() throws { + // Equality + let publicKey = P521.Signing.PrivateKey().publicKey + XCTAssertEqual(publicKey, publicKey) + + // Inequality + for _ in 0..<32 { + XCTAssertNotEqual( + publicKey, + P521.Signing.PrivateKey().publicKey + ) + } + } + + func testP521KeyAgreementPublicKeyEquatable() throws { + // Equality + let publicKey = P521.KeyAgreement.PrivateKey().publicKey + XCTAssertEqual(publicKey, publicKey) + + // Inequality + for _ in 0..<32 { + XCTAssertNotEqual( + publicKey, + P521.KeyAgreement.PrivateKey().publicKey + ) + } + } + + func testP256SigningPublicKeyHashable() throws { + let expectedCount = 64 + let set = Set((0..