@@ -890,6 +890,41 @@ final class WireCoreCryptoTests: XCTestCase {
890890 XCTAssertNotNil ( acquisition)
891891 }
892892
893+ func testParseJwkProducesSenderUsableInCreateConversation( ) async throws {
894+ let jwk = generateEd25519Jwk ( )
895+ let externalSender = try ExternalSender . parseJwk ( jwk: jwk)
896+ let alice = try await createClients ( " alice1 " ) [ 0 ]
897+ let conversationId = ConversationId ( bytes: Data ( " ext-sender-jwk " . utf8) )
898+
899+ let retrievedKey = try await alice. transaction { ctx -> ExternalSenderKey in
900+ let credentialRef = try await ctx. findCredentials (
901+ clientId: nil , publicKey: nil , ciphersuite: nil ,
902+ credentialType: nil , earliestValidity: nil
903+ ) . first!
904+ try await ctx. createConversation (
905+ conversationId: conversationId,
906+ credentialRef: credentialRef,
907+ externalSender: externalSender
908+ )
909+ return try await ctx. getExternalSender ( conversationId: conversationId)
910+ }
911+
912+ XCTAssertEqual ( retrievedKey. copyBytes ( ) , externalSender. serialize ( ) )
913+ }
914+
915+ func testParsePublicKeyAcceptsBytesProducedBySerialize( ) throws {
916+ let fromJwk = try ExternalSender . parseJwk ( jwk: generateEd25519Jwk ( ) )
917+ let fromBytes = try ExternalSender . parsePublicKey (
918+ key: fromJwk. serialize ( ) ,
919+ signatureScheme: . ed25519
920+ )
921+ XCTAssertEqual ( fromJwk, fromBytes)
922+ }
923+
924+ func testParseJwkRejectsMalformedBytes( ) {
925+ XCTAssertThrowsError ( try ExternalSender . parseJwk ( jwk: Data ( [ 0 , 1 , 2 , 3 ] ) ) )
926+ }
927+
893928 // MARK: - helpers
894929
895930 final actor MockMlsTransport : MlsTransport {
@@ -993,6 +1028,12 @@ final class WireCoreCryptoTests: XCTestCase {
9931028 ClientId ( bytes: withUnsafeBytes ( of: UUID ( ) . uuid) { Data ( $0) } )
9941029 }
9951030
1031+ private func generateEd25519Jwk( ) -> Data {
1032+ let base64PublicKey = Curve25519 . Signing. PrivateKey ( ) . publicKey. rawRepresentation
1033+ . base64URLEncodedString ( )
1034+ return Data ( #"{"kty":"OKP","crv":"Ed25519","x":" \#( base64PublicKey) "}"# . utf8)
1035+ }
1036+
9961037 // swift-format-ignore: AlwaysUseLowerCamelCase
9971038 /// Assert that an error is thrown when a block is performed.
9981039 ///
@@ -1096,4 +1137,11 @@ extension Data {
10961137 guard hex. count / bytes. count == 2 else { return nil }
10971138 self . init ( bytes)
10981139 }
1140+
1141+ func base64URLEncodedString( ) -> String {
1142+ base64EncodedString ( )
1143+ . replacingOccurrences ( of: " + " , with: " - " )
1144+ . replacingOccurrences ( of: " / " , with: " _ " )
1145+ . replacingOccurrences ( of: " = " , with: " " )
1146+ }
10991147}
0 commit comments