Skip to content

Commit

Permalink
Merge branch 'EWC-consortium:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
josmilan authored Oct 10, 2024
2 parents 62e8f30 + 4b8902b commit f6c7294
Show file tree
Hide file tree
Showing 13 changed files with 926 additions and 65 deletions.
5 changes: 3 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ let package = Package(
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "1.8.1"),
.package(url: "https://github.com/decentralised-dataexchange/PresentationExchangeSdkiOS.git", .upToNextMajor(from: "2024.8.1")),
.package(url: "https://github.com/airsidemobile/JOSESwift.git", from: "2.3.0"),
.package(url: "https://github.com/apple/swift-crypto.git", from:"3.5.2")
.package(url: "https://github.com/apple/swift-crypto.git", from:"3.5.2"),
.package(url: "https://github.com/niscy-eudiw/SwiftCBOR.git", from: "0.5.7")
],
targets: [
.target(
name: "eudiWalletOidcIos",
dependencies: ["Base58Swift", "CryptoSwift", "PresentationExchangeSdkiOS", "JOSESwift", .product(name: "Crypto", package: "swift-crypto")],
dependencies: ["Base58Swift", "CryptoSwift", "PresentationExchangeSdkiOS", "JOSESwift", "SwiftCBOR", .product(name: "Crypto", package: "swift-crypto")],
path: "Sources"),
.testTarget(
name: "eudi-wallet-oidc-iosTests",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// Created by Mumthasir mohammed on 08/03/24.
//
import Foundation

// MARK: - IssuerWellKnownConfiguration
public struct Display: Codable{
public let name: String?
Expand Down Expand Up @@ -38,7 +37,6 @@ public struct Display: Codable{
textColor = mTextColor
}
}

public struct TrustFrameworkInIssuer {
public let name: String?
public let type: String?
Expand All @@ -52,7 +50,6 @@ public struct TrustFrameworkInIssuer {
display = from.display == nil ? nil : Display(from: from.display!)
}
}

// MARK: - CredentialObj
public struct CredentialSupportedObject {

Expand Down Expand Up @@ -82,7 +79,6 @@ public struct CredentialSupportedObject {
}
}
}

public struct DisplayElement {
public var name: String?
public var locale: Locale?
Expand All @@ -92,7 +88,6 @@ public struct DisplayElement {
locale = from.locale
}
}

public struct IssuerCredentialDefinition {
public var type: [String]?
public var vct: String?
Expand All @@ -102,7 +97,6 @@ public struct IssuerCredentialDefinition {
vct = from.vct
}
}

// MARK: - DataSharing
public struct DataSharing {
public var format, scope: String?
Expand All @@ -111,6 +105,7 @@ public struct DataSharing {
public var types: [String]?
public var trustFramework: TrustFramework?
public var credentialDefinition: IssuerCredentialDefinition?
public var docType: String?

init(from: DataSharingResponse) {
format = from.format
Expand All @@ -121,6 +116,7 @@ public struct DataSharing {
display = dataSharingDisplayList.map({ Display(from: $0) })
}
credentialDefinition = from.credentialDefinition == nil ? nil : IssuerCredentialDefinition(from: from.credentialDefinition!)
docType = from.docType
}

init(from: DataSharingOldFormatResponse) {
Expand All @@ -132,14 +128,12 @@ public struct DataSharing {
}
}
}

// MARK: - CredentialsSupportedObjectDisplay
public struct CredentialsSupportedObjectDisplay {
public var name, location, locale: String?
public var cover, logo: DisplayCover?
public var description: String?
}

// MARK: - Cover
public struct DisplayCover: Codable {
public var uri: String?
Expand All @@ -158,7 +152,6 @@ public struct DisplayCover: Codable {
url = mUrl
}
}

public struct IssuerWellKnownConfiguration {
public let credentialIssuer: String?
public let authorizationServer: String?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,15 @@ struct DataSharingResponse: Codable {
var cryptographicBindingMethodsSupported, cryptographicSuitesSupported: [String]?
var display: [DisplayResponse]?
var credentialDefinition: IssuerCredentialDefinitionResponse?
var docType: String?

enum CodingKeys: String, CodingKey {
case format, scope
case cryptographicBindingMethodsSupported = "cryptographic_binding_methods_supported"
case cryptographicSuitesSupported = "cryptographic_suites_supported"
case display
case credentialDefinition = "credential_definition"
case docType = "doctype"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public struct InputDescriptor: Codable {
public let name: String?
public let purpose: String?
public var constraints: Constraints?
public let format: InputDescriptorFormat?
public let format: [String: JwtVp?]?//InputDescriptorFormat?
}
// MARK: - Constraints
public struct Constraints: Codable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
//
// Created by iGrant on 25/07/24.
//

import Foundation

protocol CredentialValidaorProtocol {
func validateCredential(jwt: String?, jwksURI: String?) async throws
func validateCredential(jwt: String?, jwksURI: String?, format: String) async throws
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,19 @@
//
// Created by iGrant on 24/07/24.
//

import Foundation
import Base58Swift

public enum ValidationError: Error {
case JWTExpired
case signatureExpired
}

public class CredentialValidatorService: CredentialValidaorProtocol {
public static var shared = CredentialValidatorService()
public init() {}

public func validateCredential(jwt: String?, jwksURI: String?) async throws {
let isJWTExpired = ExpiryValidator.validateExpiryDate(jwt: jwt) ?? false
let isSignatureExpied = await SignatureValidator.validateSign(jwt: jwt, jwksURI: jwksURI) ?? false
public func validateCredential(jwt: String?, jwksURI: String?, format: String) async throws {
let isJWTExpired = ExpiryValidator.validateExpiryDate(jwt: jwt, format: format) ?? false
let isSignatureExpied = await SignatureValidator.validateSign(jwt: jwt, jwksURI: jwksURI, format: format) ?? false
if isJWTExpired {
throw ValidationError.JWTExpired
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,27 @@
//

import Foundation
import SwiftCBOR


class ExpiryValidator {

static func validateExpiryDate(jwt: String?) -> Bool? {
guard let split = jwt?.split(separator: "."),
let jsonString = "\(split[1])".decodeBase64(),
static func validateExpiryDate(jwt: String?, format: String) -> Bool? {
var expirationDate: String = ""
if format == "mso_mdoc" {
if let issuerAuthData = getIssuerAuth(credential: jwt ?? "") {
expirationDate = getExpiryFromIssuerAuth(cborData: issuerAuthData) ?? ""
} else {
return false
}
} else {

guard let split = jwt?.split(separator: "."), split.count > 1, let jsonString = "\(split[1])".decodeBase64(),
let jsonObject = UIApplicationUtils.shared.convertStringToDictionary(text: jsonString) else { return false }
guard let vc = jsonObject["vc"] as? [String: Any], let expirationDate = vc["expirationDate"] as? String else { return false }
let dateFormatter = DateFormatter()
guard let vc = jsonObject["vc"] as? [String: Any], let expiryDate = vc["expirationDate"] as? String else { return false }
expirationDate = expiryDate
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
guard let expiryDate = dateFormatter.date(from: expirationDate) else { return false}
Expand All @@ -25,5 +37,86 @@ class ExpiryValidator {
return true
}
}


static func getIssuerAuth(credential: String) -> CBOR? {
// Convert the base64 URL encoded credential to Data
if let data = Data(base64URLEncoded: credential) {
do {
// Decode the CBOR data into a dictionary
let decodedCBOR = try CBOR.decode([UInt8](data))

if let dictionary = decodedCBOR {
// Check for the presence of "issuerAuth" in the dictionary
if let issuerAuthValue = dictionary[CBOR.utf8String("issuerAuth")] {
return issuerAuthValue // Return the issuerAuth value directly
}
}
} catch {
print("Error decoding CBOR: \(error)")
return nil
}
} else {
print("Invalid base64 URL encoded credential.")
return nil
}

return nil // Return nil if "issuerAuth" is not found
}


static func getExpiryFromIssuerAuth(cborData: CBOR) -> String? {
guard case let CBOR.array(elements) = cborData else {
print("Expected CBOR array, but got something else.")
return nil
}
var docType: String? = ""
for element in elements {
if case let CBOR.byteString(byteString) = element {
if let nestedCBOR = try? CBOR.decode(byteString) {
if case let CBOR.tagged(tag, item) = nestedCBOR, tag.rawValue == 24 {
if case let CBOR.byteString(data) = item {
if let decodedInnerCBOR = try? CBOR.decode([UInt8](data)) {
docType = extractExpiry(cborData: decodedInnerCBOR )
} else {
print("Failed to decode inner ByteString under Tag 24.")
}
}
}
} else {
print("Could not decode ByteString as CBOR, inspecting data directly.")
print("ByteString data: \(byteString)")
}
} else {
print("Element: \(element)")
}
}
return docType ?? ""
}

static func extractExpiry(cborData: CBOR) -> String? {
guard case let CBOR.map(map) = cborData else {
return nil
}
for (key, value) in map {
if case let CBOR.utf8String(keyString) = key, keyString == "validityInfo" {
if case let CBOR.map(validityMap) = value {
for (validityKey, validityValue) in validityMap {
if case let CBOR.utf8String(validityKeyString) = validityKey, validityKeyString == "validUntil" {
if case let CBOR.tagged(_, CBOR.utf8String(validUntilString)) = validityValue {
return validUntilString
} else {
print("The value associated with 'validUntil' is not in the expected format.")
}
}
}
} else {
print("The value associated with 'validityInfo' is not a map.")
}
}
}
print("validityInfo not found in the CBOR map.")
return nil
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ import CryptoKit

class SignatureValidator {

static func validateSign(jwt: String?, jwksURI: String?) async -> Bool? {
static func validateSign(jwt: String?, jwksURI: String?, format: String) async -> Bool? {
var jwk: [String: Any] = [:]
guard let split = jwt?.split(separator: "."),
let jsonString = "\(split[0])".decodeBase64(),
if format == "mso_mdoc" {
return true
} else {
guard let split = jwt?.split(separator: "."), split.count > 1 else { return true}
guard let jsonString = "\(split[0])".decodeBase64(),
let jsonObject = UIApplicationUtils.shared.convertStringToDictionary(text: jsonString) else { return false }
if let kid = jsonObject["kid"] as? String {
if kid.hasPrefix("did:key:z") {
Expand All @@ -31,6 +34,7 @@ class SignatureValidator {
}
return validateSignature(jwt: jwt, jwk: jwk)
}
}


static func processJWKfromKid(did: String?) -> [String: Any] {
Expand Down
Loading

0 comments on commit f6c7294

Please sign in to comment.