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

feat(edgeAgent): KID will be present on any signed JWTs #170

Merged
merged 1 commit into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions EdgeAgentSDK/Apollo/Sources/ApolloImpl+Public.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extension ApolloImpl: Apollo {
guard
let keyType = parameters[KeyProperties.type.rawValue]
else { throw ApolloError.invalidKeyType(invalid: "", valid: ValidCryptographicTypes.allCases.map(\.rawValue)) }
let identifier = parameters[KeyProperties.kid.rawValue] ?? UUID().uuidString
switch keyType {
case ValidCryptographicTypes.ec.rawValue:
guard
Expand All @@ -63,7 +64,11 @@ extension ApolloImpl: Apollo {
let derivationPath = try parameters[KeyProperties.derivationPath.rawValue].map {
try DerivationPath(string: $0)
} ?? DerivationPath()
return Secp256k1PrivateKey(raw: keyData, derivationPath: derivationPath)
return Secp256k1PrivateKey(
identifier: identifier,
raw: keyData,
derivationPath: derivationPath
)
} else {
guard
let derivationPathStr = parameters[KeyProperties.derivationPath.rawValue],
Expand All @@ -76,6 +81,7 @@ extension ApolloImpl: Apollo {
}
let derivationPath = try DerivationPath(string: derivationPathStr)
return try CreateSec256k1KeyPairOperation().compute(
identifier: identifier,
seed: Seed(value: seed),
keyPath: derivationPath
)
Expand All @@ -85,37 +91,45 @@ extension ApolloImpl: Apollo {
let keyStr = parameters[KeyProperties.rawKey.rawValue],
let keyData = Data(base64Encoded: keyStr)
{
return try CreateEd25519KeyPairOperation(logger: ApolloImpl.logger).compute(fromPrivateKey: keyData)
return try CreateEd25519KeyPairOperation(logger: ApolloImpl.logger).compute(
identifier: identifier,
fromPrivateKey: keyData
)
} else if
let derivationPathStr = parameters[KeyProperties.derivationPath.rawValue],
let seedStr = parameters[KeyProperties.seed.rawValue],
let seed = Data(base64Encoded: seedStr)
{
let derivationPath = try DerivationPath(string: derivationPathStr)
return try CreateEd25519KeyPairOperation(logger: ApolloImpl.logger).compute(
identifier: identifier,
seed: Seed(value: seed),
keyPath: derivationPath
)
}
return CreateEd25519KeyPairOperation(logger: ApolloImpl.logger).compute()
return CreateEd25519KeyPairOperation(logger: ApolloImpl.logger).compute(identifier: identifier)
case .x25519:
if
let keyStr = parameters[KeyProperties.rawKey.rawValue],
let keyData = Data(base64Encoded: keyStr)
{
return try CreateX25519KeyPairOperation(logger: ApolloImpl.logger).compute(fromPrivateKey: keyData)
return try CreateX25519KeyPairOperation(logger: ApolloImpl.logger).compute(
identifier: identifier,
fromPrivateKey: keyData
)
} else if
let derivationPathStr = parameters[KeyProperties.derivationPath.rawValue],
let seedStr = parameters[KeyProperties.seed.rawValue],
let seed = Data(base64Encoded: seedStr)
{
let derivationPath = try DerivationPath(string: derivationPathStr)
return try CreateX25519KeyPairOperation(logger: ApolloImpl.logger).compute(
identifier: identifier,
seed: Seed(value: seed),
keyPath: derivationPath
)
}
return CreateX25519KeyPairOperation(logger: ApolloImpl.logger).compute()
return CreateX25519KeyPairOperation(logger: ApolloImpl.logger).compute(identifier: identifier)
}
default:
throw ApolloError.invalidKeyType(invalid: keyType, valid: ValidCryptographicTypes.allCases.map(\.rawValue))
Expand All @@ -126,6 +140,7 @@ extension ApolloImpl: Apollo {
guard
let keyType = parameters[KeyProperties.type.rawValue]
else { throw ApolloError.invalidKeyType(invalid: "", valid: ValidCryptographicTypes.allCases.map(\.rawValue)) }
let identifier = parameters[KeyProperties.kid.rawValue] ?? UUID().uuidString
switch keyType {
case ValidCryptographicTypes.ec.rawValue:
guard
Expand All @@ -140,12 +155,12 @@ extension ApolloImpl: Apollo {
switch curve {
case .secp256k1:
if let keyData = parameters[KeyProperties.rawKey.rawValue].flatMap({ Data(base64Encoded: $0) }) {
return Secp256k1PublicKey(raw: keyData)
return Secp256k1PublicKey(identifier: identifier, raw: keyData)
} else if
let x = parameters[KeyProperties.curvePointX.rawValue].flatMap({ Data(base64Encoded: $0) }),
let y = parameters[KeyProperties.curvePointY.rawValue].flatMap({ Data(base64Encoded: $0) })
{
return Secp256k1PublicKey(x: x, y: y)
return Secp256k1PublicKey(identifier: identifier, x: x, y: y)
} else {
throw ApolloError.missingKeyParameters(missing: [
KeyProperties.rawKey.rawValue,
Expand All @@ -159,14 +174,14 @@ extension ApolloImpl: Apollo {
else {
throw ApolloError.missingKeyParameters(missing: [KeyProperties.rawKey.rawValue])
}
return Ed25519PublicKey(raw: keyData)
return Ed25519PublicKey(identifier: identifier, raw: keyData)
case .x25519:
guard
let keyData = parameters[KeyProperties.rawKey.rawValue].flatMap({ Data(base64Encoded: $0) })
else {
throw ApolloError.missingKeyParameters(missing: [KeyProperties.rawKey.rawValue])
}
return X25519PublicKey(raw: keyData)
return X25519PublicKey(identifier: identifier, raw: keyData)
}
default:
throw ApolloError.invalidKeyType(invalid: keyType, valid: ValidCryptographicTypes.allCases.map(\.rawValue))
Expand Down
2 changes: 1 addition & 1 deletion EdgeAgentSDK/Apollo/Sources/Model/Ed25519Key.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ struct Ed25519PublicKey: PublicKey {
self.internalKey = internalKey
}

init(raw: Data) {
init(identifier: String = UUID().uuidString, raw: Data) {
self.init(internalKey: .init(raw: raw.toKotlinByteArray()))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extension Secp256k1PrivateKey: ExportableKey {
var jwk: JWK {
JWK(
kty: "EC",
kid: identifier,
d: raw.base64UrlEncodedString(),
crv: getProperty(.curve)?.lowercased(),
x: publicKey().getProperty(.curvePointX).flatMap { Data(fromBase64URL: $0)?.base64UrlEncodedString() },
Expand Down Expand Up @@ -42,6 +43,7 @@ extension Secp256k1PublicKey: ExportableKey {
var jwk: JWK {
JWK(
kty: "EC",
kid: identifier,
crv: getProperty(.curve)?.lowercased(),
x: getProperty(.curvePointX)
.flatMap { Data(fromBase64URL: $0)?.base64UrlEncodedString() } ?? raw.base64UrlEncodedString(),
Expand Down
7 changes: 4 additions & 3 deletions EdgeAgentSDK/Apollo/Sources/Model/Secp256k1Key.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ struct Secp256k1PrivateKey: PrivateKey {
self.size = internalKey.raw.toData().count
}

init(raw: Data, derivationPath: Domain.DerivationPath) {
init(identifier: String, raw: Data, derivationPath: Domain.DerivationPath) {
self.init(
identifier: identifier,
internalKey: KMMECSecp256k1PrivateKey(raw: raw.toKotlinByteArray()),
derivationPath: derivationPath
)
Expand Down Expand Up @@ -91,7 +92,7 @@ struct Secp256k1PublicKey: PublicKey {
self.raw = internalKey.raw.toData()
}

init(x: Data, y: Data) {
init(identifier: String = UUID().uuidString, x: Data, y: Data) {
self.init(
internalKey: .Companion().secp256k1FromByteCoordinates(
x: x.toKotlinByteArray(),
Expand All @@ -100,7 +101,7 @@ struct Secp256k1PublicKey: PublicKey {
)
}

init(raw: Data) {
init(identifier: String = UUID().uuidString, raw: Data) {
self.init(internalKey: .Companion().secp256k1FromBytes(encoded: raw.toKotlinByteArray()))
}

Expand Down
2 changes: 1 addition & 1 deletion EdgeAgentSDK/Apollo/Sources/Model/X25519Key.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct X25519PublicKey: PublicKey {
self.internalKey = internalKey
}

init(raw: Data) {
init(identifier: String = UUID().uuidString, raw: Data) {
self.init(internalKey: .init(raw: raw.toKotlinByteArray()))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import Foundation
struct CreateEd25519KeyPairOperation {
let logger: SDKLogger

func compute() -> PrivateKey {
func compute(identifier: String = UUID().uuidString) -> PrivateKey {
let privateKey = KMMEdKeyPair.Companion().generateKeyPair().privateKey
return Ed25519PrivateKey(internalKey: privateKey)
return Ed25519PrivateKey(identifier: identifier, internalKey: privateKey)

}

Expand All @@ -24,7 +24,7 @@ struct CreateEd25519KeyPairOperation {
)
}

func compute(seed: Seed, keyPath: Domain.DerivationPath) throws -> PrivateKey {
func compute(identifier: String, seed: Seed, keyPath: Domain.DerivationPath) throws -> PrivateKey {
let derivedHdKey = ApolloLibrary
.EdHDKey
.companion
Expand All @@ -33,6 +33,7 @@ struct CreateEd25519KeyPairOperation {
)

return Ed25519PrivateKey(
identifier: identifier,
internalKey: .init(raw: derivedHdKey.privateKey),
derivationPath: keyPath
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ struct CreateSec256k1KeyPairOperation {
self.logger = logger
}

func compute(seed: Seed, keyPath: Domain.DerivationPath) throws -> PrivateKey {
func compute(identifier: String, seed: Seed, keyPath: Domain.DerivationPath) throws -> PrivateKey {
let derivedHdKey = ApolloLibrary.HDKey(
seed: seed.value.toKotlinByteArray(),
depth: 0,
childIndex: 0
).derive(path: keyPath.keyPathString())
return Secp256k1PrivateKey(internalKey: derivedHdKey.getKMMSecp256k1PrivateKey(), derivationPath: keyPath)

return Secp256k1PrivateKey(
identifier: identifier,
internalKey: derivedHdKey.getKMMSecp256k1PrivateKey(),
derivationPath: keyPath
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import Foundation
struct CreateX25519KeyPairOperation {
let logger: SDKLogger

func compute() -> PrivateKey {
func compute(identifier: String = UUID().uuidString) -> PrivateKey {
let privateKey = KMMX25519KeyPair.Companion().generateKeyPair().privateKey
return X25519PrivateKey(internalKey: privateKey)
return X25519PrivateKey(identifier: identifier, internalKey: privateKey)

}

Expand All @@ -26,7 +26,7 @@ struct CreateX25519KeyPairOperation {
)
}

func compute(seed: Seed, keyPath: Domain.DerivationPath) throws -> PrivateKey {
func compute(identifier: String, seed: Seed, keyPath: Domain.DerivationPath) throws -> PrivateKey {
let derivedHdKey = ApolloLibrary
.EdHDKey
.companion
Expand All @@ -35,6 +35,7 @@ struct CreateX25519KeyPairOperation {
)

return X25519PrivateKey(
identifier: identifier,
internalKey: KMMEdPrivateKey(raw: derivedHdKey.privateKey).x25519PrivateKey(),
derivationPath: keyPath
)
Expand Down
14 changes: 7 additions & 7 deletions EdgeAgentSDK/Castor/Sources/Resolvers/PeerDIDResolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ extension DIDCore.DIDDocument {

self.init(
id: from.id.string,
verificationMethods: verificationMethods + authenticationMethods + keyAgreementMethods,
verificationMethod: verificationMethods + authenticationMethods + keyAgreementMethods,
authentication: authenticationIds.map { .stringValue($0) },
assertionMethod: nil,
capabilityDelegation: nil,
Expand All @@ -65,7 +65,7 @@ extension DIDCore.DIDDocument {
}

func toDomain() throws -> Domain.DIDDocument {
let authenticationUrls = self.verificationMethods
let authenticationUrls = self.verificationMethod?
.filter {
guard let type = KnownVerificationMaterialType(rawValue: $0.type) else {
return false
Expand All @@ -77,9 +77,9 @@ extension DIDCore.DIDDocument {
return false
}
}
.map { $0.id }
.map { $0.id } ?? []

let keyAgreementUrls = self.verificationMethods
let keyAgreementUrls = self.verificationMethod?
.filter {
guard let type = KnownVerificationMaterialType(rawValue: $0.type) else {
return false
Expand All @@ -91,11 +91,11 @@ extension DIDCore.DIDDocument {
return false
}
}
.map { $0.id }
.map { $0.id } ?? []

let verificationMethods = try self.verificationMethods.map {
let verificationMethods = try self.verificationMethod?.map {
try $0.toDomain()
}
} ?? []

let services = try self.services?.map {
let service = try DIDCore.DIDDocument.Service(from: $0)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Core
import Domain
import Foundation

Expand Down Expand Up @@ -29,17 +30,13 @@ public extension DIDCommAgent {
/// - Returns: The parsed Out-of-Band invitation
/// - Throws: `EdgeAgentError` if the string is not a valid URL
func parseOOBInvitation(url: String) throws -> OutOfBandInvitation {
guard let messageData = Data(fromBase64URL: url) else {
guard let url = URL(string: url) else {
throw CommonError.invalidURLError(url: url)
}
if let base64url = Data(base64URLEncoded: url) {
return try JSONDecoder.didComm().decode(OutOfBandInvitation.self, from: base64url)
} else if let url = URL(string: url) {
return try parseOOBInvitation(url: url)
} else {
throw CommonError.invalidURLError(url: url)
}
let message = try JSONDecoder.didComm().decode(OutOfBandInvitation.self, from: messageData)
guard message.type == ProtocolTypes.didcomminvitation.rawValue else {
throw EdgeAgentError.unknownInvitationTypeError
}
return message
}

/// Parses the given URL as an Out-of-Band invitation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Could not find key in storage please use Castor instead and provide the private
let apollo = self.apollo
let castor = self.castor

let usingPrivateKey: PrivateKey
var usingPrivateKey: PrivateKey

if let masterPrivateKey {
usingPrivateKey = masterPrivateKey
Expand All @@ -94,7 +94,12 @@ Could not find key in storage please use Castor instead and provide the private
])
}

let newDID = try castor.createPrismDID(masterPublicKey: usingPrivateKey.publicKey(), services: services)
var publicKey = usingPrivateKey.publicKey()

let newDID = try castor.createPrismDID(masterPublicKey: publicKey, services: services)
let kid = DIDUrl(did: newDID, fragment: "#authentication0").string
usingPrivateKey.identifier = kid
publicKey.identifier = kid
logger.debug(message: "Created new Prism DID", metadata: [
.maskedMetadataByLevel(key: "DID", value: newDID.string, level: .debug),
.maskedMetadataByLevel(key: "keyPathIndex", value: "\(index)", level: .debug)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,17 @@ final class PresentationExchangeFlowTests: XCTestCase {
vc: .init(credentialSubject: ["test": "aliceTest"])
)

let jwsHeader = DefaultJWSHeaderImpl(algorithm: .ES256K)
guard
guard
let key = try await edgeAgent.pluto.getDIDPrivateKeys(did: issuerDID).first().await()?.first,
let jwkD = try await edgeAgent.apollo.restorePrivateKey(key).exporting?.jwk
else {
XCTFail()
fatalError()
}
let jwsHeader = DefaultJWSHeaderImpl(
algorithm: .ES256K,
keyID: jwkD.kid
)
return try JWT.signed(payload: payload, protectedHeader: jwsHeader, key: jwkD.toJoseJWK()).jwtString
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ extension DIDCore.DIDDocument {
}
self.init(
id: from.id.string,
verificationMethods: verificationMethods,
verificationMethod: verificationMethods,
authentication: authentications.map { .stringValue($0) },
keyAgreement: keyAgreements.map { .stringValue($0) },
services: services.map { $0.toAnyCodable() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,10 @@ struct JWTPresentation {

let jwt = try JWT.signed(
payload: payload,
protectedHeader: DefaultJWSHeaderImpl(algorithm: .ES256K),
protectedHeader: DefaultJWSHeaderImpl(
algorithm: .ES256K,
keyID: keyJWK.kid
),
key: JSONWebKey.JWK(
keyType: .init(rawValue: keyJWK.kty)!,
keyID: keyJWK.kid,
Expand Down
Loading
Loading