Skip to content

Commit

Permalink
Merge pull request #21 from niscy-eudiw/feature/format-as-json-object
Browse files Browse the repository at this point in the history
[fix] format as json object
  • Loading branch information
dtsiflit authored Apr 19, 2024
2 parents d9d1772 + c5c6aea commit 2c5486e
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 136 deletions.
9 changes: 9 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@
"revision" : "26cc5e9ae0947092c7139ef7ba612e34646086c7",
"version" : "0.10.1"
}
},
{
"identity" : "swiftyjson",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SwiftyJSON/SwiftyJSON.git",
"state" : {
"revision" : "2b6054efa051565954e1d2b9da831680026cd768",
"version" : "4.3.0"
}
}
],
"version" : 2
Expand Down
14 changes: 13 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ let package = Package(
.package(
url: "https://github.com/birdrides/mockingbird.git",
.upToNextMinor(from: "0.20.0")
)
),
.package(
url: "https://github.com/SwiftyJSON/SwiftyJSON.git",
from: "4.0.0"
),
],
targets: [
.target(
Expand All @@ -37,6 +41,10 @@ let package = Package(
name: "JSONSchema",
package: "JSONSchema.swift"
),
.product(
name: "SwiftyJSON",
package: "SwiftyJSON"
),
],
path: "Sources",
resources: [
Expand All @@ -58,6 +66,10 @@ let package = Package(
.product(
name: "Sextant",
package: "Sextant"
),
.product(
name: "SwiftyJSON",
package: "SwiftyJSON"
)
],
path: "Tests"
Expand Down
4 changes: 2 additions & 2 deletions Sources/Claim/Claim.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import Foundation

public struct Claim {
public let id: ClaimId
public let format: FormatDesignation
public let format: String
public let jsonObject: JSONObject

public init(
id: ClaimId,
format: FormatDesignation,
format: String,
jsonObject: JSONObject
) {
self.id = id
Expand Down
13 changes: 7 additions & 6 deletions Sources/Matching/Matcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import Foundation
import Sextant
import JSONSchema
import SwiftyJSON

public typealias ClaimsEvaluation = [ClaimId: [InputDescriptorId: InputDescriptorEvaluation]]
public typealias InputDescriptorEvaluationPerClaim = [InputDescriptorId: [ClaimId: InputDescriptorEvaluation]]
Expand Down Expand Up @@ -61,7 +62,7 @@ public class PresentationMatcher: PresentationMatcherType {

private extension PresentationMatcher {
private func matchInputDescriptors(
presentationDefinitionFormat: [Format]?,
presentationDefinitionFormat: [JSON]?,
inputDescriptors: [InputDescriptor],
claim: Claim
) -> [InputDescriptorId: InputDescriptorEvaluation] {
Expand All @@ -78,7 +79,7 @@ private extension PresentationMatcher {
}

private func evaluate(
presentationDefinitionFormat: [Format]?,
presentationDefinitionFormat: [JSON]?,
inputDescriptor: InputDescriptor,
claim: Claim
) -> InputDescriptorEvaluation {
Expand All @@ -98,15 +99,15 @@ private extension PresentationMatcher {

private func isFormatSupported(
inputDescriptor: InputDescriptor,
presentationDefinitionFormat: [Format]?,
claimFormat: FormatDesignation
presentationDefinitionFormat: [JSON]?,
claimFormat: String
) -> Bool {

guard let formats: [Format] = inputDescriptor.formatContainer?.formats ?? presentationDefinitionFormat else {
guard let formats: [JSON] = inputDescriptor.formatContainer?.formats ?? presentationDefinitionFormat else {
return true
}

return formats.map { $0.designation }.contains(where: { $0 == claimFormat })
return formats.compactMap { $0["designation"].string }.contains(where: { $0 == claimFormat })
}

private func checkFieldConstraints(
Expand Down
129 changes: 8 additions & 121 deletions Sources/PresentationDefinition/Format.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,128 +14,29 @@
* limitations under the License.
*/
import Foundation

public enum FormatSpecifier: Codable, Equatable {
case alg(Set<FormatAlgorithm>)
case proofType(Set<LdpProof>)
case none
}

public enum FormatAlgorithm: String, Codable {
case HS256 // HMAC using SHA-256 (Required)
case HS384 // HMAC using SHA-384
case HS512 // HMAC using SHA-512
case RS256 // RSASSA-PKCS1-v1_5 using SHA-256 (Recommended)
case RS384 // RSASSA-PKCS1-v1_5 using SHA-384
case RS512 // RSASSA-PKCS1-v1_5 using SHA-512
case ES256 // ECDSA using P-256 and SHA-256 (Recommended)
case ES256K
case ES384 // ECDSA using P-384 and SHA-384
case ES512 // ECDSA using P-521 and SHA-512
case PS256 // RSASSA-PSS using SHA-256 and MGF1 with SHA-256
case PS384
case PS512
case EDDSA = "EdDSA"
}

public enum LdpProof: String, Codable {
case ed25519Signature2018 = "Ed25519Signature2018"
case rsaSignature2018 = "RsaSignature2018"
case rsaVerificationKey2018 = "RsaVerificationKey2018"
case ecdsaSecp256k1Signature2019 = "EcdsaSecp256k1Signature2019"
case ecdsaSecp256k1VerificationKey2019 = "EcdsaSecp256k1VerificationKey2019"
case ecdsaSecp256k1RecoverySignature2020 = "EcdsaSecp256k1RecoverySignature2020"
case ecdsaSecp256k1RecoveryMethod2020 = "EcdsaSecp256k1RecoveryMethod2020"
case jsonWebSignature2020 = "JsonWebSignature2020"
case jwsVerificationKey2020 = "JwsVerificationKey2020"
case gpgSignature2020 = "GpgSignature2020"
case gpgVerificationKey2020 = "GpgVerificationKey2020"
case jcsEd25519Signature2020 = "JcsEd25519Signature2020"
case jcsEd25519Key2020 = "JcsEd25519Key2020"
case bbsBlsSignature2020 = "BbsBlsSignature2020"
case bbsBlsSignatureProof2020 = "BbsBlsSignatureProof2020"
case bls12381G1Key2020 = "Bls12381G1Key2020"
case bls12381G2Key2020 = "Bls12381G2Key2020"
}

public enum FormatDesignation: String, Codable {

case msoMdoc = "MSO_MDOC"
case jwt = "JWT"
case jwtVC = "JWT_VC"
case jwtVp = "JWT_VP"

case ldp = "LDP"
case ldpVc = "LDP_VC"
case ldpVp = "LDP_VP"

case sdJwt = "SD_JWT"
case hbJwt = "HB_JWT"
}
import SwiftyJSON

public struct FormatContainer: Codable, Equatable {
public let formats: [Format]
public let formats: [JSON]

enum Key: String, CodingKey {
case formats
}

public init(formats: [Format]) {
public init(formats: [JSON]) {
self.formats = formats
}

public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let dictionary = try container.decode([String: [String: [String]]].self)
var parsed: [Format] = []
var parsed: [JSON] = []

for (key, value) in dictionary {
let designation = key
let properties: [String: [String]] = value

if properties.count > 1 {
throw PresentationError.invalidFormat
}

for (key, value) in properties {
guard let formatDesignation = FormatDesignation(rawValue: designation.uppercased()) else {
throw PresentationError.invalidFormat
}

var property: FormatSpecifier = .none
var algs: [FormatAlgorithm] = []
if key == "alg" {
algs = value.compactMap { FormatAlgorithm(rawValue: $0) }
if algs.isEmpty {
throw PresentationError.invalidFormat
}

property = .alg(Set(algs))
}

var proofs: [LdpProof] = []
if key == "proof_type" {
proofs = value.compactMap { LdpProof(rawValue: $0) }
if proofs.isEmpty {
throw PresentationError.invalidFormat
}

property = .proofType(Set(proofs))
}

let format: Format = .init(
designation: formatDesignation,
property: property
)

switch property {
case .none:
throw PresentationError.invalidFormat
default: break
}

parsed.append(format)
}
var newDict: [String: Any] = [:]
newDict["designation"] = key
newDict.merge(value) { (_, new) in new }
parsed.append(JSON(newDict))
}
formats = parsed
}
Expand All @@ -145,17 +46,3 @@ public struct FormatContainer: Codable, Equatable {
try? container.encode(formats, forKey: .formats)
}
}

public struct Format: Codable, Equatable {
public let designation: FormatDesignation
public let property: FormatSpecifier

enum CodingKeys: String, CodingKey {
case designation
case property
}

public static func == (lhs: Format, rhs: Format) -> Bool {
return lhs.designation == rhs.designation && lhs.property == rhs.property
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/
import Foundation
import SwiftyJSON

/*
Based on https://identity.foundation/presentation-exchange/
Expand Down
8 changes: 4 additions & 4 deletions Tests/PresentationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ final class PresentationTests: XCTestCase {
let presentationDefinition = try! result.get()
let format = presentationDefinition.inputDescriptors.first!.formatContainer!.formats.first

XCTAssertTrue(format!.designation == .msoMdoc)
XCTAssertTrue(format!["designation"].string?.lowercased() == "mso_mdoc")
}

func testValidateFormatExamplePresentationDefinitionExpectedData() throws {
Expand All @@ -133,7 +133,7 @@ final class PresentationTests: XCTestCase {

let formats = presentationDefinition.formatContainer!.formats

XCTAssert(!formats.filter { $0.designation == .jwt}.isEmpty)
XCTAssert(!formats.filter { $0["designation"].string?.lowercased() == "jwt" }.isEmpty)
}

func testAuthorizationRequestDataGivenValidInput() throws {
Expand Down Expand Up @@ -173,8 +173,8 @@ final class PresentationTests: XCTestCase {
)

let presentationDefinition = try! result.get()
let format = presentationDefinition.formatContainer!.formats.filter { $0.designation == .sdJwt}.first
let format = presentationDefinition.formatContainer!.formats.filter { $0["designation"].string?.lowercased() == "sd_jwt"}.first

XCTAssertTrue(format!.designation == .sdJwt)
XCTAssertTrue(format!["designation"].string == "sd_jwt")
}
}
4 changes: 2 additions & 2 deletions Tests/TestsConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct TestsConstants {
static let testClaimsBankAndPassport = [
Claim(
id: "samplePassport",
format: .ldp,
format: "LDP",
jsonObject: [
"credentialSchema":
[
Expand All @@ -37,7 +37,7 @@ struct TestsConstants {
),
Claim(
id: "sampleBankAccount",
format: .jwt,
format: "JWT",
jsonObject: [
"issuer": "did:example:123",
"credentialSchema":
Expand Down

0 comments on commit 2c5486e

Please sign in to comment.