diff --git a/src/contacts/contacts.controller.ts b/src/contacts/contacts.controller.ts index ac7a257..2629b25 100644 --- a/src/contacts/contacts.controller.ts +++ b/src/contacts/contacts.controller.ts @@ -11,9 +11,10 @@ import { UseGuards, } from '@nestjs/common' import { Contact, ContactsService } from './interfaces/contacts.interfaces' -import { Crypto } from '@kiltprotocol/sdk-js' +import { Did } from '@kiltprotocol/sdk-js' import Optional from 'typescript-optional' import { AuthGuard } from '../auth/auth.guard' +import { IDidDocumentSigned } from '@kiltprotocol/sdk-js/build/did/Did' @Controller('contacts') export class ContactsController { @@ -31,15 +32,18 @@ export class ContactsController { throw new BadRequestException('no name') } if (contact.did) { - if (!contact.signature) { - throw new BadRequestException('no signature') - } - - const hash = Crypto.hashStr(JSON.stringify(contact.did)) - if ( - !Crypto.verify(hash, contact.signature, contact.publicIdentity.address) - ) { - throw new BadRequestException('bad signature for hash') + try { + if ( + !Did.verifyDidDocumentSignature( + contact.did, + Did.getIdentifierFromAddress(contact.publicIdentity.address) + ) + ) { + throw new BadRequestException('Did signature not verifiable') + } + } catch (e) { + console.log(e) + throw new BadRequestException('Did signature not verifiable') } } await this.contactService.add(contact) @@ -64,7 +68,9 @@ export class ContactsController { } @Get('did/:address') - public async getDidDocument(@Param('address') address): Promise { + public async getDidDocument( + @Param('address') address + ): Promise { const result: Optional = await this.contactService.findByAddress( address ) diff --git a/src/contacts/contacts.module.spec.ts b/src/contacts/contacts.module.spec.ts index 500e2dd..b3f07e2 100644 --- a/src/contacts/contacts.module.spec.ts +++ b/src/contacts/contacts.module.spec.ts @@ -13,14 +13,19 @@ import { } from './interfaces/contacts.interfaces' import { MongoDbMContactsService } from './mongodb-contacts.service' import Optional from 'typescript-optional' +import { + IDidDocumentSigned, + IDENTIFIER_PREFIX, +} from '@kiltprotocol/sdk-js/build/did/Did' -jest.mock('@kiltprotocol/sdk-js/build/crypto/Crypto', () => { +jest.mock('@kiltprotocol/sdk-js/build/did/Did', () => { return { - hashStr: jest.fn((): string => '0x1'), - verify: jest.fn((): boolean => true), + verifyDidDocumentSignature: jest.fn((): boolean => true), + getIdentifierFromAddress: jest.fn( + (address: string): string => IDENTIFIER_PREFIX + address + ), } }) - describe('Contact Module', () => { const testContact: Contact = { metaData: { @@ -33,8 +38,12 @@ describe('Contact Module', () => { serviceAddress: 'https://services.devnet.kilt.io:443/messaging', }, } - const testDID: object = { + const signature = + '0x00aad52336444c0263a22c22f2b99bbcdfc3a6912b5d085c11df01de2bb13dae7c9adf89ecb58f9a32dd021c1c0c1ff0ed39ba361a85f350714b58f15cbd617607' + + const signedTestDID: IDidDocumentSigned = { id: 'did:kilt:5CKq9ovoHUFb5Qg2q7YmQ2waNhgQm4C22qwb1Wgehnn2eBcb', + signature, '@context': 'https://w3id.org/did/v1', authentication: [ { @@ -67,29 +76,23 @@ describe('Contact Module', () => { }, ], } - const signature = - '0x00aad52336444c0263a22c22f2b99bbcdfc3a6912b5d085c11df01de2bb13dae7c9adf89ecb58f9a32dd021c1c0c1ff0ed39ba361a85f350714b58f15cbd617607' + const contactWithDid: Contact = { ...testContact, - did: testDID, - signature, + did: signedTestDID, } - const noSigContact: Contact = { + const badSigContact: Contact = { ...testContact, - did: testDID, + did: { ...signedTestDID, signature: signature.replace('d', 'f') }, } - const badSigContact: Contact = { ...contactWithDid, signature: '0x1' } const address = testContact.publicIdentity.address describe('Controller', () => { let contactsController: ContactsController let contactsService: ContactsService - const mockedHashStr = require('@kiltprotocol/sdk-js/build/crypto/Crypto') - .hashStr - const mockedVerify = require('@kiltprotocol/sdk-js/build/crypto/Crypto') - .verify - + const mockedVerifyDidDocumentSignature = require('@kiltprotocol/sdk-js/build/did/Did') + .verifyDidDocumentSignature const fakeContactService: ContactsService = { add: jest.fn( async (): Promise => { @@ -131,8 +134,7 @@ describe('Contact Module', () => { it('calls contactService.add on valid Contact without Did', async () => { const addSpy = jest.spyOn(contactsService, 'add') expect(await contactsController.add(testContact)).toEqual(undefined) - expect(mockedHashStr).not.toHaveBeenCalled() - expect(mockedVerify).not.toHaveBeenCalled() + expect(mockedVerifyDidDocumentSignature).not.toHaveBeenCalled() expect(addSpy).toHaveBeenCalledTimes(1) expect(addSpy).toHaveBeenCalledWith(testContact) }) @@ -165,37 +167,27 @@ describe('Contact Module', () => { await expect(contactsController.add(noNameContact)).rejects.toThrow( BadRequestException ) - expect(mockedHashStr).not.toHaveBeenCalled() - expect(mockedVerify).not.toHaveBeenCalled() expect(addSpy).not.toHaveBeenCalled() }) it('calls contactService.add on valid Contact with Did', async () => { const addSpy = jest.spyOn(contactsService, 'add') - expect(await contactsController.add(contactWithDid)).toEqual(undefined) + + await contactsController.add(contactWithDid) + expect(mockedVerifyDidDocumentSignature).toHaveBeenCalledWith( + signedTestDID, + IDENTIFIER_PREFIX + contactWithDid.publicIdentity.address + ) expect(addSpy).toHaveBeenCalledTimes(1) expect(addSpy).toHaveBeenCalledWith(contactWithDid) - expect(mockedHashStr).toHaveBeenCalledTimes(1) - expect(mockedVerify).toHaveBeenCalledTimes(1) - expect(mockedHashStr).toHaveBeenCalledWith(JSON.stringify(testDID)) - expect(mockedVerify).toHaveBeenCalledWith( - '0x1', - contactWithDid.signature, - contactWithDid.publicIdentity.address - ) }) it('rejects contact with did if signature is missing or invalid', async () => { const addSpy = jest.spyOn(contactsService, 'add') - mockedVerify.mockReturnValue(false) - await expect(contactsController.add(noSigContact)).rejects.toThrow( - BadRequestException - ) + mockedVerifyDidDocumentSignature.mockReturnValue(false) await expect(contactsController.add(badSigContact)).rejects.toThrow( BadRequestException ) expect(addSpy).not.toHaveBeenCalled() - expect(mockedHashStr).toHaveBeenCalledTimes(1) - expect(mockedVerify).toHaveBeenCalledTimes(1) }) }) describe('list', () => { diff --git a/src/contacts/interfaces/contacts.interfaces.ts b/src/contacts/interfaces/contacts.interfaces.ts index 6e31cf5..4c8edd1 100644 --- a/src/contacts/interfaces/contacts.interfaces.ts +++ b/src/contacts/interfaces/contacts.interfaces.ts @@ -1,4 +1,5 @@ import { PublicIdentity } from '@kiltprotocol/sdk-js' +import { IDidDocumentSigned } from '@kiltprotocol/sdk-js/build/did/Did' import { Document } from 'mongoose' import Optional from 'typescript-optional' @@ -6,8 +7,7 @@ export interface Contact { metaData: { name: string } - did?: object - signature?: string + did?: IDidDocumentSigned publicIdentity: PublicIdentity } diff --git a/src/contacts/schemas/contacts.schema.ts b/src/contacts/schemas/contacts.schema.ts index 6203329..a3d6525 100644 --- a/src/contacts/schemas/contacts.schema.ts +++ b/src/contacts/schemas/contacts.schema.ts @@ -5,7 +5,6 @@ export const ContactSchema = new mongoose.Schema({ name: String, }, did: Object, - signature: String, publicIdentity: { address: String, boxPublicKeyAsHex: String, diff --git a/test/contacts.e2e-spec.ts b/test/contacts.e2e-spec.ts index a89a5d1..19fdbbe 100644 --- a/test/contacts.e2e-spec.ts +++ b/test/contacts.e2e-spec.ts @@ -8,7 +8,7 @@ import { Contact, } from '../src/contacts/interfaces/contacts.interfaces' import { ContactsModule } from '../src/contacts/contacts.module' -import { IDidDocument } from '@kiltprotocol/sdk-js/build/did/Did' +import { IDidDocumentSigned } from '@kiltprotocol/sdk-js/build/did/Did' describe('contacts endpoint (e2e)', () => { let app: INestApplication @@ -91,10 +91,10 @@ describe('contacts endpoint (e2e)', () => { }) it('gets did by contact address', async () => { - const didAlice = sdk.Did.fromIdentity( + const didAlice = sdk.Did.signDidDocument( + sdk.Did.fromIdentity(idAlice).createDefaultDidDocument(), idAlice - ).createDefaultDidDocument() - + ) await contactsService.add({ ...contactA, did: didAlice }) await request(app.getHttpServer()) .get(`/contacts/did/${contactA.publicIdentity.address}`) @@ -195,15 +195,12 @@ describe('contacts endpoint (e2e)', () => { }) describe('with did', () => { - let didAlice: IDidDocument - let signature: string + let didAlice: IDidDocumentSigned beforeAll(() => { - didAlice = sdk.Did.fromIdentity(idAlice).createDefaultDidDocument() - // TODO (KILTprotocol/ticket#687): I would expect this to work, but it doesn't: - // signature = sdk.Did.signDidDocument(didAlice, idAlice).signature - signature = idAlice.signStr( - sdk.Crypto.hashStr(JSON.stringify(didAlice)) + didAlice = sdk.Did.signDidDocument( + sdk.Did.fromIdentity(idAlice).createDefaultDidDocument(), + idAlice ) }) @@ -215,7 +212,6 @@ describe('contacts endpoint (e2e)', () => { publicIdentity: idAlice.getPublicIdentity(), metaData: { name: 'Alice' }, did: didAlice, - signature, } as Contact) .expect(201) @@ -246,7 +242,6 @@ describe('contacts endpoint (e2e)', () => { publicIdentity: idAlice.getPublicIdentity(), metaData: { name: 'Alice' }, did: didAlice, - signature, } as Contact) .expect(201) @@ -266,7 +261,7 @@ describe('contacts endpoint (e2e)', () => { .send({ publicIdentity: idAlice.getPublicIdentity(), metaData: { name: 'Alice' }, - did: didAlice, + did: { ...didAlice, signature: '' }, } as Contact) .expect(400) @@ -279,10 +274,10 @@ describe('contacts endpoint (e2e)', () => { .send({ publicIdentity: idAlice.getPublicIdentity(), metaData: { name: 'Alice' }, - did: didAlice, - signature: idAlice.signStr( - JSON.stringify({ ...didAlice, service: 'www.happy-phishing.com' }) - ), + did: { + ...didAlice, + signature: didAlice.signature.replace('d', 'f'), + }, } as Contact) .expect(400)