From 58eb864e49cc8b45aa49abe3cff03c4ef6c404c5 Mon Sep 17 00:00:00 2001 From: "Josep Milan K.A" Date: Thu, 10 Oct 2024 17:29:22 +0530 Subject: [PATCH] Fix: Updated filter logic for sdjwt credentials --- .../Service/SDJWTService.swift | 103 +++++++++++++----- .../Service/VerificationService.swift | 2 +- 2 files changed, 77 insertions(+), 28 deletions(-) diff --git a/Sources/eudiWalletOidcIos/Service/SDJWTService.swift b/Sources/eudiWalletOidcIos/Service/SDJWTService.swift index dc5c9e6..81bb279 100644 --- a/Sources/eudiWalletOidcIos/Service/SDJWTService.swift +++ b/Sources/eudiWalletOidcIos/Service/SDJWTService.swift @@ -12,11 +12,11 @@ public class SDJWTService { private init() {} /** - * Calculates the SHA-256 hash of the input string and returns it in base64url encoding. - * - * @param inputString The input string to be hashed. - * @return The SHA-256 hash of the input string in base64url encoding, or null if the input is null. - */ + * Calculates the SHA-256 hash of the input string and returns it in base64url encoding. + * + * @param inputString The input string to be hashed. + * @return The SHA-256 hash of the input string in base64url encoding, or null if the input is null. + */ public func calculateSHA256Hash(inputString: String?) -> String? { guard let inputString = inputString, let inputData = inputString.data(using: .utf8) else { @@ -50,28 +50,28 @@ public class SDJWTService { presentationDefinition: VerificationService.processPresentationDefinition(presentationRequest.presentationDefinition) ) -// let iat = Date() -// let payload = -// ([ -// "audience": "\(presentationRequest.clientId ?? "")", -// "issueTime": "\(iat)", -// "nonce": "\(UUID().uuidString)", -// "exp": SDJWTService().calculateSHA256Hash(inputString: processedCredentialWithRequiredDisclosures) ?? "" -// ] as [String : Any]).toString() ?? "" -// -// let header = -// ([ -// "algorithm": "ES256", -// "type": "kb_jwt" -// ]).toString() ?? "" -// -// // Create JWT token -// let headerData = Data(header.utf8) -// let payloadData = Data(payload.utf8) -// let unsignedToken = "\(headerData.base64URLEncodedString()).\(payloadData.base64URLEncodedString())" -// let signatureData = try! privateKey.signature(for: unsignedToken.data(using: .utf8)!) -// let signature = signatureData.rawRepresentation -// let idToken = "\(unsignedToken).\(signature.base64URLEncodedString())" + // let iat = Date() + // let payload = + // ([ + // "audience": "\(presentationRequest.clientId ?? "")", + // "issueTime": "\(iat)", + // "nonce": "\(UUID().uuidString)", + // "exp": SDJWTService().calculateSHA256Hash(inputString: processedCredentialWithRequiredDisclosures) ?? "" + // ] as [String : Any]).toString() ?? "" + // + // let header = + // ([ + // "algorithm": "ES256", + // "type": "kb_jwt" + // ]).toString() ?? "" + // + // // Create JWT token + // let headerData = Data(header.utf8) + // let payloadData = Data(payload.utf8) + // let unsignedToken = "\(headerData.base64URLEncodedString()).\(payloadData.base64URLEncodedString())" + // let signatureData = try! privateKey.signature(for: unsignedToken.data(using: .utf8)!) + // let signature = signatureData.rawRepresentation + // let idToken = "\(unsignedToken).\(signature.base64URLEncodedString())" return processedCredentialWithRequiredDisclosures } catch { @@ -134,6 +134,55 @@ public class SDJWTService { guard let jsonData = try? JSONSerialization.data(withJSONObject: object) else { return nil } return String(data: jsonData, encoding: .utf8) } + public func updateIssuerJwtWithDisclosuresForFiltering(credential: String?) -> String? { + guard let split = credential?.split(separator: "."), split.count > 1, + let jsonString = "\(split[1])".decodeBase64(), + let jsonObject = UIApplicationUtils.shared.convertStringToDictionary(text: jsonString) else { return nil } + + var object = jsonObject + + var hashList: [String] = [] + let disclosures = getDisclosuresFromSDJWT(credential) ?? [] + disclosures.forEach { encodedString in + guard let hash = calculateSHA256Hash(inputString: encodedString) else { return } + hashList.append(hash) + } + + object = addDisclosuresToCredentialForFiltering(jsonElement: jsonObject, disclosures: disclosures, hashList: hashList) + + guard let jsonData = try? JSONSerialization.data(withJSONObject: object) else { return nil } + return String(data: jsonData, encoding: .utf8) + } + private func addDisclosuresToCredentialForFiltering(jsonElement: [String: Any], disclosures: [String], hashList: [String]) -> [String: Any] { + var modifiedJsonElement = jsonElement + + if modifiedJsonElement["_sd"] != nil { + guard let sdList = modifiedJsonElement["_sd"] as? [String] else { return [:] } + for (index, hash) in hashList.enumerated() { + if isStringPresentInJSONArray(jsonArray: sdList, searchString: hash) { + + if let disclosure = disclosures[index].decodeBase64() { + let (decodedKey, decodedValue) = extractKeyValue(from: disclosure) ?? ("","" as Any) + if let decodedValue = decodedValue as? [String: Any] { + modifiedJsonElement[decodedKey] = disclosure + } else if let decodedValue = decodedValue as? [Any] { + modifiedJsonElement[decodedKey] = disclosure + } else { + modifiedJsonElement[decodedKey] = disclosure + } + } + } + } + } + + for (key, value) in modifiedJsonElement { + if(value is [String: Any]){ + modifiedJsonElement[key] = addDisclosuresToCredentialForFiltering(jsonElement: value as! [String : Any], disclosures: disclosures, hashList: hashList) + } + } + + return modifiedJsonElement + } private func addDisclosuresToCredential(jsonElement: [String: Any], disclosures: [String], hashList: [String]) -> [String: Any] { var modifiedJsonElement = jsonElement diff --git a/Sources/eudiWalletOidcIos/Service/VerificationService.swift b/Sources/eudiWalletOidcIos/Service/VerificationService.swift index e499e55..1283993 100644 --- a/Sources/eudiWalletOidcIos/Service/VerificationService.swift +++ b/Sources/eudiWalletOidcIos/Service/VerificationService.swift @@ -821,7 +821,7 @@ public func filterNameSpaces(nameSpacesValue: CBOR, requestedParams: [String]) - let jsonString: String if (cred.split(separator: "~").count) > 0 { - jsonString = SDJWTService.shared.updateIssuerJwtWithDisclosures(credential: cred) ?? "" + jsonString = SDJWTService.shared.updateIssuerJwtWithDisclosuresForFiltering(credential: cred) ?? "" } else if split.count > 1, let base64Data = Data(base64Encoded: String(split[1]), options: .ignoreUnknownCharacters), let decodedString = String(data: base64Data, encoding: .utf8) {