Skip to content

Commit

Permalink
Merge pull request #24 from goncalo-frade-iohk/refactor/update-jose-lib
Browse files Browse the repository at this point in the history
feat(jose): updated to use a new jose library
  • Loading branch information
dtsiflit authored Jun 18, 2024
2 parents 3a41b5c + 447dc97 commit 6a999d2
Show file tree
Hide file tree
Showing 25 changed files with 201 additions and 255 deletions.
30 changes: 24 additions & 6 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
{
"pins" : [
{
"identity" : "joseswift",
"identity" : "cryptoswift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/niscy-eudiw/JOSESwift.git",
"location" : "https://github.com/krzyzanowskim/CryptoSwift.git",
"state" : {
"revision" : "518cedba79ef18867191811b161471298b6cb7c8",
"version" : "2.4.1-gcm"
"revision" : "c9c3df6ab812de32bae61fc0cd1bf6d45170ebf0",
"version" : "1.8.2"
}
},
{
"identity" : "jose-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/beatt83/jose-swift.git",
"state" : {
"revision" : "682002aae8d841d47bd9f641b8b85a233460d140",
"version" : "3.1.0"
}
},
{
"identity" : "secp256k1.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/GigaBitcoin/secp256k1.swift.git",
"state" : {
"revision" : "4c77c7384768acf1093d66ccaacf298d322b10b7",
"version" : "0.15.0"
}
},
{
"identity" : "swiftyjson",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SwiftyJSON/SwiftyJSON.git",
"state" : {
"revision" : "b3dcd7dbd0d488e1a7077cb33b00f2083e382f07",
"version" : "5.0.1"
"revision" : "af76cf3ef710b6ca5f8c05f3a31307d44a3c5828",
"version" : "5.0.2"
}
}
],
Expand Down
12 changes: 6 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version: 5.8
// swift-tools-version: 5.8.1
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand All @@ -23,16 +23,16 @@ let package = Package(
from: "5.0.1"
),
.package(
url: "https://github.com/niscy-eudiw/JOSESwift.git",
exact: "2.4.1-gcm"
),
url: "https://github.com/beatt83/jose-swift.git",
from: "3.1.0"
)
],
targets: [
.target(
name: "eudi-lib-sdjwt-swift",
dependencies: [
.product(name: "SwiftyJSON", package: "swiftyjson"),
.product(name: "JOSESwift", package: "JOSESwift")
"jose-swift",
.product(name: "SwiftyJSON", package: "swiftyjson")
],
path: "Sources",
plugins: [
Expand Down
1 change: 0 additions & 1 deletion Sources/Factory/SDJWTFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
import Foundation
import SwiftyJSON
import JOSESwift

typealias ClaimSet = (value: JSON, disclosures: [Disclosure])

Expand Down
39 changes: 0 additions & 39 deletions Sources/Issuer/JWSController.swift

This file was deleted.

19 changes: 10 additions & 9 deletions Sources/Issuer/JWT.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,38 @@
* limitations under the License.
*/
import Foundation
import JOSESwift
import JSONWebAlgorithms
import JSONWebSignature
import SwiftyJSON

public struct JWT: JWTRepresentable {

// MARK: - Properties

var header: JWSHeader
var header: JWSRegisteredFieldsHeader
var payload: JSON

// MARK: - Lifecycle

public init(header: JWSHeader, payload: JSON) throws {
public init(header: JWSRegisteredFieldsHeader, payload: JSON) throws {
guard header.algorithm?.rawValue != Keys.none.rawValue else {
throw SDJWTError.noneAsAlgorithm
}

guard SignatureAlgorithm.allCases.map({$0.rawValue}).contains(header.algorithm?.rawValue) else {
guard SigningAlgorithm.allCases.map({$0.rawValue}).contains(header.algorithm?.rawValue) else {
throw SDJWTError.macAsAlgorithm
}

self.header = header
self.payload = payload
}

public init(header: JWSHeader, kbJwtPayload: JSON) throws {
public init(header: JWSRegisteredFieldsHeader, kbJwtPayload: JSON) throws {
guard header.algorithm?.rawValue != Keys.none.rawValue else {
throw SDJWTError.noneAsAlgorithm
}

guard SignatureAlgorithm.allCases.map({$0.rawValue}).contains(header.algorithm?.rawValue) else {
guard SigningAlgorithm.allCases.map({$0.rawValue}).contains(header.algorithm?.rawValue) else {
throw SDJWTError.macAsAlgorithm
}
self.header = header
Expand All @@ -54,13 +55,13 @@ public struct JWT: JWTRepresentable {

// MARK: - Methods

func sign<KeyType>(signer: Signer<KeyType>) throws -> JWS {
func sign<KeyType>(key: KeyType) throws -> JWS {
let unsignedJWT = try self.asUnsignedJWT()
return try JWS(header: unsignedJWT.header, payload: unsignedJWT.payload, signer: signer)
return try JWS.init(payload: unsignedJWT.payload, protectedHeader: unsignedJWT.header, key: key)
}

mutating func addKBTyp() {
self.header.typ = "kb+jwt"
self.header.type = "kb+jwt"
}
}

Expand Down
13 changes: 6 additions & 7 deletions Sources/Issuer/JWTRepresentable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,25 @@
* limitations under the License.
*/
import Foundation
import JOSESwift
import JSONWebSignature
import SwiftyJSON

typealias Base64String = String
typealias UnsignedJWT = (header: JWSHeader, payload: Payload)
typealias UnsignedJWT = (header: JWSRegisteredFieldsHeader, payload: Data)

protocol JWTRepresentable {

var header: JWSHeader { get }
var header: JWSRegisteredFieldsHeader { get }
var payload: JSON { get }

func asUnsignedJWT() throws -> UnsignedJWT
func sign<KeyType>(signer: Signer<KeyType>) throws -> JWS
func sign<KeyType>(key: KeyType) throws -> JWS

init(header: JWSHeader, payload: JSON) throws
init(header: JWSRegisteredFieldsHeader, payload: JSON) throws
}

extension JWTRepresentable {
func asUnsignedJWT() throws -> UnsignedJWT {
let payload = Payload(try payload.rawData())
return(header, payload)
return(header, try payload.rawData())
}
}
48 changes: 16 additions & 32 deletions Sources/Issuer/SDJWT.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
* limitations under the License.
*/
import Foundation
import JSONWebKey
import JSONWebSignature
import JSONWebToken
import SwiftyJSON
import JOSESwift

public typealias KBJWT = JWT

Expand Down Expand Up @@ -75,30 +77,28 @@ public struct SignedSDJWT {

var delineatedCompactSerialisation: String {
let separator = "~"
let input = ([jwt.compactSerializedString] + disclosures).reduce("") { $0.isEmpty ? $1 : $0 + separator + $1 } + separator
let input = ([jwt.compactSerialization] + disclosures).reduce("") { $0.isEmpty ? $1 : $0 + separator + $1 } + separator
return DigestCreator()
.hashAndBase64Encode(
input: input
) ?? ""
}

// MARK: - Lifecycle

init(
serializedJwt: String,
disclosures: [Disclosure],
serializedKbJwt: String?
) throws {
self.jwt = try JWS(compactSerialization: serializedJwt)
self.jwt = try JWS(jwsString: serializedJwt)
self.disclosures = disclosures
self.kbJwt = try? JWS(compactSerialization: serializedKbJwt ?? "")
self.kbJwt = try? JWS(jwsString: serializedKbJwt ?? "")
}

private init?<KeyType>(sdJwt: SDJWT, issuersPrivateKey: KeyType) {
// Create a Signed SDJWT with no key binding
guard let signingAlgorithm = sdJwt.jwt.header.algorithm,
let signedJwt = try? SignedSDJWT.createSignedJWT(jwsController: .init(signingAlgorithm: signingAlgorithm, privateKey: issuersPrivateKey), jwt: sdJwt.jwt)
else {
guard let signedJwt = try? SignedSDJWT.createSignedJWT(key: issuersPrivateKey, jwt: sdJwt.jwt) else {
return nil
}

Expand All @@ -114,12 +114,7 @@ public struct SignedSDJWT {

self.jwt = signedSDJWT.jwt
self.disclosures = signedSDJWT.disclosures

guard let signingAlgorithm = kbJWT.header.algorithm,
let signedKBJwt = try? SignedSDJWT.createSignedJWT(jwsController: .init(signingAlgorithm: signingAlgorithm, privateKey: holdersPrivateKey), jwt: kbJWT)
else {
return nil
}
let signedKBJwt = try? SignedSDJWT.createSignedJWT(key: holdersPrivateKey, jwt: kbJWT)
self.kbJwt = signedKBJwt
}

Expand All @@ -140,8 +135,8 @@ public struct SignedSDJWT {
}()
}

private static func createSignedJWT<KeyType>(jwsController: JWSController<KeyType>, jwt: JWT) throws -> JWS {
try jwt.sign(signer: jwsController.signer)
private static func createSignedJWT<KeyType>(key: KeyType, jwt: JWT) throws -> JWS {
try jwt.sign(key: key)
}

func disclosuresToPresent(disclosures: [Disclosure]) -> Self {
Expand All @@ -151,16 +146,16 @@ public struct SignedSDJWT {
}

func toSDJWT() throws -> SDJWT {
if let kbJwtHeader = kbJwt?.header,
if let kbJwtHeader = kbJwt?.protectedHeader,
let kbJWtPayload = try? kbJwt?.payloadJSON() {
return try SDJWT(
jwt: JWT(header: jwt.header, payload: jwt.payloadJSON()),
jwt: JWT(header: jwt.protectedHeader, payload: jwt.payloadJSON()),
disclosures: disclosures,
kbJWT: JWT(header: kbJwtHeader, kbJwtPayload: kbJWtPayload))
}

return try SDJWT(
jwt: JWT(header: jwt.header, payload: jwt.payloadJSON()),
jwt: JWT(header: jwt.protectedHeader, payload: jwt.payloadJSON()),
disclosures: disclosures,
kbJWT: nil)
}
Expand All @@ -173,22 +168,11 @@ public struct SignedSDJWT {
throw SDJWTVerifierError.keyBindingFailed(description: "Failled to find holders public key")
}

guard let keyType = JWKKeyType(rawValue: jwk["kty"].stringValue) else {
guard let jwkObject = try? JSONDecoder.jwt.decode(JWK.self, from: jwk.rawData()) else {
throw SDJWTVerifierError.keyBindingFailed(description: "failled to extract key type")
}

switch keyType {
case .EC:
guard let crvType = ECCurveType(rawValue: jwk["crv"].stringValue) else {
throw SDJWTVerifierError.keyBindingFailed(description: "failled to extract curve type")
}
return ECPublicKey(crv: crvType, x: jwk["x"].stringValue, y: jwk["y"].stringValue)
case .RSA:
return RSAPublicKey(modulus: jwk["n"].stringValue, exponent: jwk["e"].stringValue)
case .OCT:
return try SymmetricKey(key: jwk["k"].rawData())
}

return jwkObject
}
}

Expand Down
Loading

0 comments on commit 6a999d2

Please sign in to comment.