Skip to content

Commit

Permalink
Merge pull request #32 from moratori/refactor-jwt-related-processing
Browse files Browse the repository at this point in the history
Refactor jwt related processing
  • Loading branch information
ryosuke-wakaba authored Oct 16, 2024
2 parents 1261a1f + d3b108d commit f7a0260
Show file tree
Hide file tree
Showing 16 changed files with 495 additions and 190 deletions.
8 changes: 4 additions & 4 deletions tw2023_wallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@
A83039BF2B4E4229004139A7 /* ZipUtilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83039B92B4E4229004139A7 /* ZipUtilTest.swift */; };
A83039C02B4E4229004139A7 /* SDJwtUtilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83039BA2B4E4229004139A7 /* SDJwtUtilTest.swift */; };
A83039C12B4E4229004139A7 /* KeyPairUtilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83039BB2B4E4229004139A7 /* KeyPairUtilTest.swift */; };
A83039C22B4E4229004139A7 /* SerializeUtilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83039BC2B4E4229004139A7 /* SerializeUtilTest.swift */; };
A83039C42B4E4829004139A7 /* SwiftASN1 in Frameworks */ = {isa = PBXBuildFile; productRef = A83039C32B4E4829004139A7 /* SwiftASN1 */; };
A83039C72B4E6E5D004139A7 /* id_token_sharing_history.proto in Sources */ = {isa = PBXBuildFile; fileRef = A83039C62B4E6E5D004139A7 /* id_token_sharing_history.proto */; };
A83039C92B4E6E7E004139A7 /* credential_data.proto in Sources */ = {isa = PBXBuildFile; fileRef = A83039C82B4E6E7E004139A7 /* credential_data.proto */; };
Expand All @@ -179,6 +178,7 @@
A87A957D2CACCDD500001D8F /* ProviderTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87A957C2CACCDD000001D8F /* ProviderTypes.swift */; };
A87A957E2CACCDD500001D8F /* ProviderTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87A957C2CACCDD000001D8F /* ProviderTypes.swift */; };
A88779BD2C33DC08002EE9C2 /* WebViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88779BC2C33DC08002EE9C2 /* WebViewTests.swift */; };
A88BF3532CB7807600401ACC /* SerializeUtilTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88BF3522CB7806B00401ACC /* SerializeUtilTest.swift */; };
A88D323A2C26997700429E75 /* Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = A82ECC782C22738900B9784B /* Metadata.swift */; };
A88D323C2C26B0DF00429E75 /* UrlEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A82ECC7F2C23A6AB00B9784B /* UrlEncoder.swift */; };
A88D32442C27001B00429E75 /* credential_display_filled.json in Resources */ = {isa = PBXBuildFile; fileRef = A82601A82C267A2A00BF8139 /* credential_display_filled.json */; };
Expand Down Expand Up @@ -412,7 +412,6 @@
A83039B92B4E4229004139A7 /* ZipUtilTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZipUtilTest.swift; sourceTree = "<group>"; };
A83039BA2B4E4229004139A7 /* SDJwtUtilTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SDJwtUtilTest.swift; sourceTree = "<group>"; };
A83039BB2B4E4229004139A7 /* KeyPairUtilTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyPairUtilTest.swift; sourceTree = "<group>"; };
A83039BC2B4E4229004139A7 /* SerializeUtilTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerializeUtilTest.swift; sourceTree = "<group>"; };
A83039C62B4E6E5D004139A7 /* id_token_sharing_history.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = id_token_sharing_history.proto; sourceTree = "<group>"; };
A83039C82B4E6E7E004139A7 /* credential_data.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = credential_data.proto; sourceTree = "<group>"; };
A83039CA2B4E6E92004139A7 /* credential_sharing_history.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = credential_sharing_history.proto; sourceTree = "<group>"; };
Expand All @@ -429,6 +428,7 @@
A8509C282B82315D00B28C35 /* RecipientClaims.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipientClaims.swift; sourceTree = "<group>"; };
A87A957C2CACCDD000001D8F /* ProviderTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProviderTypes.swift; sourceTree = "<group>"; };
A88779BC2C33DC08002EE9C2 /* WebViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewTests.swift; sourceTree = "<group>"; };
A88BF3522CB7806B00401ACC /* SerializeUtilTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerializeUtilTest.swift; sourceTree = "<group>"; };
A89108012B82D1650060DD71 /* RecipientClaimsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipientClaimsViewModel.swift; sourceTree = "<group>"; };
A89108032B82D2880060DD71 /* RecipientClaimsPreviewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipientClaimsPreviewModel.swift; sourceTree = "<group>"; };
A891080B2B84785F0060DD71 /* credential_sharing_history.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = credential_sharing_history.pb.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1033,12 +1033,12 @@
A83039B62B4E4229004139A7 /* Utils */ = {
isa = PBXGroup;
children = (
A88BF3522CB7806B00401ACC /* SerializeUtilTest.swift */,
A83039B72B4E4229004139A7 /* JWTTest.swift */,
A83039B82B4E4229004139A7 /* CertificateUtilTest.swift */,
A83039B92B4E4229004139A7 /* ZipUtilTest.swift */,
A83039BA2B4E4229004139A7 /* SDJwtUtilTest.swift */,
A83039BB2B4E4229004139A7 /* KeyPairUtilTest.swift */,
A83039BC2B4E4229004139A7 /* SerializeUtilTest.swift */,
F6CC769D2B580EF600FA26A8 /* QRCodeGeneratorTest.swift */,
A82ECC812C23A81C00B9784B /* UrlEncoderTest.swift */,
);
Expand Down Expand Up @@ -1741,6 +1741,7 @@
8B5C65992B5251C000D72289 /* KeyBindingImpl.swift in Sources */,
8B5C659C2B54D97400D72289 /* ES256K.swift in Sources */,
8B0E0AA92B3ED7D20080F6A3 /* AuthorizationRquestTests.swift in Sources */,
A88BF3532CB7807600401ACC /* SerializeUtilTest.swift in Sources */,
8BB2BA7F2B4C188E00C668BA /* EncryptionHelperTests.swift in Sources */,
8B43AE322B3A5B880016CF83 /* VCIMetadataClientTests.swift in Sources */,
8B5C65912B515BC300D72289 /* JWTUtil.swift in Sources */,
Expand Down Expand Up @@ -1772,7 +1773,6 @@
A88D323A2C26997700429E75 /* Metadata.swift in Sources */,
8BB513982B3BB88900D4EFB3 /* VCIMetadataUtil.swift in Sources */,
8B43AE382B3A93C60016CF83 /* AuthServerMetadata.swift in Sources */,
A83039C22B4E4229004139A7 /* SerializeUtilTest.swift in Sources */,
8B0E0AB02B403D510080F6A3 /* PresentationExchange.swift in Sources */,
A88779BD2C33DC08002EE9C2 /* WebViewTests.swift in Sources */,
8B297C372B39538500D2998D /* VCIMetadataTests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@

import Foundation

func jwtVcJsonClaimsTobeDisclosed(jwt: String) -> [Disclosure] {
if let (_, body, _) = try? JWTUtil.decodeJwt(jwt: jwt),
let vc = body["vc"] as? [String: Any],
let credentialSubject = vc["credentialSubject"] as? [String: Any]
{
let disclosures = credentialSubject.map { key, value in
// valueがネストしていることは想定していない。
return Disclosure(disclosure: nil, key: key, value: value as? String)
}
return disclosures
}
return []
}

@Observable
class CredentialDetailViewModel {
var requiredClaims: [DisclosureWithOptionality] = []
Expand Down Expand Up @@ -53,9 +67,8 @@ class CredentialDetailViewModel {
case "jwt_vc_json":
inputDescriptor = pd.inputDescriptors[0] // 選択開示できないので先頭固定
self.undisclosedClaims = []

let jwt = credential.payload
self.requiredClaims = JWTUtil.convertJWTClaimsAsDisclosure(jwt: jwt).map { it in
self.requiredClaims = jwtVcJsonClaimsTobeDisclosed(jwt: credential.payload).map
{ it in
return DisclosureWithOptionality(
disclosure: it, isSubmit: true, isUserSelectable: false)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,13 @@ class DisplayQRCodeViewModel: ObservableObject {
// else {
// return nil
// }
let jsonDict = [
let jsonDict: [String: Any] = [
"format": credential.format,
"credential": credential.payload,
"display": credential.qrDisplay,
]

guard let jsonData = try? JSONSerialization.data(withJSONObject: jsonDict, options: []),
let jsonString = String(data: jsonData, encoding: .utf8)
else {
guard let jsonString = try? jsonDict.toString() else {
return nil
}

Expand Down
11 changes: 6 additions & 5 deletions tw2023_wallet/Services/OID/JwtVpJsonGeneratorImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ class JwtVpJsonGeneratorImpl: JwtVpJsonGenerator {
vp: vpClaims
)
let vpTokenPayload = jwtPayload.toDictionary()
do {
return try JWTUtil.sign(keyAlias: keyAlias, header: header, payload: vpTokenPayload)
}
catch {
fatalError("Failed to sign JWT: \(error)")
let result = JWTUtil.sign(keyAlias: keyAlias, header: header, payload: vpTokenPayload)
switch result {
case let .success(jwt):
return jwt
case let .failure(error):
fatalError("Failed to sign JWT: \(error)")
}
}

Expand Down
8 changes: 7 additions & 1 deletion tw2023_wallet/Services/OID/KeyBindingImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ class KeyBindingImpl: KeyBinding {
"_sd_hash": sdHash,
"nonce": nonce,
]
return try JWTUtil.sign(keyAlias: keyAlias, header: header, payload: payload)
let result = JWTUtil.sign(keyAlias: keyAlias, header: header, payload: payload)
switch result {
case let .success(jwt):
return jwt
case let .failure(error):
throw error
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions tw2023_wallet/Services/OID/PresentationExchange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,13 @@ class JwtVpJsonPresentation {
path = "$[\(pathIndex)]"
}

/*
Add a comment regarding the leading `$`.
In VP draft 18 (ID 2), when sending `vp_token` as an array, the correct notation is `$[N].`.
However, in draft 21, the correct notation is `$.`. (In other words, it is a relative path)

For now, we will keep the current implementation, but it should be adjusted accordingly based on the specification we adopt.
*/
let pathNested = Path(
format: "jwt_vc_json",
path: "$.vp.verifiableCredential[\(pathNestedIndex)]"
Expand Down
8 changes: 6 additions & 2 deletions tw2023_wallet/Services/OID/Provider/OpenIdProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -383,21 +383,25 @@ class OpenIdProvider {
return .failure(OpenIdProviderIllegalStateException.illegalState)
}

let preparedSubmissionData = try! credentials.compactMap {
credential -> PreparedSubmissionData? in
let isMultipleVpTokens = credentials.count > 1
let preparedSubmissionData = try! credentials.enumerated().compactMap {
(index, credential) -> PreparedSubmissionData? in
let tokenIndex = isMultipleVpTokens ? index : index - 1
switch credential.format {
case "vc+sd-jwt":
return
try credential.createVpTokenForSdJwtVc(
clientId: clientId,
nonce: nonce,
tokenIndex: index,
keyBinding: keyBinding)

case "jwt_vc_json":
return
try credential.createVpTokenForJwtVc(
clientId: clientId,
nonce: nonce,
tokenIndex: index,
jwtVpJsonGenerator: jwtVpJsonGenerator

)
Expand Down
8 changes: 6 additions & 2 deletions tw2023_wallet/Services/OID/Provider/ProviderTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct SubmissionCredential: Codable, Equatable {
func createVpTokenForSdJwtVc(
clientId: String,
nonce: String,
tokenIndex: Int,
keyBinding: KeyBinding?
) throws -> PreparedSubmissionData {
guard let kb = keyBinding else {
Expand Down Expand Up @@ -94,7 +95,7 @@ struct SubmissionCredential: Codable, Equatable {
let dm = DescriptorMap(
id: inputDescriptor.id,
format: format,
path: "$",
path: tokenIndex > -1 ? "$[\(tokenIndex)]" : "$",
pathNested: nil
)

Expand All @@ -113,6 +114,7 @@ struct SubmissionCredential: Codable, Equatable {
func createVpTokenForJwtVc(
clientId: String,
nonce: String,
tokenIndex: Int,
jwtVpJsonGenerator: JwtVpJsonGenerator?
) throws -> PreparedSubmissionData {
guard let generator = jwtVpJsonGenerator else {
Expand All @@ -133,7 +135,9 @@ struct SubmissionCredential: Codable, Equatable {
payloadOptions: JwtVpJsonPayloadOptions(aud: clientId, nonce: nonce))

let descriptorMap = JwtVpJsonPresentation.genDescriptorMap(
inputDescriptorId: inputDescriptor.id)
inputDescriptorId: inputDescriptor.id,
pathIndex: tokenIndex
)
return PreparedSubmissionData(
credentialId: id,
vpToken: vpToken,
Expand Down
3 changes: 1 addition & 2 deletions tw2023_wallet/Signature/ES256K.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ class ES256K {
]

// Encode header to Base64URL
let encodedHeader = try Data(JSONSerialization.data(withJSONObject: header))
.base64URLEncodedString()
let encodedHeader = try header.toBase64UrlString()

// Encode payload to Base64URL
let encodedPayload = payload.data(using: .utf8)?.base64URLEncodedString() ?? ""
Expand Down
Loading

0 comments on commit f7a0260

Please sign in to comment.