Fix nits from last PR
This commit is contained in:
Родитель
2d57a27529
Коммит
8073174d98
|
@ -24,6 +24,7 @@
|
|||
551F3068252E97000081D5E7 /* IdentifierCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 551F3067252E97000081D5E7 /* IdentifierCreator.swift */; };
|
||||
55253976252FCA6D003202D5 /* VCCrypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55253975252FCA6D003202D5 /* VCCrypto.framework */; };
|
||||
55253977252FCA6D003202D5 /* VCCrypto.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 55253975252FCA6D003202D5 /* VCCrypto.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
55253982252FDF89003202D5 /* KeyContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55253981252FDF89003202D5 /* KeyContainer.swift */; };
|
||||
55575738251BC575009979AB /* VCEntities.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5557572E251BC575009979AB /* VCEntities.framework */; };
|
||||
5557573D251BC575009979AB /* VCEntitiesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5557573C251BC575009979AB /* VCEntitiesTests.swift */; };
|
||||
5557573F251BC575009979AB /* VCEntities.h in Headers */ = {isa = PBXBuildFile; fileRef = 55575731251BC575009979AB /* VCEntities.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
|
@ -123,6 +124,7 @@
|
|||
551F3065252E71680081D5E7 /* MultihashTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultihashTests.swift; sourceTree = "<group>"; };
|
||||
551F3067252E97000081D5E7 /* IdentifierCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentifierCreator.swift; sourceTree = "<group>"; };
|
||||
55253975252FCA6D003202D5 /* VCCrypto.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = VCCrypto.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
55253981252FDF89003202D5 /* KeyContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyContainer.swift; sourceTree = "<group>"; };
|
||||
5557572E251BC575009979AB /* VCEntities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = VCEntities.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
55575731251BC575009979AB /* VCEntities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VCEntities.h; sourceTree = "<group>"; };
|
||||
55575732251BC575009979AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -353,6 +355,7 @@
|
|||
55AF7482252F6A7E006A8B25 /* document */,
|
||||
55AF748D252F6BE0006A8B25 /* Identifier.swift */,
|
||||
551F3067252E97000081D5E7 /* IdentifierCreator.swift */,
|
||||
55253981252FDF89003202D5 /* KeyContainer.swift */,
|
||||
);
|
||||
path = identifier;
|
||||
sourceTree = "<group>";
|
||||
|
@ -584,6 +587,7 @@
|
|||
5518CC7625264D5700C7A21B /* ResponseMappings.swift in Sources */,
|
||||
551F3068252E97000081D5E7 /* IdentifierCreator.swift in Sources */,
|
||||
551F305B252E39540081D5E7 /* IdentifierFormatter.swift in Sources */,
|
||||
55253982252FDF89003202D5 /* KeyContainer.swift in Sources */,
|
||||
557BFC53251E665D005B5B24 /* IssuanceResponseFormatter.swift in Sources */,
|
||||
5584E4A02525656500A9DE58 /* SchemaDescriptor.swift in Sources */,
|
||||
55575766251BC6CF009979AB /* LogoDisplayDescriptor.swift in Sources */,
|
||||
|
|
|
@ -14,6 +14,6 @@ func createTokenTimeConstraints(expiryInSeconds: Int) -> TokenTimeConstraints {
|
|||
}
|
||||
|
||||
func formatHeaders(usingIdentifier identifier: Identifier, andSigningKey key: KeyContainer) -> Header {
|
||||
let keyId = identifier.longformId + "#" + key.keyId
|
||||
let keyId = identifier.longFormDid + "#" + key.keyId
|
||||
return Header(type: jwtType, algorithm: key.algorithm, keyId: keyId)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import VCJwt
|
||||
|
||||
protocol IdentifierFormatting {
|
||||
func createIonLongForm(recoveryKey: ECPublicJwk,
|
||||
func createIonLongFormDid(recoveryKey: ECPublicJwk,
|
||||
updateKey: ECPublicJwk,
|
||||
didDocumentKeys: [ECPublicJwk],
|
||||
serviceEndpoints: [IdentifierDocumentServiceEndpoint]) throws -> String
|
||||
|
@ -17,18 +17,18 @@ struct IdentifierFormatter: IdentifierFormatting {
|
|||
private let multihash: Multihash = Multihash()
|
||||
private let encoder: JSONEncoder = JSONEncoder()
|
||||
|
||||
private let ionPrefix = "did:ion:"
|
||||
private let ionQueryValue = "?-ion-initial-state="
|
||||
private let replaceAction = "replace"
|
||||
private static let ionPrefix = "did:ion:"
|
||||
private static let ionQueryValue = "?-ion-initial-state="
|
||||
private static let replaceAction = "replace"
|
||||
|
||||
func createIonLongForm(recoveryKey: ECPublicJwk,
|
||||
func createIonLongFormDid(recoveryKey: ECPublicJwk,
|
||||
updateKey: ECPublicJwk,
|
||||
didDocumentKeys: [ECPublicJwk],
|
||||
serviceEndpoints: [IdentifierDocumentServiceEndpoint]) throws -> String {
|
||||
|
||||
let document = IdentifierDocument(fromJwks: didDocumentKeys, andServiceEndpoints: serviceEndpoints)
|
||||
|
||||
let patches = [IdentifierDocumentPatch(action: replaceAction, document: document)]
|
||||
let patches = [IdentifierDocumentPatch(action: IdentifierFormatter.replaceAction, document: document)]
|
||||
|
||||
let commitmentHash = try self.createCommitmentHash(usingJwk: updateKey)
|
||||
let delta = IdentifierDocumentDeltaDescriptor(updateCommitment: commitmentHash, patches: patches)
|
||||
|
@ -46,7 +46,7 @@ struct IdentifierFormatter: IdentifierFormatting {
|
|||
|
||||
let shortForm = try self.createShortFormIdentifier(usingSuffixData: suffixData)
|
||||
|
||||
return shortForm + ionQueryValue + encodedPayload
|
||||
return shortForm + IdentifierFormatter.ionQueryValue + encodedPayload
|
||||
}
|
||||
|
||||
private func createShortFormIdentifier(usingSuffixData data: SuffixDescriptor) throws -> String {
|
||||
|
@ -54,7 +54,7 @@ struct IdentifierFormatter: IdentifierFormatting {
|
|||
let encodedData = try encoder.encode(data)
|
||||
let hashedSuffixData = multihash.compute(from: encodedData).base64URLEncodedString()
|
||||
|
||||
return ionPrefix + hashedSuffixData
|
||||
return IdentifierFormatter.ionPrefix + hashedSuffixData
|
||||
}
|
||||
|
||||
private func createSuffixData(usingDelta delta: IdentifierDocumentDeltaDescriptor, recoveryKey: ECPublicJwk) throws -> SuffixDescriptor {
|
||||
|
|
|
@ -37,7 +37,7 @@ public class IssuanceResponseFormatter: IssuanceResponseFormatting {
|
|||
|
||||
return IssuanceResponseClaims(publicKeyThumbprint: try publicKey.getThumbprint(),
|
||||
audience: response.audience,
|
||||
did: identifier.longformId,
|
||||
did: identifier.longFormDid,
|
||||
publicJwk: publicKey,
|
||||
contract: response.contractUri,
|
||||
jti: UUID().uuidString,
|
||||
|
|
|
@ -49,7 +49,7 @@ public class PresentationResponseFormatter: PresentationResponseFormatting {
|
|||
|
||||
return PresentationResponseClaims(publicKeyThumbprint: try publicKey.getThumbprint(),
|
||||
audience: response.request.content.redirectURI,
|
||||
did: identifier.longformId,
|
||||
did: identifier.longFormDid,
|
||||
publicJwk: publicKey,
|
||||
jti: UUID().uuidString,
|
||||
presentationSubmission: presentationSubmission,
|
||||
|
|
|
@ -30,7 +30,7 @@ class VerifiablePresentationFormatter {
|
|||
let vpClaims = VerifiablePresentationClaims(vpId: UUID().uuidString,
|
||||
purpose: PURPOSE,
|
||||
verifiablePresentation: verifiablePresentationDescriptor,
|
||||
issuerOfVp: identifier.longformId,
|
||||
issuerOfVp: identifier.longFormDid,
|
||||
audience: audience,
|
||||
iat: timeConstraints.issuedAt,
|
||||
exp: timeConstraints.expiration)
|
||||
|
|
|
@ -6,36 +6,18 @@
|
|||
import VCCrypto
|
||||
|
||||
public struct Identifier {
|
||||
public let longformId: String
|
||||
public let longFormDid: String
|
||||
let didDocumentKeys: [KeyContainer]
|
||||
let updateKey: KeyContainer
|
||||
let recoveryKey: KeyContainer
|
||||
|
||||
public init(longformId: String,
|
||||
public init(longFormDid: String,
|
||||
didDocumentKeys: [KeyContainer],
|
||||
updateKey: KeyContainer,
|
||||
recoveryKey: KeyContainer) {
|
||||
self.longformId = longformId
|
||||
self.longFormDid = longFormDid
|
||||
self.didDocumentKeys = didDocumentKeys
|
||||
self.updateKey = updateKey
|
||||
self.recoveryKey = recoveryKey
|
||||
}
|
||||
}
|
||||
|
||||
public struct KeyContainer {
|
||||
|
||||
/// key reference to key in Secret Store
|
||||
let keyReference: VCCryptoSecret
|
||||
|
||||
/// keyId to specify key in Identifier Document (must be less than 20 chars long)
|
||||
let keyId: String
|
||||
|
||||
/// Always ES256K because we only support Secp256k1 keys
|
||||
let algorithm: String = "ES256K"
|
||||
|
||||
public init(keyReference: VCCryptoSecret,
|
||||
keyId: String) {
|
||||
self.keyReference = keyReference
|
||||
self.keyId = keyId
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public struct IdentifierCreator {
|
|||
let recoveryKeyContainer = KeyContainer(keyReference: try self.cryptoOperations.generateKey(), keyId: "recover")
|
||||
|
||||
let longformDid = try self.createLongformDid(signingKeyContainer: signingKeyContainer, updateKeyContainer: updateKeyContainer, recoveryKeyContainer: recoveryKeyContainer)
|
||||
return Identifier(longformId: longformDid, didDocumentKeys: [signingKeyContainer], updateKey: updateKeyContainer, recoveryKey: recoveryKeyContainer)
|
||||
return Identifier(longFormDid: longformDid, didDocumentKeys: [signingKeyContainer], updateKey: updateKeyContainer, recoveryKey: recoveryKeyContainer)
|
||||
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ public struct IdentifierCreator {
|
|||
let signingJwk = try self.generatePublicJwk(for: signingKeyContainer)
|
||||
let updateJwk = try self.generatePublicJwk(for: updateKeyContainer)
|
||||
let recoveryJwk = try self.generatePublicJwk(for: recoveryKeyContainer)
|
||||
return try self.identifierFormatter.createIonLongForm(recoveryKey: recoveryJwk, updateKey: updateJwk, didDocumentKeys: [signingJwk], serviceEndpoints: [])
|
||||
return try self.identifierFormatter.createIonLongFormDid(recoveryKey: recoveryJwk, updateKey: updateJwk, didDocumentKeys: [signingJwk], serviceEndpoints: [])
|
||||
}
|
||||
|
||||
private func generatePublicJwk(for keyMapping: KeyContainer) throws -> ECPublicJwk {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import VCCrypto
|
||||
|
||||
public struct KeyContainer {
|
||||
|
||||
/// key reference to key in Secret Store
|
||||
let keyReference: VCCryptoSecret
|
||||
|
||||
/// keyId to specify key in Identifier Document (must be less than 20 chars long)
|
||||
let keyId: String
|
||||
|
||||
/// Always ES256K because we only support Secp256k1 keys
|
||||
let algorithm: String = "ES256K"
|
||||
|
||||
public init(keyReference: VCCryptoSecret,
|
||||
keyId: String) {
|
||||
self.keyReference = keyReference
|
||||
self.keyId = keyId
|
||||
}
|
||||
}
|
|
@ -42,8 +42,6 @@ public extension KeyedDecodingContainer {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public extension KeyedEncodingContainerProtocol where Key == JSONCodingKeys {
|
||||
mutating func encode(_ value: Dictionary<String, Any>) throws {
|
||||
try value.forEach({ (key, value) in
|
||||
|
@ -76,4 +74,3 @@ public extension KeyedEncodingContainerProtocol {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,10 +15,8 @@ class IdentifierFormatterTests: XCTestCase {
|
|||
|
||||
func testFormatting() throws {
|
||||
let key = ECPublicJwk(x: "Ir5lqT2yDCXdWI8HgMj2erz9HVChFFv4Bd70oDqclvs", y: "_uSQb2NNO3MMnsS83ByMxayGbk3ODYxAlMx-_YOw5oc", keyId: "testKey")
|
||||
let actualDid = try formatter.createIonLongForm(recoveryKey: key, updateKey: key, didDocumentKeys: [key], serviceEndpoints: [])
|
||||
let actualDid = try formatter.createIonLongFormDid(recoveryKey: key, updateKey: key, didDocumentKeys: [key], serviceEndpoints: [])
|
||||
XCTAssertEqual(actualDid, expectedDid)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -29,12 +29,12 @@ class IssuanceResponseFormatterTests: XCTestCase {
|
|||
let key = try cryptoOperation.generateKey()
|
||||
|
||||
let keyContainer = KeyContainer(keyReference: key, keyId: "keyId")
|
||||
self.mockIdentifier = Identifier(longformId: "longFormDid", didDocumentKeys: [keyContainer], updateKey: keyContainer, recoveryKey: keyContainer)
|
||||
self.mockIdentifier = Identifier(longFormDid: "longFormDid", didDocumentKeys: [keyContainer], updateKey: keyContainer, recoveryKey: keyContainer)
|
||||
}
|
||||
|
||||
func testFormatToken() throws {
|
||||
let formattedToken = try formatter.format(response: self.mockResponse, usingIdentifier: self.mockIdentifier)
|
||||
XCTAssertEqual(formattedToken.content.did, self.mockIdentifier.longformId)
|
||||
XCTAssertEqual(formattedToken.content.did, self.mockIdentifier.longFormDid)
|
||||
XCTAssertEqual(formattedToken.content.contract, self.mockResponse.contractUri)
|
||||
XCTAssertEqual(formattedToken.content.audience, self.mockResponse.audience)
|
||||
XCTAssert(MockTokenSigner.wasSignCalled)
|
||||
|
|
|
@ -31,7 +31,7 @@ class PresentationResponseFormatterTests: XCTestCase {
|
|||
let key = try cryptoOperation.generateKey()
|
||||
|
||||
let keyContainer = KeyContainer(keyReference: key, keyId: "keyId")
|
||||
self.mockIdentifier = Identifier(longformId: "longFormDid", didDocumentKeys: [keyContainer], updateKey: keyContainer, recoveryKey: keyContainer)
|
||||
self.mockIdentifier = Identifier(longFormDid: "longFormDid", didDocumentKeys: [keyContainer], updateKey: keyContainer, recoveryKey: keyContainer)
|
||||
}
|
||||
|
||||
func testFormatToken() throws {
|
||||
|
@ -40,7 +40,7 @@ class PresentationResponseFormatterTests: XCTestCase {
|
|||
|
||||
let formattedToken = try formatter.format(response: self.mockResponse, usingIdentifier: self.mockIdentifier)
|
||||
|
||||
XCTAssertEqual(formattedToken.content.did, self.mockIdentifier.longformId)
|
||||
XCTAssertEqual(formattedToken.content.did, self.mockIdentifier.longFormDid)
|
||||
XCTAssertNotNil(formattedToken.content.exp)
|
||||
XCTAssertNotNil(formattedToken.content.iat)
|
||||
XCTAssertNotNil(formattedToken.content.jti)
|
||||
|
@ -59,7 +59,7 @@ class PresentationResponseFormatterTests: XCTestCase {
|
|||
func testFormatTokenNoVcs() throws {
|
||||
|
||||
let formattedToken = try formatter.format(response: self.mockResponse, usingIdentifier: self.mockIdentifier)
|
||||
XCTAssertEqual(formattedToken.content.did, self.mockIdentifier.longformId)
|
||||
XCTAssertEqual(formattedToken.content.did, self.mockIdentifier.longFormDid)
|
||||
XCTAssertNotNil(formattedToken.content.exp)
|
||||
XCTAssertNotNil(formattedToken.content.iat)
|
||||
XCTAssertNotNil(formattedToken.content.jti)
|
||||
|
|
|
@ -24,7 +24,7 @@ class IdentifierCreatorTests: XCTestCase {
|
|||
let creator = IdentifierCreator(cryptoOperations: self.cryptoOperations, identifierFormatter: MockIdentifierFormatter(returningString: self.expectedResult))
|
||||
let actualResult = try creator.create()
|
||||
XCTAssertEqual(MockCryptoOperations.generateKeyCallCount, 3)
|
||||
XCTAssertEqual(actualResult.longformId, expectedResult)
|
||||
XCTAssertEqual(actualResult.longFormDid, expectedResult)
|
||||
}
|
||||
|
||||
func testCreateIdentifierWithCryptoOperations() throws {
|
||||
|
|
|
@ -15,7 +15,7 @@ struct MockIdentifierFormatter: IdentifierFormatting {
|
|||
self.returningString = returningString
|
||||
}
|
||||
|
||||
func createIonLongForm(recoveryKey: ECPublicJwk, updateKey: ECPublicJwk, didDocumentKeys: [ECPublicJwk], serviceEndpoints: [IdentifierDocumentServiceEndpoint]) throws -> String {
|
||||
func createIonLongFormDid(recoveryKey: ECPublicJwk, updateKey: ECPublicJwk, didDocumentKeys: [ECPublicJwk], serviceEndpoints: [IdentifierDocumentServiceEndpoint]) throws -> String {
|
||||
return self.returningString
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class IssuanceUseCaseTests: XCTestCase {
|
|||
self.contract = try JSONDecoder().decode(Contract.self, from: encodedContract)
|
||||
|
||||
let keyContainer = KeyContainer(keyReference: MockVCCryptoSecret(), keyId: "keyId234")
|
||||
self.mockIdentifier = Identifier(longformId: "longform", didDocumentKeys: [keyContainer], updateKey: keyContainer, recoveryKey: keyContainer)
|
||||
self.mockIdentifier = Identifier(longFormDid: "longform", didDocumentKeys: [keyContainer], updateKey: keyContainer, recoveryKey: keyContainer)
|
||||
|
||||
MockIssuanceResponseFormatter.wasFormatCalled = false
|
||||
MockApiCalls.wasPostCalled = false
|
||||
|
|
|
@ -24,7 +24,7 @@ class PresentationUseCaseTests: XCTestCase {
|
|||
self.presentationRequest = PresentationRequest(from: TestData.presentationRequest.rawValue)!
|
||||
|
||||
let keyContainer = KeyContainer(keyReference: MockVCCryptoSecret(), keyId: "keyId234")
|
||||
self.mockIdentifier = Identifier(longformId: "longform", didDocumentKeys: [keyContainer], updateKey: keyContainer, recoveryKey: keyContainer)
|
||||
self.mockIdentifier = Identifier(longFormDid: "longform", didDocumentKeys: [keyContainer], updateKey: keyContainer, recoveryKey: keyContainer)
|
||||
|
||||
MockPresentationResponseFormatter.wasFormatCalled = false
|
||||
MockApiCalls.wasPostCalled = false
|
||||
|
|
Загрузка…
Ссылка в новой задаче