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

Commit

Permalink
feat: Dp did key improvements (#318)
Browse files Browse the repository at this point in the history
* feat: adding option to not resolve dids for presentation

* feat: Adding basic logic to support new did key method

* fix: fix tests and typos

* fix: work in progress

* fix: cleanup

* fix: preparing for publish

* fix: clean up

* fix: missed declaration

* fix: making lint happy

* fix: resolver not for prod

* fix: skip tests for url resolver

* fix: skip resolution for polygon cause of registry issue

* fix: update HANGLEOGs

* fix: trying new codeclimate version

* fix: put back previous code climate version

* fix: trying code climate version 3.0

* fix: playing with code climatre

---------

Co-authored-by: Denys <denys.p@affinidi.com>
  • Loading branch information
DenisPopov15 and Denys authored Aug 17, 2023
1 parent 4ce2efa commit 315ee5f
Show file tree
Hide file tree
Showing 44 changed files with 564 additions and 90 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/codeclimate-workflow-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ jobs:
run: npm run build
- name: Lint packages
run: npm run lint
- uses: paambaati/codeclimate-action@v2.6.0
- uses: paambaati/codeclimate-action@v2.7.1
env:
CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
TEST_SECRETS: ${{secrets.INTEGRATION_TEST_SECRETS}}
TESTMAIL_API_KEY: ${{secrets.TESTMAIL_API_KEY}}
TESTMAIL_NS: ${{secrets.TESTMAIL_NS}}
with:
coverageCommand: npm run test:coverage:codeclimate
- name: Generate and Upload Test Coverage
run: |
$GITHUB_WORKSPACE/tmp/cc-test-reporter sum-coverage $GITHUB_WORKSPACE/tmp/codeclimate.*.json -p $(ls -1q $GITHUB_WORKSPACE/tmp/codeclimate.*.json | wc -l) -d -o tmp/codeclimate.total.json
$GITHUB_WORKSPACE/tmp/cc-test-reporter upload-coverage -i $GITHUB_WORKSPACE/tmp/codeclimate.total.json
env:
CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
# - name: Generate and Upload Test Coverage
# run: |
# $GITHUB_WORKSPACE/tmp/cc-test-reporter sum-coverage $GITHUB_WORKSPACE/tmp/codeclimate.*.json -p $(ls -1q $GITHUB_WORKSPACE/tmp/codeclimate.*.json | wc -l) -d -o tmp/codeclimate.total.json
# $GITHUB_WORKSPACE/tmp/cc-test-reporter upload-coverage -i $GITHUB_WORKSPACE/tmp/codeclimate.total.json
# env:
# CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
14 changes: 7 additions & 7 deletions .github/workflows/codeclimate-workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@ jobs:
run: npm run build
- name: Lint packages
run: npm run lint
- uses: paambaati/codeclimate-action@v2.6.0
- uses: paambaati/codeclimate-action@v2.7.1
env:
CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
TEST_SECRETS: ${{secrets.INTEGRATION_TEST_SECRETS}}
TESTMAIL_API_KEY: ${{secrets.TESTMAIL_API_KEY}}
TESTMAIL_NS: ${{secrets.TESTMAIL_NS}}
with:
coverageCommand: npm run test:coverage:codeclimate
- name: Generate and Upload Test Coverage
run: |
$GITHUB_WORKSPACE/tmp/cc-test-reporter sum-coverage $GITHUB_WORKSPACE/tmp/codeclimate.*.json -p $(ls -1q $GITHUB_WORKSPACE/tmp/codeclimate.*.json | wc -l) -d -o tmp/codeclimate.total.json
$GITHUB_WORKSPACE/tmp/cc-test-reporter upload-coverage -i $GITHUB_WORKSPACE/tmp/codeclimate.total.json
env:
CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
# - name: Generate and Upload Test Coverage
# run: |
# $GITHUB_WORKSPACE/tmp/cc-test-reporter sum-coverage $GITHUB_WORKSPACE/tmp/codeclimate.*.json -p $(ls -1q $GITHUB_WORKSPACE/tmp/codeclimate.*.json | wc -l) -d -o tmp/codeclimate.total.json
# $GITHUB_WORKSPACE/tmp/cc-test-reporter upload-coverage -i $GITHUB_WORKSPACE/tmp/codeclimate.total.json
# env:
# CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}

2 changes: 2 additions & 0 deletions common-libs/common/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# release 3.3.0 (2023-08-16)
* Add support for the did key method and public Key JWK format
# release 3.2.0 (2023-05-30)
* remove metrics service
# release 3.1.0 (2023-03-14)
Expand Down
38 changes: 20 additions & 18 deletions common-libs/common/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions common-libs/common/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@affinidi/common",
"version": "3.2.0",
"version": "3.3.0",
"description": "Common utilities and types for Affinidi SDKs",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down Expand Up @@ -107,4 +107,4 @@
"typescript": "^4.3.2"
},
"gitHead": "39b8ae64eb5e37ddae2f80438b320adaefae8ef6"
}
}
19 changes: 17 additions & 2 deletions common-libs/common/src/Affinity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class Affinity {
cacheMaxSize: options.cacheMaxSize,
cacheTtlInMin: options.cacheTtlInMin,
resolveLegacyElemLocally: options.resolveLegacyElemLocally,
resolveKeyLocally: options.resolveKeyLocally,
})
this._digestService = new DigestService()
this._platformCryptographyTools = platformCryptographyTools
Expand Down Expand Up @@ -181,6 +182,10 @@ export class Affinity {
}
}

async checkCredentialStatus(credential: any): Promise<{ verified: boolean; error?: string }> {

Check warning on line 185 in common-libs/common/src/Affinity.ts

View workflow job for this annotation

GitHub Actions / publish

Argument 'credential' should be typed with a non-any type
return this._checkCredentialStatus(credential)
}

async _checkCredentialStatus(credential: any): Promise<{ verified: boolean; error?: string }> {

Check warning on line 189 in common-libs/common/src/Affinity.ts

View workflow job for this annotation

GitHub Actions / publish

Argument 'credential' should be typed with a non-any type
if (credential.credentialStatus) {
// We don't need to have `revocationList.checkStatus` verify the VC because we already do that
Expand Down Expand Up @@ -298,10 +303,18 @@ export class Affinity {
return this._keyManager.signCredential(unsignedCredentialInput, keySuiteType)
}

_getProvidedDidDocument(didDocuments: any, controller: string, didDocument: any) {

Check warning on line 306 in common-libs/common/src/Affinity.ts

View workflow job for this annotation

GitHub Actions / publish

Missing return type on function

Check warning on line 306 in common-libs/common/src/Affinity.ts

View workflow job for this annotation

GitHub Actions / publish

Argument 'didDocuments' should be typed with a non-any type

Check warning on line 306 in common-libs/common/src/Affinity.ts

View workflow job for this annotation

GitHub Actions / publish

Argument 'didDocument' should be typed with a non-any type
const controllerDid = parse(controller).did
const providedDidDocument = didDocuments[controllerDid] || didDocuments[controller] || didDocument

return providedDidDocument
}

async validatePresentation(
vp: any,
didDocument?: any,
challenge?: string,
didDocuments: any = {},
): Promise<{ result: true; data: VPV1 } | { result: false; error: string }> {
const result = await validateVPV1({
documentLoader: this._createDocumentLoader(),
Expand All @@ -310,17 +323,19 @@ export class Affinity {
throw new Error(`Unsupported proofType: ${proofType}`)
}

const resolvedDidDocument = await this._resolveDidIfNoDidDocument(controller, didDocument)
const providedDidDocument = this._getProvidedDidDocument(didDocuments, controller, didDocument)
const resolvedDidDocument = await this._resolveDidIfNoDidDocument(controller, providedDidDocument)
const publicKey = DidDocumentService.getPublicKey(verificationMethod, resolvedDidDocument)
const factory = this._platformCryptographyTools.verifySuiteFactories[proofType]

return factory(publicKey, verificationMethod, controller)
},
getProofPurposeOptions: async ({ proofPurpose, controller }) => {
const providedDidDocument = this._getProvidedDidDocument(didDocuments, controller, didDocument)
switch (proofPurpose) {
case 'authentication':
case 'assertionMethod': {
const resolvedDidDoc = await this._resolveDidIfNoDidDocument(controller, didDocument)
const resolvedDidDoc = await this._resolveDidIfNoDidDocument(controller, providedDidDocument)

// TODO: workaround, for now polygon dids has only verificationMethod
// it could be changed in future as polygon is under developing
Expand Down
2 changes: 2 additions & 0 deletions common-libs/common/src/_defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const POLYGON_TESTNET_DID_METHOD = 'polygon:testnet'
export const ELEM_DID_METHOD = 'elem'
export const ELEM_ANCHORED_DID_METHOD = 'elem-anchored'
export const WEB_DID_METHOD = 'web'
export const KEY_DID_METHOD = 'key'
export const DEFAULT_DID_METHOD = JOLO_DID_METHOD
export const SUPPORTED_DID_METHODS = [
JOLO_DID_METHOD,
Expand All @@ -12,4 +13,5 @@ export const SUPPORTED_DID_METHODS = [
POLYGON_DID_METHOD,
POLYGON_TESTNET_DID_METHOD,
WEB_DID_METHOD,
KEY_DID_METHOD,
] as const
1 change: 1 addition & 0 deletions common-libs/common/src/dto/shared.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class AffinityOptions {
cacheMaxSize?: number
cacheTtlInMin?: number
resolveLegacyElemLocally?: boolean
resolveKeyLocally?: boolean
beforeDocumentLoader?: DocumentLoader

keyManager?: KeyManager
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Resolver } from 'did-resolver'
import { DidDocument } from '../../shared/interfaces'
import KeyDidDocumentService from './KeyDidDocumentService'
import { decodeBase58 } from '../../utils/ethUtils'

const MULTIBASE_ENCODED_BASE58_IDENTIFIER = 'z' // z represents the multibase encoding scheme of base58 encoding, https://github.com/multiformats/multibase/blob/master/multibase.csv#L18

const pubKeyFromDid = (did: string): { publicKey: Buffer; fingerprint: string } => {
const fingerprint = did.split(':')[2]
const encoded = fingerprint.replace(MULTIBASE_ENCODED_BASE58_IDENTIFIER, '')
const decoded = decodeBase58(encoded)

const publicKey = decoded.slice(2, decoded.length)

return { publicKey, fingerprint }
}

const resolveKeyDID = async (did: string) => {
const { publicKey, fingerprint } = pubKeyFromDid(did)
const didDocument = KeyDidDocumentService.buildDidDocumentFromPubKey(publicKey, fingerprint)

return didDocument
}

export const resolveKeyDIDWithParams = async (did: string, isDidJson: boolean = false) => {
const { publicKey, fingerprint } = pubKeyFromDid(did)
const didDocument = KeyDidDocumentService.buildDidDocumentFromPubKey(publicKey, fingerprint, isDidJson)

return didDocument
}

export const resolveDidKeyLocal = (did: string) => {
const resolver = new Resolver({ key: resolveKeyDID })
return resolver.resolve(did) as Promise<DidDocument>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { KeyVault } from './KeyVault'
import { encodeBase58 } from '../../utils/ethUtils'
import DidDocumentService from './index'

const SECP256K1_MULTICODEC_IDENTIFIER = 0xe7 // 0xe7 indicates a Secp256k1 public key
const VARIABLE_INTEGER_TRAILING_BYTE = 0x01 // 0x01 indicates the end of the leading bytes according to variable integer spec, https://github.com/multiformats/multibase/blob/master/multibase.csv#L18
const MULTIBASE_ENCODED_BASE58_IDENTIFIER = 'z' // z represents the multibase encoding scheme of base58 encoding, https://github.com/multiformats/multibase/blob/master/multibase.csv#L18

export default class KeyDidDocumentService {
private _keyProvider

constructor(keyProvider: KeyVault) {
this._keyProvider = keyProvider
}

_fingerprintFromPubKey(publicKey: Buffer): string {
const unitArray = new Uint8Array(2 + publicKey.length)
unitArray[0] = SECP256K1_MULTICODEC_IDENTIFIER
unitArray[1] = VARIABLE_INTEGER_TRAILING_BYTE
unitArray.set(publicKey, 2)

const buffer = Buffer.from(unitArray)

return `${MULTIBASE_ENCODED_BASE58_IDENTIFIER}${encodeBase58(buffer)}`
}

getMyDid(): string {
const publicKey = this._keyProvider.primaryPublicKey
const fingerprint = this._fingerprintFromPubKey(publicKey)
return `did:key:${fingerprint}`
}

_getFingerPrintFromDid(did: string): string {
const fingerprint = did.split(':')[2]

return fingerprint
}

getKeyId() {
const did = this.getMyDid()
const fingerprint = this._getFingerPrintFromDid(did)

return `${did}#${fingerprint}`
}

static buildDidDocumentFromPubKey(pubKeyBytes: Buffer, fingerprint: string, isDidJson: boolean = false) {
const did = `did:key:${fingerprint}`
const keyId = `${did}#${fingerprint}`
let publicKey: any = {
id: keyId,
type: 'Secp256k1VerificationKey2018',
controller: did,
publicKeyBase58: encodeBase58(pubKeyBytes),
}

if (isDidJson) {
const publicKeyJwk = DidDocumentService.getPublicKeyJwkFromPublicKey(pubKeyBytes)
publicKey = {
id: keyId,
type: 'JsonWebKey2020',
controller: did,
publicKeyJwk,
}
}

return {
'@context': ['https://www.w3.org/ns/did/v1', 'https://w3id.org/security/suites/jws-2020/v1'],
id: did,
// verificationMethod: [publicKey],
publicKey: [publicKey],
authentication: [keyId],
assertionMethod: [keyId],
capabilityDelegation: [keyId],
capabilityInvocation: [keyId],
keyAgreement: [keyId],
}
}

async _buildDidDocumentInformation(isDidJson: boolean = false) {
const did = this.getMyDid()
const fingerprint = this._getFingerPrintFromDid(did)
const publicKey = this._keyProvider.primaryPublicKey

const didDocument = KeyDidDocumentService.buildDidDocumentFromPubKey(publicKey, fingerprint, isDidJson)

return { did, didDocument, fingerprint }
}

async buildDidDocumentForRegister() {
const { did, didDocument, fingerprint } = await this._buildDidDocumentInformation()

return {
did,
didDocument,
keyId: `${did}#${fingerprint}`,
}
}

async getDidDocument() {
const { didDocument } = await this._buildDidDocumentInformation()
return didDocument
}
}
Loading

0 comments on commit 315ee5f

Please sign in to comment.