Skip to content

Commit

Permalink
feat(agent): enable did comm
Browse files Browse the repository at this point in the history
Release 0.2

There were quite a few assumptions that changed. Therefore the huge amount of changes, important notes below:
- Now pluto will persist 2 keys for DIDPeer. TODO: Change to be an array of keys
- Added DIDcomm integration with our DIDResolver and SecretsResolver
- SecretsResolver is working but TODO move it to a more proper place
- Changed Keys models to support an enum of Curves

Fixes ATL-2698
  • Loading branch information
goncalo-frade-iohk committed Dec 9, 2022
1 parent 4f9948e commit e8e1fd8
Show file tree
Hide file tree
Showing 60 changed files with 884 additions and 381 deletions.
1 change: 1 addition & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,5 @@ identifier_name:
- id
- ec
- to
- cb # this is due to the didcomm library using this parameter name
reporter: "xcode"
27 changes: 27 additions & 0 deletions Apollo/Sources/ApolloImpl+Public.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ returns random mnemonics nerver returns invalid mnemonics
}
}

public func createKeyPair(seed: Seed, privateKey: PrivateKey) throws -> KeyPair {
switch privateKey.curve {
case .secp256k1:
return createKeyPair(seed: seed, curve: privateKey.curve)
case .x25519:
return try CreateX25519KeyPairOperation(logger: ApolloImpl.logger)
.compute(fromPrivateKey: privateKey)
case .ed25519:
return try CreateEd25519KeyPairOperation(logger: ApolloImpl.logger)
.compute(fromPrivateKey: privateKey)
}
}

public func compressedPublicKey(publicKey: PublicKey) -> CompressedPublicKey {
publicKey.compressed()
}
Expand Down Expand Up @@ -67,4 +80,18 @@ returns random mnemonics nerver returns invalid mnemonics
signature: signature
).compute()
}

public func getPrivateJWKJson(id: String, keyPair: KeyPair) throws -> String {
guard
let jsonString = try OctetKeyPair(id: id, from: keyPair).privateJson
else { throw CommonError.somethingWentWrongError }
return jsonString
}

public func getPublicJWKJson(id: String, keyPair: KeyPair) throws -> String {
guard
let jsonString = try OctetKeyPair(id: id, from: keyPair).privateJson
else { throw CommonError.somethingWentWrongError }
return jsonString
}
}
4 changes: 2 additions & 2 deletions Apollo/Sources/Extensions/PrivateKey+Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation
import PrismAPI

extension Domain.PrivateKey {
init(fromEC: ECPrivateKey) {
self.init(curve: ECConfig().CURVE_NAME, value: fromEC.getEncoded().toData())
init(curve: KeyCurve, fromEC: ECPrivateKey) {
self.init(curve: curve, value: fromEC.getEncoded().toData())
}
}
94 changes: 94 additions & 0 deletions Apollo/Sources/Model/OctetKeyPair.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import Core
import Domain
import Foundation

struct OctetKeyPair {
struct PublicJson: Codable {
enum CodingKeys: String, CodingKey {
case kty
case kid
case crv
case publicKey = "x"
}

let kty = "OKP"
let kid: String
let crv: String
let publicKey: String

init(kid: String, crv: String, publicKey: String) {
self.kid = kid
self.crv = crv
self.publicKey = publicKey
}
}

struct PrivateJson: Codable {
enum CodingKeys: String, CodingKey {
case kty
case kid
case crv
case publicKey = "x"
case privateKey = "d"
}

let kty = "OKP"
let kid: String
let crv: String
let privateKey: String
let publicKey: String

init(kid: String, crv: String, privateKey: String, publicKey: String) {
self.kid = kid
self.crv = crv
self.privateKey = privateKey
self.publicKey = publicKey
}
}

let kty = "OKP"
let kid: String
let crv: String
let privateKey: String
let publicKey: String

init(id: String, from: KeyPair) throws {
self.init(
kid: id,
crv: from.curve.name,
privateKey: from.privateKey.value.base64UrlEncodedString(),
publicKey: from.publicKey.value.base64UrlEncodedString()
)
}

init(kid: String, crv: String, privateKey: String, publicKey: String) {
self.kid = kid
self.crv = crv
self.privateKey = privateKey
self.publicKey = publicKey
}

var publicJson: String? {
let publicJson = PublicJson(
kid: kid,
crv: crv,
publicKey: publicKey
)
guard let dataJson = try? JSONEncoder().encode(publicJson) else {
return nil
}
return String(data: dataJson, encoding: .utf8)
}
var privateJson: String? {
let privateJson = PrivateJson(
kid: kid,
crv: crv,
privateKey: privateKey,
publicKey: publicKey
)
guard let dataJson = try? JSONEncoder().encode(privateJson) else {
return nil
}
return String(data: dataJson, encoding: .utf8)
}
}
13 changes: 12 additions & 1 deletion Apollo/Sources/Operations/CreateEd25519KeyPairOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,19 @@ struct CreateEd25519KeyPairOperation {
let publicKey = privateKey.publicKey
return KeyPair(
curve: .ed25519,
privateKey: .init(curve: "Ed25519", value: privateKey.rawRepresentation),
privateKey: .init(curve: .ed25519, value: privateKey.rawRepresentation),
publicKey: .init(curve: "Ed25519", value: publicKey.rawRepresentation)
)
}

func compute(fromPrivateKey: PrivateKey) throws -> KeyPair {
let privateKey = try Curve25519
.Signing
.PrivateKey(rawRepresentation: fromPrivateKey.value)
return KeyPair(
curve: fromPrivateKey.curve,
privateKey: fromPrivateKey,
publicKey: .init(curve: "Ed25519", value: privateKey.publicKey.rawRepresentation)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct CreateSec256k1KeyPairOperation {

return KeyPair(
curve: .secp256k1(index: keyPath.index),
privateKey: PrivateKey(fromEC: newKey.keyPair().privateKey),
privateKey: PrivateKey(curve: .secp256k1(index: keyPath.index), fromEC: newKey.keyPair().privateKey),
publicKey: PublicKey(fromEC: newKey.keyPair().publicKey)
)
}
Expand Down
13 changes: 12 additions & 1 deletion Apollo/Sources/Operations/CreateX25519KeyPairOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,19 @@ struct CreateX25519KeyPairOperation {
let publicKey = privateKey.publicKey
return KeyPair(
curve: .x25519,
privateKey: .init(curve: "X25519", value: privateKey.rawRepresentation),
privateKey: .init(curve: .x25519, value: privateKey.rawRepresentation),
publicKey: .init(curve: "X25519", value: publicKey.rawRepresentation)
)
}

func compute(fromPrivateKey: PrivateKey) throws -> KeyPair {
let privateKey = try Curve25519
.KeyAgreement
.PrivateKey(rawRepresentation: fromPrivateKey.value)
return KeyPair(
curve: fromPrivateKey.curve,
privateKey: fromPrivateKey,
publicKey: .init(curve: "X25519", value: privateKey.publicKey.rawRepresentation)
)
}
}
14 changes: 13 additions & 1 deletion Builders/Sources/MercuryBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,33 @@ import Foundation
import Mercury

public struct MercuryBuilder {
let apollo: Apollo
let castor: Castor
let pluto: Pluto
let session: URLSession
let timeout: TimeInterval

public init(
apollo: Apollo,
castor: Castor,
pluto: Pluto,
session: URLSession = .shared,
timeout: TimeInterval = 30
) {
self.apollo = apollo
self.castor = castor
self.pluto = pluto
self.session = session
self.timeout = timeout
}

public func build() -> Mercury {
MercuryImpl(session: session, timeout: timeout, castor: castor)
MercuryImpl(
session: session,
timeout: timeout,
apollo: apollo,
castor: castor,
pluto: pluto
)
}
}
18 changes: 13 additions & 5 deletions Castor/Sources/CastorImpl+Public.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,18 @@ extension CastorImpl: Castor {

public func resolveDID(did: DID) async throws -> DIDDocument {
guard
let document = try await resolvers
.first?
.resolve(did: did)
else { throw CastorError.notPossibleToResolveDID }
return document
let resolver = resolvers.first(where: { $0.method == did.method })
else {
throw CastorError.notPossibleToResolveDID
}
return try await resolver.resolve(did: did)
}

public func getEcnumbasis(did: DID, keyPair: KeyPair) throws -> String {
try CreatePeerDIDOperation(
autenticationKeyPair: keyPair,
agreementKeyPair: keyPair,
services: []
).computeEcnumbasis(did: did, keyPair: keyPair)
}
}
2 changes: 1 addition & 1 deletion Castor/Sources/CastorImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public struct CastorImpl {
public init(apollo: Apollo, resolvers: [DIDResolverDomain] = []) {
self.apollo = apollo
self.resolvers = resolvers + [
// LongFormPrismDIDResolver(apollo: apollo),
LongFormPrismDIDResolver(apollo: apollo),
PeerDIDResolver()
]
}
Expand Down
4 changes: 2 additions & 2 deletions Castor/Sources/DID/PeerDID/PeerDID.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ struct PeerDID {
let type = try container.decode(String.self, forKey: .type)
self.type = type == "dm" ? "DIDCommMessaging" : type
self.serviceEndpoint = try container.decode(String.self, forKey: .serviceEndpoint)
self.routingKeys = try container.decode([String].self, forKey: .routingKeys)
self.accept = try container.decode([String].self, forKey: .accept)
self.routingKeys = (try? container.decode([String].self, forKey: .routingKeys)) ?? []
self.accept = (try? container.decode([String].self, forKey: .accept)) ?? []
}
}

Expand Down
1 change: 1 addition & 0 deletions Castor/Sources/Helpers/JWK+Helper.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Core
import Domain
import Foundation

Expand Down
18 changes: 0 additions & 18 deletions Castor/Sources/Helpers/Json+Helpers.swift

This file was deleted.

16 changes: 16 additions & 0 deletions Castor/Sources/Operations/CreatePeerDIDOperation.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Core
import Domain
import Foundation
import Multibase

struct CreatePeerDIDOperation {
enum Numalgo2Prefix: String {
Expand Down Expand Up @@ -34,6 +35,21 @@ struct CreatePeerDIDOperation {
).did
}

func computeEcnumbasis(did: DID, keyPair: KeyPair) throws -> String {
switch keyPair.curve {
case .x25519:
let material = try keyAgreementFromKeyPair(keyPair: keyPair)
let multibaseEcnumbasis = try createMultibaseEncnumbasis(material: material)
return String(multibaseEcnumbasis.dropFirst())
case .ed25519:
let material = try authenticationFromKeyPair(keyPair: keyPair)
let multibaseEcnumbasis = try createMultibaseEncnumbasis(material: material)
return String(multibaseEcnumbasis.dropFirst())
default:
throw CommonError.somethingWentWrongError
}
}

private func createPeerDID(
encryptionKeys: [VerificationMaterialAgreement],
signingKeys: [VerificationMaterialAuthentication],
Expand Down
2 changes: 2 additions & 0 deletions Castor/Sources/Resolvers/LongFormPrismDIDResolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import Foundation
struct LongFormPrismDIDResolver: DIDResolverDomain {
let apollo: Apollo

var method = "prism"

func resolve(did: DID) throws -> DIDDocument {
let prismDID = try LongFormPrismDID(did: did)
guard
Expand Down
Loading

0 comments on commit e8e1fd8

Please sign in to comment.