diff --git a/Sources/Parser/CompactParser.swift b/Sources/Parser/CompactParser.swift index 4f03ce7..4181e19 100644 --- a/Sources/Parser/CompactParser.swift +++ b/Sources/Parser/CompactParser.swift @@ -27,23 +27,22 @@ public class CompactParser: ParserProtocol { private static let TILDE = "~" - var serialisedString: String var serialisationFormat: SerialisationFormat = .serialised // MARK: - Lifecycle - public required init(serialiserProtocol: SerialiserProtocol) { - self.serialisedString = serialiserProtocol.serialised - } - - public init(serialisedString: String) { - self.serialisedString = serialisedString + public init() { } // MARK: - Methods - public func getSignedSdJwt() throws -> SignedSDJWT { - let (serialisedJWT, disclosuresInBase64, serialisedKBJWT) = try self.parseCombined() + public func getSignedSdJwt(using serialiserProtocol: SerialiserProtocol) throws -> SignedSDJWT { + let serialisedString = serialiserProtocol.serialised + return try getSignedSdJwt(serialisedString: serialisedString) + } + + public func getSignedSdJwt(serialisedString: String) throws -> SignedSDJWT { + let (serialisedJWT, disclosuresInBase64, serialisedKBJWT) = try self.parseCombined(serialisedString) return try SignedSDJWT(serializedJwt: serialisedJWT, disclosures: disclosuresInBase64, serializedKbJwt: serialisedKBJWT) } @@ -88,8 +87,8 @@ public class CompactParser: ParserProtocol { } - private func parseCombined() throws -> (String, [Disclosure], String?) { - let parts = self.serialisedString + private func parseCombined(_ serialisedString: String) throws -> (String, [Disclosure], String?) { + let parts = serialisedString .split(separator: "~") .map {String($0)} diff --git a/Sources/Parser/EnvelopedParser.swift b/Sources/Parser/EnvelopedParser.swift index 2b364c0..de5a75c 100644 --- a/Sources/Parser/EnvelopedParser.swift +++ b/Sources/Parser/EnvelopedParser.swift @@ -18,31 +18,32 @@ import Foundation public class EnvelopedParser: ParserProtocol { // MARK: - Properties + + let compactParser: ParserProtocol + + // MARK: - Lifecycle - var sdJwt: SignedSDJWT + public init( + compactParser: ParserProtocol = CompactParser() + ) { + self.compactParser = compactParser + } - // MARK: - Lifecycle + // MARK: - Methods - public init(serialiserProtocol: SerialiserProtocol) throws { + public func getSignedSdJwt(using serialiserProtocol: any SerialiserProtocol) throws -> SignedSDJWT { let jsonDecoder = JSONDecoder() let envelopedJwt = try jsonDecoder.decode(EnvelopedJwt.self, from: serialiserProtocol.data) - let compactParser = CompactParser(serialisedString: envelopedJwt.sdJwt) - self.sdJwt = try compactParser.getSignedSdJwt() + return try compactParser.getSignedSdJwt(serialisedString: envelopedJwt.sdJwt) } - - public init(data: Data) throws { + + public func getSignedSdJwt(serialisedString: String) throws -> SignedSDJWT { let jsonDecoder = JSONDecoder() - let envelopedJwt = try jsonDecoder.decode(EnvelopedJwt.self, from: data) - let compactParser = CompactParser(serialisedString: envelopedJwt.sdJwt) - self.sdJwt = try compactParser.getSignedSdJwt() + let envelopedJwt = try jsonDecoder.decode( + EnvelopedJwt.self, from: serialisedString.data(using: .utf8) ?? Data() + ) + return try compactParser.getSignedSdJwt(serialisedString: envelopedJwt.sdJwt) } - - // MARK: - Methods - - public func getSignedSdJwt() throws -> SignedSDJWT { - return sdJwt - } - } public struct EnvelopedJwt: Codable { diff --git a/Sources/Parser/ParserProtocol.swift b/Sources/Parser/ParserProtocol.swift index fddddf0..1acda25 100644 --- a/Sources/Parser/ParserProtocol.swift +++ b/Sources/Parser/ParserProtocol.swift @@ -16,15 +16,22 @@ import Foundation public protocol ParserProtocol { - - func getSignedSdJwt() throws -> SignedSDJWT - + // Existing method to support SerialiserProtocol + func getSignedSdJwt(using serialiserProtocol: SerialiserProtocol) throws -> SignedSDJWT + + // New method to support String input + func getSignedSdJwt(serialisedString: String) throws -> SignedSDJWT } struct NoParser: ParserProtocol { + var sdJWT: SignedSDJWT - - func getSignedSdJwt() throws -> SignedSDJWT { + + func getSignedSdJwt(using serialiserProtocol: any SerialiserProtocol) throws -> SignedSDJWT { + return self.sdJWT + } + + func getSignedSdJwt(serialisedString: String) throws -> SignedSDJWT { return self.sdJWT } } diff --git a/Sources/Verifier/DisclosuresVerifier.swift b/Sources/Verifier/DisclosuresVerifier.swift index 136f7d5..e636d10 100644 --- a/Sources/Verifier/DisclosuresVerifier.swift +++ b/Sources/Verifier/DisclosuresVerifier.swift @@ -62,8 +62,8 @@ public class DisclosuresVerifier: VerifierProtocol { recreatedClaims = claimExtractor.recreatedClaims } - convenience init(parser: ParserProtocol) throws { - try self.init(signedSDJWT: try parser.getSignedSdJwt()) + convenience init(parser: ParserProtocol, serialisedString: String) throws { + try self.init(signedSDJWT: try parser.getSignedSdJwt(serialisedString: serialisedString)) } // MARK: - Methods diff --git a/Sources/Verifier/SDJWTVCVerifier.swift b/Sources/Verifier/SDJWTVCVerifier.swift index 680e676..f364e34 100644 --- a/Sources/Verifier/SDJWTVCVerifier.swift +++ b/Sources/Verifier/SDJWTVCVerifier.swift @@ -81,21 +81,27 @@ public class SDJWTVCVerifier: SdJwtVcVerifierType { /// Service for fetching issuer metadata such as public keys. private let fetcher: any SdJwtVcIssuerMetaDataFetching + /// A parser conforming to `ParserProtocol`, responsible for parsing SD-JWTs. + private let parser: ParserProtocol + /** * Initializes the `SDJWTVCVerifier` with dependencies for metadata fetching, certificate trust, and public key lookup. * * - Parameters: + * - parser: A parser responsible for parsing SD-JWTs. * - fetcher: A service responsible for fetching issuer metadata. * - trust: The X.509 trust configuration. * - lookup: Optional service for looking up public keys from DIDs or DID URLs. */ public init( + parser: ParserProtocol = CompactParser(), fetcher: SdJwtVcIssuerMetaDataFetching = SdJwtVcIssuerMetaDataFetcher( session: URLSession.shared ), trust: X509CertificateTrust = X509CertificateTrustFactory.none, lookup: LookupPublicKeysFromDIDDocument? = nil ) { + self.parser = parser self.fetcher = fetcher self.trust = trust self.lookup = lookup @@ -110,8 +116,7 @@ public class SDJWTVCVerifier: SdJwtVcVerifierType { func verifyIssuance( unverifiedSdJwt: String ) async throws -> Result { - let parser = CompactParser(serialisedString: unverifiedSdJwt) - let jws = try parser.getSignedSdJwt().jwt + let jws = try parser.getSignedSdJwt(serialisedString: unverifiedSdJwt).jwt let jwk = try await issuerJwsKeySelector( jws: jws, trust: trust, @@ -121,9 +126,8 @@ public class SDJWTVCVerifier: SdJwtVcVerifierType { switch jwk { case .success(let jwk): return try SDJWTVerifier( - parser: CompactParser( - serialisedString: unverifiedSdJwt - ) + parser: parser, + serialisedString: unverifiedSdJwt ).verifyIssuance { jws in try SignatureVerifier( signedJWT: jws, diff --git a/Sources/Verifier/SDJWTVerifier.swift b/Sources/Verifier/SDJWTVerifier.swift index 6cde786..c4183cd 100644 --- a/Sources/Verifier/SDJWTVerifier.swift +++ b/Sources/Verifier/SDJWTVerifier.swift @@ -41,8 +41,11 @@ public class SDJWTVerifier { /// - parser: A parser conforming to `ParserProtocol`. /// - Throws: An error if the SDJWT cannot be obtained. /// - public init(parser: ParserProtocol) throws { - self.sdJwt = try parser.getSignedSdJwt() + public init( + parser: ParserProtocol = CompactParser(), + serialisedString: String + ) throws { + self.sdJwt = try parser.getSignedSdJwt(serialisedString: serialisedString) } /// Initializes the verifier with a pre-existing SDJWT. diff --git a/Tests/Issuance/SignedJwtTest.swift b/Tests/Issuance/SignedJwtTest.swift index fb4b1d1..8cd0a30 100644 --- a/Tests/Issuance/SignedJwtTest.swift +++ b/Tests/Issuance/SignedJwtTest.swift @@ -48,7 +48,9 @@ final class SignedJwtTest: XCTestCase { CompactSerialiser(signedSDJWT: jwt) } - let verifier = try SDJWTVerifier(parser: CompactParser(serialisedString: serialised)).verifyIssuance { jws in + let verifier = try SDJWTVerifier( + serialisedString: serialised + ).verifyIssuance { jws in try SignatureVerifier(signedJWT: jws, publicKey: keyPair.public) } claimVerifier: { _, _ in ClaimsVerifier() diff --git a/Tests/JSONSerialization/JSONSerializationTest.swift b/Tests/JSONSerialization/JSONSerializationTest.swift index 0cded15..334e717 100644 --- a/Tests/JSONSerialization/JSONSerializationTest.swift +++ b/Tests/JSONSerialization/JSONSerializationTest.swift @@ -31,8 +31,8 @@ final class JSONSerializationTest: XCTestCase { func testSdJWTGeneralSerialization() async throws { // Given - let parser = CompactParser(serialisedString: SDJWTConstants.compactSdJwt) - let sdJwt = try! parser.getSignedSdJwt() + let parser = CompactParser() + let sdJwt = try! parser.getSignedSdJwt(serialisedString: SDJWTConstants.compactSdJwt) // When let json = try sdJwt.asJwsJsonObject( @@ -69,8 +69,8 @@ final class JSONSerializationTest: XCTestCase { func testSdJWTFlattendedSerializationtest() async throws { // Given - let parser = CompactParser(serialisedString: SDJWTConstants.compactSdJwt) - let sdJwt = try! parser.getSignedSdJwt() + let parser = CompactParser() + let sdJwt = try! parser.getSignedSdJwt(serialisedString: SDJWTConstants.compactSdJwt) // When let json = try sdJwt.asJwsJsonObject( diff --git a/Tests/SpecExamples.swift b/Tests/SpecExamples.swift index b9e5376..a03c456 100644 --- a/Tests/SpecExamples.swift +++ b/Tests/SpecExamples.swift @@ -54,7 +54,10 @@ final class SpecExamples: XCTestCase { let string = CompactSerialiser(signedSDJWT: sdjwt).serialised - let disclosureVerifierOut = try DisclosuresVerifier(parser: CompactParser(serialisedString: string)).verify() + let disclosureVerifierOut = try DisclosuresVerifier( + parser: CompactParser(), + serialisedString: string + ).verify() validateObjectResults(factoryResult: output, expectedDigests: disclosureVerifierOut.digestsFoundOnPayload.count, diff --git a/Tests/Verification/SerializerTest.swift b/Tests/Verification/SerializerTest.swift index 233dd79..e8e75bc 100644 --- a/Tests/Verification/SerializerTest.swift +++ b/Tests/Verification/SerializerTest.swift @@ -34,21 +34,24 @@ final class SerialiserTest: XCTestCase { func testPareserWhenReceivingASerialisedFormatJWT_ThenConstructUnsignedSDJWT() throws { let serialisedString = try testSerializerWhenSerializedFormatIsSelected_ThenExpectSerialisedFormattedSignedSDJWT() - let parser = CompactParser(serialisedString: serialisedString) - let jwt = try parser.getSignedSdJwt().toSDJWT() + let parser = CompactParser() + let jwt = try parser.getSignedSdJwt(serialisedString: serialisedString).toSDJWT() print(jwt.disclosures) } func testSerialiseWhenChosingEnvelopeFormat_AppylingNoKeyBinding_ThenExpectACorrectJWT() throws { - let compactParser = try CompactParser(serialisedString: testSerializerWhenSerializedFormatIsSelected_ThenExpectSerialisedFormattedSignedSDJWT()) - + let compactParser = CompactParser() let envelopeSerializer = try EnvelopedSerialiser( - SDJWT: compactParser.getSignedSdJwt(), + SDJWT: compactParser.getSignedSdJwt( + serialisedString: testSerializerWhenSerializedFormatIsSelected_ThenExpectSerialisedFormattedSignedSDJWT() + ), jwTpayload: JWTBody(nonce: "", aud: "sub", iat: 1234).toJSONData()) - let parser = try EnvelopedParser(serialiserProtocol: envelopeSerializer) - - let verifier = try SDJWTVerifier(parser: parser).verifyIssuance { jws in + let parser = EnvelopedParser() + let verifier = try SDJWTVerifier( + parser: parser, + serialisedString: envelopeSerializer.serialised + ).verifyIssuance { jws in try SignatureVerifier(signedJWT: jws, publicKey: issuersKeyPair.public) } claimVerifier: { _, _ in ClaimsVerifier() diff --git a/Tests/Verification/VcVerifierTest.swift b/Tests/Verification/VcVerifierTest.swift index 0bac520..81cdb06 100644 --- a/Tests/Verification/VcVerifierTest.swift +++ b/Tests/Verification/VcVerifierTest.swift @@ -91,8 +91,8 @@ final class VcVerifierTest: XCTestCase { // Given let sdJwtString = SDJWTConstants.x509_sd_jwt.clean() - let parser = CompactParser(serialisedString: sdJwtString) - let sdJwt = try! parser.getSignedSdJwt() + let parser = CompactParser() + let sdJwt = try! parser.getSignedSdJwt(serialisedString: sdJwtString) // When let json = try sdJwt.asJwsJsonObject( @@ -116,8 +116,8 @@ final class VcVerifierTest: XCTestCase { // Given let sdJwtString = SDJWTConstants.x509_sd_jwt.clean() - let parser = CompactParser(serialisedString: sdJwtString) - let sdJwt = try! parser.getSignedSdJwt() + let parser = CompactParser() + let sdJwt = try! parser.getSignedSdJwt(serialisedString: sdJwtString) // When let json = try sdJwt.asJwsJsonObject( @@ -141,8 +141,8 @@ final class VcVerifierTest: XCTestCase { // Given let sdJwtString = SDJWTConstants.issuer_metadata_sd_jwt.clean() - let parser = CompactParser(serialisedString: sdJwtString) - let sdJwt = try! parser.getSignedSdJwt() + let parser = CompactParser() + let sdJwt = try! parser.getSignedSdJwt(serialisedString: sdJwtString) // When let json = try sdJwt.asJwsJsonObject( diff --git a/Tests/Verification/VerifierTest.swift b/Tests/Verification/VerifierTest.swift index a169658..412abab 100644 --- a/Tests/Verification/VerifierTest.swift +++ b/Tests/Verification/VerifierTest.swift @@ -61,7 +61,10 @@ final class VerifierTest: XCTestCase { AiV2VpZGVuc3RyYVx1MDBkZmUgMjIifV0~ """.clean() - let result = try SDJWTVerifier(parser: CompactParser(serialisedString: complexStructureSDJWTString)) + let result = try SDJWTVerifier( + parser: CompactParser(), + serialisedString: complexStructureSDJWTString + ) .verifyIssuance { jws in try SignatureVerifier(signedJWT: jws, publicKey: pk) } claimVerifier: { _, _ in @@ -70,8 +73,8 @@ final class VerifierTest: XCTestCase { XCTAssertNoThrow(try result.get()) - let recreatedClaimsResult = try CompactParser(serialisedString: complexStructureSDJWTString) - .getSignedSdJwt() + let recreatedClaimsResult = try CompactParser() + .getSignedSdJwt(serialisedString: complexStructureSDJWTString) .recreateClaims() XCTAssertTrue(recreatedClaimsResult.recreatedClaims.exists()) @@ -138,10 +141,12 @@ final class VerifierTest: XCTestCase { """ .clean() - let result = try SDJWTVerifier(parser: CompactParser(serialisedString: ComplexStructureSDJWTString)) - .unsingedVerify { signedSDJWT in - try DisclosuresVerifier(signedSDJWT: signedSDJWT) - } + let result = try SDJWTVerifier( + parser: CompactParser(), + serialisedString: ComplexStructureSDJWTString + ).unsingedVerify { signedSDJWT in + try DisclosuresVerifier(signedSDJWT: signedSDJWT) + } XCTAssertNoThrow(try result.get()) } @@ -337,10 +342,12 @@ final class VerifierTest: XCTestCase { func testSerialiseWhenChosingEnvelopeFormat_AppylingEnvelopeBinding_ThenExpectACorrectJWT() throws { let serializerTest = SerialiserTest() - let compactParser = try CompactParser(serialisedString: serializerTest.testSerializerWhenSerializedFormatIsSelected_ThenExpectSerialisedFormattedSignedSDJWT()) + let compactParser = CompactParser() let envelopeSerializer = try EnvelopedSerialiser( - SDJWT: compactParser.getSignedSdJwt(), + SDJWT: compactParser.getSignedSdJwt( + serialisedString: serializerTest.testSerializerWhenSerializedFormatIsSelected_ThenExpectSerialisedFormattedSignedSDJWT() + ), jwTpayload: JWTBody(nonce: "", aud: "sub", iat: 1234 ).toJSONData()) @@ -361,7 +368,10 @@ final class VerifierTest: XCTestCase { let envelopedJws = try JWS(jwsString: jwt.compactSerialization) let verifyEnvelope = - try SDJWTVerifier(parser: EnvelopedParser(data: envelopeSerializer.data)) + try SDJWTVerifier( + parser: EnvelopedParser(), + serialisedString: envelopeSerializer.serialised + ) .verifyEnvelope(envelope: envelopedJws) { jws in try SignatureVerifier(signedJWT: jws, publicKey: issuersKeyPair.public)