From 82ee070f6b6de6eff77f1932e41b70d3cfae1af5 Mon Sep 17 00:00:00 2001 From: dtsiflit Date: Tue, 8 Oct 2024 09:43:45 +0300 Subject: [PATCH] [fix] new unit test for vc uses dsl --- Sources/Issuer/SDJWTIssuer.swift | 2 - ...gMock.swift => NetworkingBundleMock.swift} | 37 +++++- Tests/Verification/VcVerifierTest.swift | 123 +++++++++++++++--- 3 files changed, 143 insertions(+), 19 deletions(-) rename Tests/Mocks/{NetworkingMock.swift => NetworkingBundleMock.swift} (67%) diff --git a/Sources/Issuer/SDJWTIssuer.swift b/Sources/Issuer/SDJWTIssuer.swift index c6e7c1e..94d0806 100644 --- a/Sources/Issuer/SDJWTIssuer.swift +++ b/Sources/Issuer/SDJWTIssuer.swift @@ -114,14 +114,12 @@ public class SDJWTIssuer { kbJWT: nil ) return try createSignedSDJWT(sdJwt: ungsingedSDJWT, issuersPrivateKey: signingKey) - // .......... case .presentation(let signedJWT, let selectedDisclosures, let KBJWT): let signedJWT = signedJWT.disclosuresToPresent(disclosures: selectedDisclosures) if let KBJWT { return try createKeyBondedSDJWT(signedSDJWT: signedJWT, kbJWT: KBJWT, holdersPrivateKey: signingKey) } return signedJWT - // .......... } } diff --git a/Tests/Mocks/NetworkingMock.swift b/Tests/Mocks/NetworkingBundleMock.swift similarity index 67% rename from Tests/Mocks/NetworkingMock.swift rename to Tests/Mocks/NetworkingBundleMock.swift index af073cf..7517dad 100644 --- a/Tests/Mocks/NetworkingMock.swift +++ b/Tests/Mocks/NetworkingBundleMock.swift @@ -14,11 +14,13 @@ * limitations under the License. */ import Foundation +import SwiftyJSON + import XCTest @testable import eudi_lib_sdjwt_swift -class NetworkingMock: Networking { +class NetworkingBundleMock: Networking { let path: String let `extension`: String @@ -56,3 +58,36 @@ class NetworkingMock: Networking { return try await data(from: URL(string: "https://www.example.com")!) } } + +class NetworkingJSONMock: Networking { + + let json: JSON + let statusCode: Int + + init( + json: JSON, + statusCode: Int = 200 + ) { + self.json = json + self.statusCode = statusCode + } + + func data( + from url: URL + ) async throws -> (Data, URLResponse) { + let result = Result.success(try self.json.rawData()) + let response = HTTPURLResponse( + url: .stub(), + statusCode: statusCode, + httpVersion: nil, + headerFields: [:] + ) + return try (result.get(), response!) + } + + func data( + for request: URLRequest + ) async throws -> (Data, URLResponse) { + return try await data(from: URL(string: "https://www.example.com")!) + } +} diff --git a/Tests/Verification/VcVerifierTest.swift b/Tests/Verification/VcVerifierTest.swift index 76a88d2..b838649 100644 --- a/Tests/Verification/VcVerifierTest.swift +++ b/Tests/Verification/VcVerifierTest.swift @@ -39,8 +39,7 @@ final class VcVerifierTest: XCTestCase { // When let result = try await SDJWTVCVerifier( trust: X509CertificateChainVerifier() - ) - .verifyIssuance( + ).verifyIssuance( unverifiedSdJwt: sdJwtString ) @@ -56,13 +55,12 @@ final class VcVerifierTest: XCTestCase { // When let result = try await SDJWTVCVerifier( fetcher: SdJwtVcIssuerMetaDataFetcher( - session: NetworkingMock( + session: NetworkingBundleMock( path: "issuer_meta_data", extension: "json" ) ) - ) - .verifyIssuance( + ).verifyIssuance( unverifiedSdJwt: sdJwtString ) @@ -78,8 +76,7 @@ final class VcVerifierTest: XCTestCase { // When let result = try await SDJWTVCVerifier( lookup: LookupPublicKeysFromDIDDocumentMock() - ) - .verifyIssuance( + ).verifyIssuance( unverifiedSdJwt: sdJwtString ) @@ -103,8 +100,7 @@ final class VcVerifierTest: XCTestCase { let result = try await SDJWTVCVerifier( trust: X509CertificateChainVerifier() - ) - .verifyIssuance( + ).verifyIssuance( unverifiedSdJwt: json ) @@ -128,8 +124,7 @@ final class VcVerifierTest: XCTestCase { let result = try await SDJWTVCVerifier( trust: X509CertificateChainVerifier() - ) - .verifyIssuance( + ).verifyIssuance( unverifiedSdJwt: json ) @@ -153,13 +148,12 @@ final class VcVerifierTest: XCTestCase { let result = try await SDJWTVCVerifier( fetcher: SdJwtVcIssuerMetaDataFetcher( - session: NetworkingMock( + session: NetworkingBundleMock( path: "issuer_meta_data", extension: "json" ) ) - ) - .verifyIssuance( + ).verifyIssuance( unverifiedSdJwt: json ) @@ -175,7 +169,7 @@ final class VcVerifierTest: XCTestCase { // When let result = try await SDJWTVCVerifier( fetcher: SdJwtVcIssuerMetaDataFetcher( - session: NetworkingMock( + session: NetworkingBundleMock( path: "issuer_meta_data", extension: "json" ) @@ -206,7 +200,7 @@ final class VcVerifierTest: XCTestCase { let result = try await SDJWTVCVerifier( fetcher: SdJwtVcIssuerMetaDataFetcher( - session: NetworkingMock( + session: NetworkingBundleMock( path: "issuer_meta_data", extension: "json" ) @@ -220,4 +214,101 @@ final class VcVerifierTest: XCTestCase { // Then XCTAssertNoThrow(try result.get()) } + + func testVerifyPresentation_WithDSLBuiltValidSDJWT_WithIssuerMetaData_Presentation_ShouldSucceed() async throws { + + let issuersKey = issuersKeyPair.public + let issuerJwk = try issuersKey.jwk + + let holdersKey = holdersKeyPair.public + let holdersJwk = try holdersKey.jwk + + let jsonObject: JSON = [ + "issuer": "https://example.com/issuer", + "jwks": [ + "keys": [ + [ + "crv": "P-256", + "kid": "Ao50Swzv_uWu805LcuaTTysu_6GwoqnvJh9rnc44U48", + "kty": "EC", + "x": issuerJwk.x?.base64URLEncode(), + "y": issuerJwk.y?.base64URLEncode() + ] + ] + ] + ] + + let issuerSignedSDJWT = try SDJWTIssuer.issue( + issuersPrivateKey: issuersKeyPair.private, + header: DefaultJWSHeaderImpl( + algorithm: .ES256, + keyID: "Ao50Swzv_uWu805LcuaTTysu_6GwoqnvJh9rnc44U48" + ) + ) { + ConstantClaims.iat(time: Date()) + ConstantClaims.exp(time: Date() + 3600) + ConstantClaims.iss(domain: "https://example.com/issuer") + FlatDisclosedClaim("sub", "6c5c0a49-b589-431d-bae7-219122a9ec2c") + FlatDisclosedClaim("given_name", "太郎") + FlatDisclosedClaim("family_name", "山田") + FlatDisclosedClaim("email", "\"unusual email address\"@example.jp") + FlatDisclosedClaim("phone_number", "+81-80-1234-5678") + ObjectClaim("address") { + FlatDisclosedClaim("street_address", "東京都港区芝公園4丁目2−8") + FlatDisclosedClaim("locality", "東京都") + FlatDisclosedClaim("region", "港区") + FlatDisclosedClaim("country", "JP") + } + FlatDisclosedClaim("birthdate", "1940-01-01") + ObjectClaim("cnf") { + ObjectClaim("jwk") { + PlainClaim("kid", "Ao50Swzv_uWu805LcuaTTysu_6GwoqnvJh9rnc44U48") + PlainClaim("kty", "EC") + PlainClaim("y", holdersJwk.y!.base64URLEncode()) + PlainClaim("x", holdersJwk.x!.base64URLEncode()) + PlainClaim("crv", "P-256") + } + } + } + + let sdHash = DigestCreator() + .hashAndBase64Encode( + input: CompactSerialiser( + signedSDJWT: issuerSignedSDJWT + ).serialised + )! + + let holder = try SDJWTIssuer + .presentation( + holdersPrivateKey: holdersKeyPair.private, + signedSDJWT: issuerSignedSDJWT, + disclosuresToPresent: issuerSignedSDJWT.disclosures, + keyBindingJWT: KBJWT( + header: DefaultJWSHeaderImpl(algorithm: .ES256), + kbJwtPayload: .init([ + Keys.nonce.rawValue: "123456789", + Keys.aud.rawValue: "example.com", + Keys.iat.rawValue: 1694600000, + Keys.sdHash.rawValue: sdHash + ]) + ) + ) + + let serialized: String = CompactSerialiser(signedSDJWT: holder).serialised + + let result = try await SDJWTVCVerifier( + fetcher: SdJwtVcIssuerMetaDataFetcher( + session: NetworkingJSONMock( + json: jsonObject + ) + ) + ).verifyPresentation( + unverifiedSdJwt: serialized, + claimsVerifier: ClaimsVerifier(), + keyBindingVerifier: KeyBindingVerifier() + ) + + XCTAssertEqual(sdHash, holder.delineatedCompactSerialisation) + XCTAssertNoThrow(try result.get()) + } }