Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#74 extract kms #76

Merged
merged 12 commits into from
Feb 11, 2022
48 changes: 48 additions & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/WalletConnect.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,34 @@
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "KMS"
BuildableName = "KMS"
BlueprintName = "KMS"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "WalletConnectKMS"
BuildableName = "WalletConnectKMS"
BlueprintName = "WalletConnectKMS"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
Expand Down Expand Up @@ -124,6 +152,26 @@
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "KMSTests"
BuildableName = "KMSTests"
BlueprintName = "KMSTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "WalletConnectKMSTests"
BuildableName = "WalletConnectKMSTests"
BlueprintName = "WalletConnectKMSTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
Expand Down
18 changes: 11 additions & 7 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,38 @@ let package = Package(
.library(
name: "WalletConnect",
targets: ["WalletConnect"]),
],
dependencies: [

],
targets: [
.target(
name: "WalletConnect",
dependencies: ["Relayer", "WalletConnectUtils"],
dependencies: ["Relayer", "WalletConnectUtils", "WalletConnectKMS"],
path: "Sources/WalletConnect"),
.target(
name: "Relayer",
dependencies: ["WalletConnectUtils"],
path: "Sources/Relayer"),
.target(
name: "WalletConnectKMS",
dependencies: ["WalletConnectUtils"],
path: "Sources/WalletConnectKMS"),
.target(
name: "WalletConnectUtils",
dependencies: []),
.testTarget(
name: "WalletConnectTests",
dependencies: ["WalletConnect", "TestingUtils"]),
dependencies: ["WalletConnect", "TestingUtils", "WalletConnectKMS"]),
.testTarget(
name: "IntegrationTests",
dependencies: ["WalletConnect", "TestingUtils"]),
dependencies: ["WalletConnect", "TestingUtils", "WalletConnectKMS"]),
.testTarget(
name: "RelayerTests",
dependencies: ["Relayer", "WalletConnectUtils", "TestingUtils"]),
.testTarget(
name: "WalletConnectKMSTests",
dependencies: ["WalletConnectKMS", "WalletConnectUtils", "TestingUtils"]),
.target(
name: "TestingUtils",
dependencies: ["WalletConnectUtils"],
dependencies: ["WalletConnectUtils", "WalletConnectKMS"],
path: "Tests/TestingUtils"),
],
swiftLanguageVersions: [.v5]
Expand Down
17 changes: 0 additions & 17 deletions Sources/Relayer/Misc/Encodable.swift

This file was deleted.

29 changes: 14 additions & 15 deletions Sources/WalletConnect/Engine/PairingEngine.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import Foundation
import Combine
import WalletConnectUtils

import WalletConnectKMS

final class PairingEngine {

var onApprovalAcknowledgement: ((Pairing) -> Void)?
var onSessionProposal: ((SessionProposal)->())?
var onPairingApproved: ((Pairing, SessionPermissions, RelayProtocolOptions)->())?
var onPairingUpdate: ((String, AppMetadata)->())?

private let wcSubscriber: WCSubscribing
private let relayer: WalletConnectRelaying
private let crypto: CryptoStorageProtocol
private let kms: KeyManagementServiceProtocol
private let sequencesStore: PairingSequenceStorage
private var appMetadata: AppMetadata
private var publishers = [AnyCancellable]()
Expand All @@ -21,14 +20,14 @@ final class PairingEngine {
private let topicInitializer: () -> String?

init(relay: WalletConnectRelaying,
crypto: CryptoStorageProtocol,
kms: KeyManagementServiceProtocol,
subscriber: WCSubscribing,
sequencesStore: PairingSequenceStorage,
metadata: AppMetadata,
logger: ConsoleLogging,
topicGenerator: @escaping () -> String? = String.generateTopic) {
self.relayer = relay
self.crypto = crypto
self.kms = kms
self.wcSubscriber = subscriber
self.appMetadata = metadata
self.sequencesStore = sequencesStore
Expand Down Expand Up @@ -65,7 +64,7 @@ final class PairingEngine {
return nil
}

let publicKey = try! crypto.createX25519KeyPair()
let publicKey = try! kms.createX25519KeyPair()

let relay = RelayProtocolOptions(protocol: "waku", params: nil)
let uri = WalletConnectURI(topic: topic, publicKey: publicKey.hexRepresentation, isController: false, relay: relay)
Expand All @@ -86,8 +85,8 @@ final class PairingEngine {
throw WalletConnectError.internal(.pairWithExistingPairingForbidden)
}

let selfPublicKey = try! crypto.createX25519KeyPair()
let agreementKeys = try! crypto.performKeyAgreement(selfPublicKey: selfPublicKey, peerPublicKey: proposal.proposer.publicKey)
let selfPublicKey = try! kms.createX25519KeyPair()
let agreementKeys = try! kms.performKeyAgreement(selfPublicKey: selfPublicKey, peerPublicKey: proposal.proposer.publicKey)

let settledTopic = agreementKeys.derivedTopic()
let pendingPairing = PairingSequence.buildResponded(proposal: proposal, agreementKeys: agreementKeys)
Expand All @@ -98,7 +97,7 @@ final class PairingEngine {
wcSubscriber.setSubscription(topic: settledTopic)
sequencesStore.setSequence(settledPairing)

try? crypto.setAgreementSecret(agreementKeys, topic: settledTopic)
try? kms.setAgreementSecret(agreementKeys, topic: settledTopic)

let approval = PairingType.ApprovalParams(
relay: proposal.relay,
Expand Down Expand Up @@ -186,10 +185,10 @@ final class PairingEngine {
return
}

let agreementKeys = try! crypto.performKeyAgreement(selfPublicKey: try! pairing.getPublicKey(), peerPublicKey: approveParams.responder.publicKey)
let agreementKeys = try! kms.performKeyAgreement(selfPublicKey: try! pairing.getPublicKey(), peerPublicKey: approveParams.responder.publicKey)

let settledTopic = agreementKeys.sharedSecret.sha256().toHexString()
try? crypto.setAgreementSecret(agreementKeys, topic: settledTopic)
try? kms.setAgreementSecret(agreementKeys, topic: settledTopic)
let proposal = pendingPairing.proposal
let settledPairing = PairingSequence.buildAcknowledged(approval: approveParams, proposal: proposal, agreementKeys: agreementKeys)

Expand Down Expand Up @@ -237,8 +236,8 @@ final class PairingEngine {
}
let sessionProposal = payloadParams.request.params
do {
if let pairingAgreementSecret = try crypto.getAgreementSecret(for: sessionProposal.signal.params.topic) {
try crypto.setAgreementSecret(pairingAgreementSecret, topic: sessionProposal.topic)
if let pairingAgreementSecret = try kms.getAgreementSecret(for: sessionProposal.signal.params.topic) {
try kms.setAgreementSecret(pairingAgreementSecret, topic: sessionProposal.topic)
} else {
relayer.respondError(for: payload, reason: .missingOrInvalid("agreement keys"))
return
Expand Down Expand Up @@ -274,8 +273,8 @@ final class PairingEngine {

private func setupExpirationHandling() {
sequencesStore.onSequenceExpiration = { [weak self] topic, publicKey in
self?.crypto.deletePrivateKey(for: publicKey)
self?.crypto.deleteAgreementSecret(for: topic)
self?.kms.deletePrivateKey(for: publicKey)
self?.kms.deleteAgreementSecret(for: topic)
}
}

Expand Down
39 changes: 20 additions & 19 deletions Sources/WalletConnect/Engine/SessionEngine.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation
import Combine
import WalletConnectUtils
import WalletConnectKMS

final class SessionEngine {
var onSessionPayloadRequest: ((Request)->())?
Expand All @@ -16,21 +17,21 @@ final class SessionEngine {
private let sequencesStore: SessionSequenceStorage
private let wcSubscriber: WCSubscribing
private let relayer: WalletConnectRelaying
private let crypto: CryptoStorageProtocol
private let kms: KeyManagementServiceProtocol
private var metadata: AppMetadata
private var publishers = [AnyCancellable]()
private let logger: ConsoleLogging
private let topicInitializer: () -> String?

init(relay: WalletConnectRelaying,
crypto: CryptoStorageProtocol,
kms: KeyManagementServiceProtocol,
subscriber: WCSubscribing,
sequencesStore: SessionSequenceStorage,
metadata: AppMetadata,
logger: ConsoleLogging,
topicGenerator: @escaping () -> String? = String.generateTopic) {
self.relayer = relay
self.crypto = crypto
self.kms = kms
self.metadata = metadata
self.wcSubscriber = subscriber
self.sequencesStore = sequencesStore
Expand Down Expand Up @@ -64,7 +65,7 @@ final class SessionEngine {
}
logger.debug("Propose Session on topic: \(pendingSessionTopic)")

let publicKey = try! crypto.createX25519KeyPair()
let publicKey = try! kms.createX25519KeyPair()

let proposal = SessionProposal(
topic: pendingSessionTopic,
Expand All @@ -78,8 +79,8 @@ final class SessionEngine {

sequencesStore.setSequence(pendingSession)
wcSubscriber.setSubscription(topic: pendingSessionTopic)
let pairingAgreementSecret = try! crypto.getAgreementSecret(for: settledPairing.topic)!
try! crypto.setAgreementSecret(pairingAgreementSecret, topic: proposal.topic)
let pairingAgreementSecret = try! kms.getAgreementSecret(for: settledPairing.topic)!
try! kms.setAgreementSecret(pairingAgreementSecret, topic: proposal.topic)

let request = PairingType.PayloadParams.Request(method: .sessionPropose, params: proposal)
let pairingPayloadParams = PairingType.PayloadParams(request: request)
Expand All @@ -97,8 +98,8 @@ final class SessionEngine {
func approve(proposal: SessionProposal, accounts: Set<String>) {
logger.debug("Approve session")

let selfPublicKey = try! crypto.createX25519KeyPair()
let agreementKeys = try! crypto.performKeyAgreement(selfPublicKey: selfPublicKey, peerPublicKey: proposal.proposer.publicKey)
let selfPublicKey = try! kms.createX25519KeyPair()
let agreementKeys = try! kms.performKeyAgreement(selfPublicKey: selfPublicKey, peerPublicKey: proposal.proposer.publicKey)

let settledTopic = agreementKeys.derivedTopic()
let pendingSession = SessionSequence.buildResponded(proposal: proposal, agreementKeys: agreementKeys, metadata: metadata)
Expand All @@ -115,7 +116,7 @@ final class SessionEngine {
sequencesStore.setSequence(pendingSession)
wcSubscriber.setSubscription(topic: proposal.topic)

try! crypto.setAgreementSecret(agreementKeys, topic: settledTopic)
try! kms.setAgreementSecret(agreementKeys, topic: settledTopic)
sequencesStore.setSequence(settledSession)
wcSubscriber.setSubscription(topic: settledTopic)

Expand Down Expand Up @@ -295,9 +296,9 @@ final class SessionEngine {
let agreementKeys: AgreementSecret
do {
let publicKey = try session.getPublicKey()
agreementKeys = try crypto.performKeyAgreement(selfPublicKey: publicKey, peerPublicKey: approveParams.responder.publicKey)
agreementKeys = try kms.performKeyAgreement(selfPublicKey: publicKey, peerPublicKey: approveParams.responder.publicKey)
settledTopic = agreementKeys.derivedTopic()
try crypto.setAgreementSecret(agreementKeys, topic: settledTopic)
try kms.setAgreementSecret(agreementKeys, topic: settledTopic)
} catch {
relayer.respondError(for: payload, reason: .missingOrInvalid("agreement keys"))
return
Expand Down Expand Up @@ -449,8 +450,8 @@ final class SessionEngine {

private func setupExpirationHandling() {
sequencesStore.onSequenceExpiration = { [weak self] topic, publicKey in
self?.crypto.deletePrivateKey(for: publicKey)
self?.crypto.deleteAgreementSecret(for: topic)
self?.kms.deletePrivateKey(for: publicKey)
self?.kms.deleteAgreementSecret(for: topic)
}
}

Expand Down Expand Up @@ -487,8 +488,8 @@ final class SessionEngine {
break
case .error:
wcSubscriber.removeSubscription(topic: proposeParams.topic)
crypto.deletePrivateKey(for: proposeParams.proposer.publicKey)
crypto.deleteAgreementSecret(for: topic)
kms.deletePrivateKey(for: proposeParams.proposer.publicKey)
kms.deleteAgreementSecret(for: topic)
sequencesStore.delete(topic: proposeParams.topic)
}
}
Expand All @@ -504,7 +505,7 @@ final class SessionEngine {
switch result {
case .response:
guard let settledSession = sequencesStore.getSequence(forTopic: settledTopic) else {return}
crypto.deleteAgreementSecret(for: topic)
kms.deleteAgreementSecret(for: topic)
wcSubscriber.removeSubscription(topic: topic)
sequencesStore.delete(topic: topic)
let sessionSuccess = Session(
Expand All @@ -519,9 +520,9 @@ final class SessionEngine {
wcSubscriber.removeSubscription(topic: settledTopic)
sequencesStore.delete(topic: topic)
sequencesStore.delete(topic: settledTopic)
crypto.deleteAgreementSecret(for: topic)
crypto.deleteAgreementSecret(for: settledTopic)
crypto.deletePrivateKey(for: pendingSession.publicKey)
kms.deleteAgreementSecret(for: topic)
kms.deleteAgreementSecret(for: settledTopic)
kms.deletePrivateKey(for: pendingSession.publicKey)
}
}

Expand Down
20 changes: 0 additions & 20 deletions Sources/WalletConnect/Extensions/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,3 @@ extension String {
}
}

extension String {
func toHexEncodedString(uppercase: Bool = true, prefix: String = "", separator: String = "") -> String {
return unicodeScalars.map { prefix + .init($0.value, radix: 16, uppercase: uppercase) } .joined(separator: separator)
}
}

extension String: GenericPasswordConvertible {

init<D>(rawRepresentation data: D) throws where D : ContiguousBytes {
let bytes = data.withUnsafeBytes { Data(Array($0)) }
guard let string = String(data: bytes, encoding: .utf8) else {
fatalError() // FIXME: Throw error
}
self = string
}

var rawRepresentation: Data {
self.data(using: .utf8) ?? Data()
}
}
17 changes: 17 additions & 0 deletions Sources/WalletConnect/KeyManagementServiceProtocol.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

import Foundation
import WalletConnectKMS

// TODO: Come up with better naming conventions
public protocol KeyManagementServiceProtocol {
func createX25519KeyPair() throws -> AgreementPublicKey
func setPrivateKey(_ privateKey: AgreementPrivateKey) throws
func setAgreementSecret(_ agreementSecret: AgreementSecret, topic: String) throws
func getPrivateKey(for publicKey: AgreementPublicKey) throws -> AgreementPrivateKey?
func getAgreementSecret(for topic: String) throws -> AgreementSecret?
func deletePrivateKey(for publicKey: String)
func deleteAgreementSecret(for topic: String)
func performKeyAgreement(selfPublicKey: AgreementPublicKey, peerPublicKey hexRepresentation: String) throws -> AgreementSecret
}

extension KeyManagementService: KeyManagementServiceProtocol {}
Loading