Skip to content

Commit

Permalink
feat: add support for did:ethr signed/meta transactions (#1031)
Browse files Browse the repository at this point in the history
  • Loading branch information
lleifermann authored Oct 18, 2022
1 parent 0c05a66 commit 88f1da9
Show file tree
Hide file tree
Showing 8 changed files with 451 additions and 94 deletions.
2 changes: 2 additions & 0 deletions __tests__/localAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import didCommWithEthrDidFlow from './shared/didCommWithEthrDidFlow'
import utils from './shared/utils'
import web3 from './shared/web3'
import credentialStatus from './shared/credentialStatus'
import ethrDidFlowSigned from "./shared/ethrDidFlowSigned";

jest.setTimeout(60000)

Expand Down Expand Up @@ -278,4 +279,5 @@ describe('Local integration tests', () => {
web3(testContext)
didCommWithEthrDidFlow(testContext)
credentialStatus(testContext)
ethrDidFlowSigned(testContext)
})
1 change: 1 addition & 0 deletions __tests__/shared/didManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ export default (testContext: {
'eth_signTransaction',
'eth_signTypedData',
'eth_signMessage',
'eth_rawSign',
],
},
publicKeyHex:
Expand Down
150 changes: 150 additions & 0 deletions __tests__/shared/ethrDidFlowSigned.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// noinspection ES6PreferShortImport

import {
IAgentOptions,
IDIDManager,
IIdentifier,
IKeyManager,
IMessageHandler,
IResolver,
TAgent,
} from '../../packages/core/src'
import {IDIDComm} from '../../packages/did-comm/src'
// @ts-ignore
import express from 'express'
import {Server} from 'http'

type ConfiguredAgent = TAgent<IDIDManager & IKeyManager & IResolver & IDIDComm & IMessageHandler>

export async function sleep(milliseconds: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, milliseconds))
}

export default (testContext: {
getAgent: () => ConfiguredAgent
setup: (options?: IAgentOptions) => Promise<boolean>
tearDown: () => Promise<boolean>
}) => {
describe('did ethr controller signed interactions', () => {
let agent: ConfiguredAgent

let alice: IIdentifier
let bob: IIdentifier

let didCommEndpointServer: Server
let listeningPort = Math.round(Math.random() * 32000 + 2048)

beforeEach(async () => {
await testContext.setup()
agent = testContext.getAgent()

alice = await agent.didManagerImport({
controllerKeyId: 'alice-controller-key',
did: 'did:ethr:ganache:0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
provider: 'did:ethr:ganache',
alias: 'alice-did-ethr',
keys: [
{
privateKeyHex: '0000000000000000000000000000000000000000000000000000000000000001',
kms: 'local',
type: 'Secp256k1',
kid: 'alice-controller-key',
},
],
})

bob = await agent.didManagerImport({
controllerKeyId: 'bob-controller-key',
did: 'did:ethr:ganache:0x02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5',
provider: 'did:ethr:ganache',
alias: 'bob-did-ethr',
keys: [
{
privateKeyHex: '0000000000000000000000000000000000000000000000000000000000000002',
kms: 'local',
type: 'Secp256k1',
kid: 'bob-controller-key',
},
],
})
})

afterAll(async () => {
await testContext.tearDown()
})

it('should add dummy service to alice did with bob sending the tx', async () => {
const result = await agent.didManagerAddService({
did: alice.did,
service: {
id: 'localhost-useless-endpoint',
type: 'DIDComm',
serviceEndpoint: `http://localhost:${listeningPort}/foobar`,
description: 'this endpoint will be removed',
}, options: {
metaIdentifierKeyId: bob.controllerKeyId
}
})

const resolution = await agent.resolveDid({ didUrl: alice.did })

expect(resolution.didDocument).toEqual(expect.objectContaining({
service: expect.arrayContaining([
expect.objectContaining({
serviceEndpoint: `http://localhost:${listeningPort}/foobar`
})
])
}))
})

it('should remove dummy service to alice did with bob sending the tx', async () => {
await agent.didManagerAddService({
did: alice.did,
service: {
id: 'localhost-useless-endpoint',
type: 'DIDComm',
serviceEndpoint: `http://localhost:${listeningPort}/foobar`,
description: 'this endpoint will be removed',
}, options: {
metaIdentifierKeyId: bob.controllerKeyId
}
})

await agent.didManagerRemoveService({
did: alice.did,
id: "localhost-useless-endpoint",
options: {
metaIdentifierKeyId: bob.controllerKeyId
}
})

const resolution = await agent.resolveDid({ didUrl: alice.did })
expect(resolution?.didDocument?.service?.[0].serviceEndpoint).toBeFalsy()
})

it('should add verification key to alice did with bob sending the tx', async () => {
const keyToAdd = await agent.keyManagerCreate({type: 'Secp256k1', kms: 'local'})

await agent.didManagerAddKey({
did: alice.did,
key: keyToAdd,
options: {
metaIdentifierKeyId: bob.controllerKeyId
}
})

// Give ganache some time to emit the event from the contract
await sleep(1000)

const didAfterchange = await agent.resolveDid({ didUrl: alice.did })
expect(didAfterchange).toBeTruthy()
expect(didAfterchange.didDocument).toEqual(expect.objectContaining({
verificationMethod: expect.arrayContaining([
expect.objectContaining({
publicKeyHex: keyToAdd.publicKeyHex
})
])
}))
})
})
}
140 changes: 86 additions & 54 deletions __tests__/shared/keyManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,14 @@ export default (testContext: {
expect(key.meta).toEqual({
foo: 'bar',
bar: 'baz',
algorithms: ['ES256K', 'ES256K-R', 'eth_signTransaction', 'eth_signTypedData', 'eth_signMessage'],
algorithms: [
'ES256K',
'ES256K-R',
'eth_signTransaction',
'eth_signTypedData',
'eth_signMessage',
'eth_rawSign',
],
})
})

Expand Down Expand Up @@ -170,7 +177,14 @@ export default (testContext: {
publicKeyHex:
'04dd467afb12bdb797303e7f3f0c8cd0ba80d518dc4e339e0e2eb8f2d99a9415cac537854a30d31a854b7af0b4fcb54c3954047390fa9500d3cc2e15a3e09017bb',
meta: {
algorithms: ['ES256K', 'ES256K-R', 'eth_signTransaction', 'eth_signTypedData', 'eth_signMessage'],
algorithms: [
'ES256K',
'ES256K-R',
'eth_signTransaction',
'eth_signTypedData',
'eth_signMessage',
'eth_rawSign',
],
foo: 'bar',
},
}
Expand Down Expand Up @@ -450,7 +464,6 @@ export default (testContext: {
],
},
types: {

Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person[]' },
Expand All @@ -461,7 +474,7 @@ export default (testContext: {
{ name: 'wallets', type: 'address[]' },
],
},
};
}

const identifier = await agent.didManagerCreate({ kms: 'local' })

Expand All @@ -471,7 +484,7 @@ export default (testContext: {
const signature = await agent.keyManagerSign({
data: JSON.stringify(msgParams),
keyRef: extendedKey.kid,
algorithm: 'eth_signTypedData'
algorithm: 'eth_signTypedData',
})

const address = extendedKey.meta.ethereumAddress
Expand All @@ -493,75 +506,73 @@ export default (testContext: {
}

//@ts-ignore
const recovered = recoverTypedSignature({data, signature: signature, version: SignTypedDataVersion.V4})
const recovered = recoverTypedSignature({
data: data as any,
signature: signature,
version: SignTypedDataVersion.V4,
})
expect(address.toLowerCase()).toEqual(recovered)
})

it('should sign credential with eth_signTypedData', async () => {
const msgParams = {
"domain": {
"chainId": 4,
"name": "VerifiableCredential",
"version": "1"
domain: {
chainId: 4,
name: 'VerifiableCredential',
version: '1',
},
"types": {
"CredentialSubject": [
types: {
CredentialSubject: [
{
"name": "id",
"type": "string"
name: 'id',
type: 'string',
},
{
"name": "you",
"type": "string"
}
name: 'you',
type: 'string',
},
],
"Issuer": [
Issuer: [
{
"name": "id",
"type": "string"
}
name: 'id',
type: 'string',
},
],
"VerifiableCredential": [
VerifiableCredential: [
{
"name": "@context",
"type": "string[]"
name: '@context',
type: 'string[]',
},
{
"name": "credentialSubject",
"type": "CredentialSubject"
name: 'credentialSubject',
type: 'CredentialSubject',
},
{
"name": "issuanceDate",
"type": "string"
name: 'issuanceDate',
type: 'string',
},
{
"name": "issuer",
"type": "Issuer"
name: 'issuer',
type: 'Issuer',
},
{
"name": "type",
"type": "string[]"
}
]
name: 'type',
type: 'string[]',
},
],
},
"message": {
"issuer": {
"id": "did:fake:123"
message: {
issuer: {
id: 'did:fake:123',
},
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://example.com/1/2/3"
],
"type": [
"VerifiableCredential",
"Custom"
],
"issuanceDate": "2022-05-31T14:02:06.109Z",
"credentialSubject": {
"id": "did:web:example.com",
"you": "Rock"
}
}
'@context': ['https://www.w3.org/2018/credentials/v1', 'https://example.com/1/2/3'],
type: ['VerifiableCredential', 'Custom'],
issuanceDate: '2022-05-31T14:02:06.109Z',
credentialSubject: {
id: 'did:web:example.com',
you: 'Rock',
},
},
}

const identifier = await agent.didManagerCreate({ kms: 'local' })
Expand All @@ -572,7 +583,7 @@ export default (testContext: {
const signature = await agent.keyManagerSign({
data: JSON.stringify(msgParams),
keyRef: extendedKey.kid,
algorithm: 'eth_signTypedData'
algorithm: 'eth_signTypedData',
})

const address = extendedKey.meta.ethereumAddress
Expand All @@ -592,13 +603,34 @@ export default (testContext: {
},
}

const args = {data, signature: signature, version: SignTypedDataVersion.V4}
const args = { data, signature: signature, version: SignTypedDataVersion.V4 }
//@ts-ignore
const recovered = recoverTypedSignature(args)
expect(address.toLowerCase()).toEqual(recovered)
})

})
it('should sign keccak hash with eth_rawSign', async () => {
const importedKey = {
kid: 'imported_raw',
kms: 'local',
type: <TKeyType>'Secp256k1',
publicKeyHex:
'04155ee0cbefeecd80de63a62b4ed8f0f97ac22a58f76a265903b9acab79bf018c7037e2bd897812170c92a4c978d6a10481491a37299d74c4bd412a111a4ac875',
privateKeyHex: '31d1ec15ff8110442012fef0d1af918c0e09b2e2ab821bba52ecc85f8655ec63',
}

const key = await agent.keyManagerImport(importedKey)

const signature = await agent.keyManagerSign({
algorithm: 'eth_rawSign',
data: '9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658',
encoding: 'hex',
keyRef: key.kid,
})

expect(signature).toEqual(
'0x9d9e6c705cfa5f348de0c5174e70234c3b372d6bfca05fd11ffc5fe46eab996a3e4780d403b611395fd8548f2b101c3542c5e43848e486ea238da18fe0ffe6d0',
)
})
})
}
Loading

0 comments on commit 88f1da9

Please sign in to comment.