Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
Separate Web5 & tbDEX targets (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
amika-sq authored Jan 17, 2024
1 parent 5b22ba6 commit 36db15a
Show file tree
Hide file tree
Showing 38 changed files with 202 additions and 142 deletions.
45 changes: 30 additions & 15 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,35 @@ let package = Package(
.package(url: "https://github.com/WeTransfer/Mocker.git", .upToNextMajor(from: "3.0.1")),
],
targets: [
// Main tbDEX library target
// Web5 Library target
.target(
name: "tbDEX",
name: "Web5",
dependencies: [
.product(name: "secp256k1", package: "secp256k1.swift"),
.product(name: "ExtrasBase64", package: "swift-extras-base64"),
.product(name: "TypeID", package: "swift-typeid"),
.product(name: "AnyCodable", package: "anycodable"),
]
),
// Shared test utilities target
// Web5 test utilities target
.target(
name: "TestUtilities",
path: "TestUtilities/"
name: "Web5TestUtilities",
dependencies: [
.product(name: "CustomDump", package: "swift-custom-dump"),
]
),
// Main tbDEX test target
// Web5 unit test target
.testTarget(
name: "tbDEXTests",
name: "Web5Tests",
dependencies: [
"tbDEX",
"TestUtilities",
.product(name: "CustomDump", package: "swift-custom-dump"),
"Web5",
"Web5TestUtilities",
]
),
// Web5 test vectors target
.testTarget(
name: "Web5TestVectors",
dependencies: [
"tbDEX",
"TestUtilities",
.product(name: "CustomDump", package: "swift-custom-dump"),
"Web5",
"Web5TestUtilities",
.product(name: "Mocker", package: "Mocker"),
],
resources: [
Expand All @@ -62,5 +60,22 @@ let package = Package(
.copy("Resources/did_web"),
]
),
// tbDEX library target
.target(
name: "tbDEX",
dependencies: [
"Web5",
.product(name: "TypeID", package: "swift-typeid"),
.product(name: "AnyCodable", package: "anycodable"),
]
),
// tbDEX unit test target
.testTarget(
name: "tbDEXTests",
dependencies: [
"tbDEX",
"Web5TestUtilities",
]
),
]
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ enum CryptoError: Error {
case illegalArgument(description: String)
}

enum Crypto {
public enum Crypto {

/// Generates a private key using the specified algorithm and curve, utilizing the appropriate `KeyGenerator`.
/// - Parameters:
Expand Down Expand Up @@ -42,7 +42,7 @@ enum Crypto {
/// - signedPayload: The data that was signed.
/// - algorithm: The algorithm used for signing/verification, only used if not provided in the JWK.
/// - Returns: Boolean indicating if the publicKey and signature are valid for the given payload.
static func verify<S, D>(
public static func verify<S, D>(
publicKey: Jwk,
signature: S,
signedPayload: D,
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,41 +1,43 @@
import Foundation

class InMemoryKeyManager {
public class InMemoryKeyManager {

/// Backing in-memory store to store generated keys.
private var keyStore = [String: Jwk]()

public init() {}

}

// MARK: - KeyManager

extension InMemoryKeyManager: KeyManager {

func generatePrivateKey(algorithm: Jwk.Algorithm, curve: Jwk.Curve? = nil) throws -> String {
public func generatePrivateKey(algorithm: Jwk.Algorithm, curve: Jwk.Curve? = nil) throws -> String {
let jwk = try Crypto.generatePrivateKey(algorithm: algorithm, curve: curve)
let alias = try getDeterministicAlias(key: jwk)
keyStore[alias] = jwk

return alias
}

func getPublicKey(keyAlias: String) throws -> Jwk? {
public func getPublicKey(keyAlias: String) throws -> Jwk? {
if let privateKey = keyStore[keyAlias] {
return try Crypto.computePublicKey(privateKey: privateKey)
} else {
return nil
}
}

func sign<D>(keyAlias: String, payload: D) throws -> Data where D: DataProtocol {
public func sign<D>(keyAlias: String, payload: D) throws -> Data where D: DataProtocol {
guard let privateKey = keyStore[keyAlias] else {
throw KeyManagerError.keyAliasNotFound
}

return try Crypto.sign(privateKey: privateKey, payload: payload)
}

func getDeterministicAlias(key: Jwk) throws -> String {
public func getDeterministicAlias(key: Jwk) throws -> String {
let alias: String

if let keyIdentifier = key.keyIdentifier {
Expand Down
70 changes: 51 additions & 19 deletions Sources/tbDEX/crypto/JWK.swift → Sources/Web5/Crypto/JWK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,36 @@ import CryptoKit
import ExtrasBase64
import Foundation

struct Jwk: Codable, Equatable {
public struct Jwk: Codable, Equatable {

// MARK: - Types

/// Supported `crv` curve types.
enum Curve: String, Codable {
public enum Curve: String, Codable {
case ed25519 = "Ed25519"
case secp256k1 = "secp256k1"
}

/// Supported `kty` key types.
enum KeyType: String, Codable {
public enum KeyType: String, Codable {
case elliptic = "EC"
case octetKeyPair = "OKP"
}

/// Supported `alg` algorithms.
enum Algorithm: String, Codable {
public enum Algorithm: String, Codable {
case eddsa = "EdDSA"
case es256k = "ES256K"
}

/// Supported `use` values.
enum PublicKeyUse: String, Codable {
public enum PublicKeyUse: String, Codable {
case signature = "sig"
case encryption = "enc"
}

/// Supported `key_ops` values.
enum KeyOperations: String, Codable {
public enum KeyOperations: String, Codable {
case encrypt
case decrypt
case sign
Expand All @@ -49,53 +49,85 @@ struct Jwk: Codable, Equatable {
/// on any of these parameters.

/// The `kty` (key type) parameter identifies the cyrptographic algorithm family used with the key.
var keyType: KeyType
public let keyType: KeyType

/// The `use` (public key use) parameter identifies the intended use of the public key.
var publicKeyUse: PublicKeyUse?
public let publicKeyUse: PublicKeyUse?

/// The "key_ops" (key operations) parameter identifies the operation(s) for which the key is intended to be used.
var keyOperations: [KeyOperations]?
public let keyOperations: [KeyOperations]?

/// The `alg` (algorithm) parameter identifies the cryptographic algorithm intended for use with the key.
var algorithm: Algorithm?
public let algorithm: Algorithm?

/// The "alg" (algorithm) parameter identifies the algorithm intended for use with the key.
var keyIdentifier: String?
public internal(set) var keyIdentifier: String?

/// The `crv` (curve) parameter identifies the cryptographic curve intended for use with the key.
var curve: Curve?
public let curve: Curve?

/// The "x5u" (X.509 URL) parameter is a URI [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986) that refers
/// to a resource for an X.509 public key certificate or certificate chain
/// [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280).
var x509Url: String?
public let x509Url: String?

/// The "x5c" (X.509 certificate chain) parameter contains a chain of one or more PKIX certificates
/// [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)
var x509CertificateChain: String?
public let x509CertificateChain: String?

/// The "x5t" (X.509 certificate SHA-1 thumbprint) parameter is a base64url-encoded SHA-1 thumbprint (a.k.a. digest)
/// of the DER encoding of an X.509 certificate [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280).
var x509CertificateSha1Thumbprint: String?
public let x509CertificateSha1Thumbprint: String?

/// The "x5t#S256" (X.509 certificate SHA-256 thumbprint) parameter is a base64url-encoded SHA-256 thumbprint
/// (a.k.a. digest) of the DER encoding of an X.509 certificate
/// [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280).
var x509CertificateSha256Thumbprint: String?
public let x509CertificateSha256Thumbprint: String?

// MARK: - KeyType Specific JWK Properties

/// The below properties represent JWK parameters that are unique to specific JWK key types.

/// `d` Private exponent.
var d: String?
let d: String?

/// The x-coordinate for the Elliptic Curve point.
var x: String?
let x: String?

/// Elliptic Curve y-coordinate.
var y: String?
let y: String?

// MARK: - Lifecycle

init(
keyType: KeyType,
publicKeyUse: PublicKeyUse? = nil,
keyOperations: [KeyOperations]? = nil,
algorithm: Algorithm? = nil,
keyIdentifier: String? = nil,
curve: Curve? = nil,
x509Url: String? = nil,
x509CertificateChain: String? = nil,
x509CertificateSha1Thumbprint: String? = nil,
x509CertificateSha256Thumbprint: String? = nil,
d: String? = nil,
x: String? = nil,
y: String? = nil
) {
self.keyType = keyType
self.publicKeyUse = publicKeyUse
self.keyOperations = keyOperations
self.algorithm = algorithm
self.keyIdentifier = keyIdentifier
self.curve = curve
self.x509Url = x509Url
self.x509CertificateChain = x509CertificateChain
self.x509CertificateSha1Thumbprint = x509CertificateSha1Thumbprint
self.x509CertificateSha256Thumbprint = x509CertificateSha256Thumbprint
self.d = d
self.x = x
self.y = y
}

// MARK: - Codable

Expand Down
34 changes: 17 additions & 17 deletions Sources/tbDEX/crypto/JWS.swift → Sources/Web5/Crypto/JWS.swift
Original file line number Diff line number Diff line change
@@ -1,72 +1,72 @@
import Foundation

/// [Specification Reference](https://datatracker.ietf.org/doc/html/rfc7515)]
struct JWS {
public struct JWS {

// Supported JWS algorithms
enum Algorithm: String, Codable {
public enum Algorithm: String, Codable {
case eddsa
case es256k
}

/// JWS JOSE Header
///
/// [Specification Reference](https://datatracker.ietf.org/doc/html/rfc7515#section-4)
struct Header: Codable {
public struct Header: Codable {

/// The "alg" (algorithm) Header Parameter identifies the cryptographic algorithm used to secure the JWS.
let algorithm: Algorithm
public let algorithm: Algorithm

/// The "jku" (JWK Set URL) Header Parameter is a URI [[RFC3986](https://datatracker.ietf.org/doc/html/rfc3986)]
/// that refers to a resource for a set of JSON-encoded public keys, one of which corresponds to the key used
/// to digitally sign the JWS.
let jwkSetURL: String?
public let jwkSetURL: String?

/// The "jwk" (JSON Web Key) Header Parameter is the public key that corresponds to the key used to digitally
/// sign the JWS.
let jwk: Jwk?
public let jwk: Jwk?

/// The "kid" (key ID) Header Parameter is a hint indicating which key was used to secure the JWS.
let keyID: String?
public let keyID: String?

/// The "x5u" (X.509 URL) Header Parameter is a URI [[RFC3986](https://datatracker.ietf.org/doc/html/rfc3986)]
/// that refers to a resource for the X.509 public key certificate or certificate chain
/// [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280) corresponding to the key used to digitally sign
/// the JWS.
let x509URL: String?
public let x509URL: String?

/// The "x5c" (X.509 certificate chain) Header Parameter contains the X.509 public key certificate or
/// certificate chain [[RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)] corresponding to the key used
/// to digitally sign the JWS.
let x509CertificateChain: String?
public let x509CertificateChain: String?

/// The "x5t" (X.509 certificate SHA-1 thumbprint) Header Parameter is a base64url-encoded SHA-1 thumbprint
/// (a.k.a. digest) of the DER encoding of the X.509 certificate
/// [[RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)] corresponding to the key used to digitally sign
/// the JWS.
let x509CertificateSHA1Thumbprint: String?
public let x509CertificateSHA1Thumbprint: String?

/// The "x5t#S256" (X.509 certificate SHA-256 thumbprint) Header Parameter is a base64url-encoded SHA-256
/// thumbprint (a.k.a. digest) of the DER encoding of the X.509 certificate
/// [[RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)] corresponding to the key used to digitally sign
/// the JWS.
let x509CertificateSHA256Thumbprint: String?
public let x509CertificateSHA256Thumbprint: String?

/// The "typ" (type) Header Parameter is used by JWS applications to declare the media type
/// [[IANA.MediaTypes](https://datatracker.ietf.org/doc/html/rfc7515#ref-IANA.MediaTypes)] of this complete JWS.
let type: String?
public let type: String?

/// The "cty" (content type) Header Parameter is used by JWS applications to declare the media type
/// [[IANA.MediaTypes](https://datatracker.ietf.org/doc/html/rfc7515#ref-IANA.MediaTypes)] of the secured
/// content (the payload).
let contentType: String?
public let contentType: String?

/// The "crit" (critical) Header Parameter indicates that extensions to this specification
/// and/or [[JWA](https://datatracker.ietf.org/doc/html/rfc7515#ref-JWA)] are being used that
/// MUST be understood and processed.
let critical: [String]?
public let critical: [String]?

init(
public init(
algorithm: JWS.Algorithm,
jwkSetURL: String? = nil,
jwk: Jwk? = nil,
Expand Down Expand Up @@ -111,7 +111,7 @@ struct JWS {
extension Jwk.Algorithm {

/// Converts a JWK algorithm to a JWS algorithm.
var jwsAlgorithm: JWS.Algorithm {
public var jwsAlgorithm: JWS.Algorithm {
switch self {
case .eddsa:
return .eddsa
Expand All @@ -124,7 +124,7 @@ extension Jwk.Algorithm {
extension JWS.Algorithm {

/// Converts a JWS algorithm to a JWK algorithm.
var jwkAlgorithm: Jwk.Algorithm {
public var jwkAlgorithm: Jwk.Algorithm {
switch self {
case .eddsa:
return .eddsa
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Foundation
/// Example implementations might provide key management through various Key Management Systems (KMS),
/// such as AWS KMS, Google Cloud KMS, Hardware Security Modules (HSM), or simple in-memory storage,
/// each adhering to the same consistent API for usage within applications.
protocol KeyManager {
public protocol KeyManager {

/// Generates and securely stores a private key based on the provided keyType,
/// returning a unique alias that can be utilized to reference the generated key for future operations.
Expand Down
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 36db15a

Please sign in to comment.