From 9354954d3616c29aa8bc754044a24ca6f04912f4 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 1 Apr 2024 17:23:06 +0530 Subject: [PATCH 01/29] Update public key param in bpiSubject model --- .../src/bri/identity/bpiSubjects/models/bpiSubject.ts | 11 +++++++---- .../src/bri/identity/bpiSubjects/models/publicKey.ts | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts b/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts index d17c5bd24..7e35f5d74 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts @@ -43,10 +43,13 @@ export class BpiSubject { this.description = newDescription; } - public updatePublicKey(newPk: PublicKey): void { - this.publicKeys = this.publicKeys.map((key) => - key.type == newPk.type ? (key = newPk) : key, - ); + public updatePublicKeys(newPKs: PublicKey[]): void { + newPKs.map((newKey: PublicKey) => { + const index = this.publicKeys.findIndex( + (oldKey: PublicKey) => oldKey.type == newKey.type, + ); + this.publicKeys[index] = newKey; + }); } public updateLoginNonce(): void { diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/models/publicKey.ts b/examples/bri-3/src/bri/identity/bpiSubjects/models/publicKey.ts index efa0acf60..4129afb50 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/models/publicKey.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/models/publicKey.ts @@ -16,10 +16,10 @@ export class PublicKey { value: string; @AutoMap() - bpiSubjectId: string; + bpiSubjectId?: string; @AutoMap() - bpiSubject: BpiSubject; + bpiSubject?: BpiSubject; constructor( id: string, From 9273b604411f9062da1381d5bd98c276bbcde296 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 1 Apr 2024 17:37:22 +0530 Subject: [PATCH 02/29] Handle Eddsa public keys in BpiSubject --- .../bpiSubjects/agents/bpiSubjects.agent.ts | 5 +- .../agents/bpiSubjectsStorage.agent.ts | 8 +-- .../dtos/request/createBpiSubject.dto.spec.ts | 16 +++-- .../api/dtos/request/createBpiSubject.dto.ts | 5 +- .../dtos/request/updateBpiSubject.dto.spec.ts | 16 +++-- .../api/dtos/request/updateBpiSubject.dto.ts | 5 +- .../api/dtos/response/bpiSubject.dto.ts | 3 +- .../api/subjects.controller.spec.ts | 62 +++++++++++++++---- .../bpiSubjects/api/subjects.controller.ts | 4 +- .../createBpiSubject.command.ts | 2 +- .../createBpiSubjectCommand.handler.ts | 25 +++++++- .../getAllBpiSubjectsQuery.handler.ts | 8 +-- .../getBpiSubjectByIdQuery.handler.ts | 7 +-- .../updateBpiSubject.command.ts | 5 +- .../updateBpiSubjectCommand.handler.ts | 33 ++++++++-- 15 files changed, 150 insertions(+), 54 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts index ed6a2cbbd..dc6dc486d 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts @@ -27,12 +27,11 @@ export class BpiSubjectAgent { public async createNewExternalBpiSubject( name: string, description: string, - publicKey: string, ): Promise { const externalRole = await this.storageAgent.getBpiSubjectRoleByName( BpiSubjectRoleName.EXTERNAL_BPI_SUBJECT, ); - return new BpiSubject(v4(), name, description, publicKey, [externalRole]); + return new BpiSubject(v4(), name, description, [], [externalRole]); } public async fetchUpdateCandidateAndThrowIfUpdateValidationFails( @@ -64,11 +63,9 @@ export class BpiSubjectAgent { bpiSubjectToUpdate: BpiSubject, name: string, description: string, - publicKey: string, ) { bpiSubjectToUpdate.updateName(name); bpiSubjectToUpdate.updateDescription(description); - bpiSubjectToUpdate.updatePublicKey(publicKey); } public async fetchDeleteCandidateAndThrowIfDeleteValidationFails( diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts index 80dff8a9f..df6cfd368 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts @@ -106,7 +106,7 @@ export class BpiSubjectStorageAgent extends PrismaService { }; }), }, - publicKey: { + publicKeys: { connect: bpiSubject.publicKeys.map((pk) => { return { id: pk.id, @@ -131,7 +131,7 @@ export class BpiSubjectStorageAgent extends PrismaService { }; }), }, - publicKey: { + publicKeys: { connect: bpiSubject.publicKeys.map((pk) => { return { id: pk.id, @@ -152,14 +152,14 @@ export class BpiSubjectStorageAgent extends PrismaService { async getBpiSubjectByPublicKey(publicKeyValue: string): Promise { const bpiSubjectModel = await this.prisma.bpiSubject.findFirst({ where: { - publicKey: { + publicKeys: { some: { value: publicKeyValue, }, }, }, include: { - publicKey: true, + publicKeys: true, }, }); diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.spec.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.spec.ts index 1d59e1ee3..8f5ec9237 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.spec.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.spec.ts @@ -6,7 +6,10 @@ import { CreateBpiSubjectDto } from './createBpiSubject.dto'; describe('CreateBpiSubjectDto', () => { it('should return error in case name not provided.', async () => { // Arrange - const dto = { desc: 'this is a description', publicKey: '2323' }; + const dto = { + desc: 'this is a description', + publicKeys: [{ type: 'ecdsa', value: '214324' }], + }; const createBpiSubjectDto = plainToInstance(CreateBpiSubjectDto, dto); // Act @@ -22,7 +25,10 @@ describe('CreateBpiSubjectDto', () => { it('should return error in case desc not provided.', async () => { // Arrange - const dto = { name: 'test', publicKey: '2323' }; + const dto = { + name: 'test', + publicKeys: [{ type: 'ecdsa', value: '214324' }], + }; const createBpiSubjectDto = plainToInstance(CreateBpiSubjectDto, dto); // Act @@ -46,9 +52,9 @@ describe('CreateBpiSubjectDto', () => { // Assert expect(errors.length).toBe(1); - expect(errors[0].property).toEqual('publicKey'); + expect(errors[0].property).toEqual('publicKeys'); expect(errors[0].constraints?.isNotEmpty).toContain( - 'publicKey ' + SHOULD_NOT_BE_EMPTY_VALIDATION_MESSAGE, + 'publicKeys ' + SHOULD_NOT_BE_EMPTY_VALIDATION_MESSAGE, ); }); @@ -57,7 +63,7 @@ describe('CreateBpiSubjectDto', () => { const dto = { name: 'test', desc: 'this is a description', - publicKey: '2323', + publicKeys: [{ type: 'ecdsa', value: '214324' }], }; const createBpiSubjectDto = plainToInstance(CreateBpiSubjectDto, dto); diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.ts index 10f77af8b..9b637a4ee 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.ts @@ -8,5 +8,8 @@ export class CreateBpiSubjectDto { desc: string; @IsNotEmpty() - publicKey: string; + publicKeys: { + type: string; + value: string; + }[]; } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.spec.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.spec.ts index 6fa666e34..37d4eb1e7 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.spec.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.spec.ts @@ -6,7 +6,10 @@ import { UpdateBpiSubjectDto } from './updateBpiSubject.dto'; describe('UpdateBpiSubjectDto', () => { it('should return error in case name not provided.', async () => { // Arrange - const dto = { desc: 'this is a description', publicKey: '2323' }; + const dto = { + desc: 'this is a description', + publicKeys: [{ type: 'ecdsa', value: '214324' }], + }; const updateBpiSubjectDto = plainToInstance(UpdateBpiSubjectDto, dto); // Act @@ -22,7 +25,10 @@ describe('UpdateBpiSubjectDto', () => { it('should return error in case desc not provided.', async () => { // Arrange - const dto = { name: 'test', publicKey: '2323' }; + const dto = { + name: 'test', + publicKeys: [{ type: 'ecdsa', value: '214324' }], + }; const updateBpiSubjectDto = plainToInstance(UpdateBpiSubjectDto, dto); // Act @@ -46,9 +52,9 @@ describe('UpdateBpiSubjectDto', () => { // Assert expect(errors.length).toBe(1); - expect(errors[0].property).toEqual('publicKey'); + expect(errors[0].property).toEqual('publicKeys'); expect(errors[0].constraints?.isNotEmpty).toContain( - 'publicKey ' + SHOULD_NOT_BE_EMPTY_VALIDATION_MESSAGE, + 'publicKeys ' + SHOULD_NOT_BE_EMPTY_VALIDATION_MESSAGE, ); }); @@ -57,7 +63,7 @@ describe('UpdateBpiSubjectDto', () => { const dto = { name: 'test', desc: 'this is a description', - publicKey: '2323', + publicKeys: [{ type: 'ecdsa', value: '214324' }], }; const updateBpiSubjectDto = plainToInstance(UpdateBpiSubjectDto, dto); diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.ts index ab0177381..8edf22d52 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.ts @@ -8,5 +8,8 @@ export class UpdateBpiSubjectDto { desc: string; @IsNotEmpty() - publicKey: string; + publicKeys: { + type: string; + value: string; + }[]; } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts index d3d4d98fc..09b2b492a 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts @@ -1,5 +1,6 @@ import { AutoMap } from '@automapper/classes'; import { BpiSubjectRoleDto } from './bpiSubjectRole.dto'; +import { PublicKey } from '../../../models/publicKey'; export class BpiSubjectDto { @AutoMap() @@ -12,7 +13,7 @@ export class BpiSubjectDto { description: string; @AutoMap() - publicKey: string; + publicKeys: PublicKey[]; @AutoMap(() => [BpiSubjectRoleDto]) roles: BpiSubjectRoleDto[]; diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.spec.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.spec.ts index a454f09f5..2e4ee4307 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.spec.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.spec.ts @@ -21,22 +21,37 @@ import { AuthzModule } from '../../../authz/authz.module'; import { mockDeep, DeepMockProxy } from 'jest-mock-extended'; import { BpiSubject } from '../models/bpiSubject'; import { uuid } from 'uuidv4'; +import { PublicKey, PublicKeyType } from '../models/publicKey'; +import { PrismaMapper } from '../../../../shared/prisma/prisma.mapper'; +import { MerkleTreeService } from '../../../merkleTree/services/merkleTree.service'; describe('SubjectController', () => { let sController: SubjectController; let subjectStorageAgentMock: DeepMockProxy; + + const existingBpiSubject1Id = uuid(); + const publicKeys1 = [ + new PublicKey('111', PublicKeyType.ECDSA, 'ecdsaPk', existingBpiSubject1Id), + new PublicKey('112', PublicKeyType.EDDSA, 'eddsaPk', existingBpiSubject1Id), + ]; const existingBpiSubject1 = new BpiSubject( - uuid(), + existingBpiSubject1Id, 'name', 'description', - 'pk', + publicKeys1, [], ); + + const existingBpiSubject2Id = uuid(); + const publicKeys2 = [ + new PublicKey('111', PublicKeyType.ECDSA, 'ecdsaPk', existingBpiSubject2Id), + new PublicKey('112', PublicKeyType.EDDSA, 'eddsaPk', existingBpiSubject2Id), + ]; const existingBpiSubject2 = new BpiSubject( uuid(), 'name2', 'description2', - 'pk2', + publicKeys2, [], ); @@ -59,7 +74,9 @@ describe('SubjectController', () => { GetAllBpiSubjectsQueryHandler, BpiSubjectStorageAgent, SubjectsProfile, + PrismaMapper, AuthzFactory, + MerkleTreeService, ], }) .overrideProvider(BpiSubjectStorageAgent) @@ -100,8 +117,8 @@ describe('SubjectController', () => { expect(fetchedBpiSubject.description).toEqual( existingBpiSubject1.description, ); - expect(fetchedBpiSubject.publicKey).toEqual( - existingBpiSubject1.publicKey, + expect(fetchedBpiSubject.publicKeys).toEqual( + existingBpiSubject1.publicKeys, ); }); }); @@ -135,13 +152,13 @@ describe('SubjectController', () => { expect(bpiSubjects[0].description).toEqual( existingBpiSubject1.description, ); - expect(bpiSubjects[0].publicKey).toEqual(existingBpiSubject1.publicKey); + expect(bpiSubjects[0].publicKeys).toEqual(existingBpiSubject1.publicKeys); expect(bpiSubjects[1].id).toEqual(existingBpiSubject2.id); expect(bpiSubjects[1].name).toEqual(existingBpiSubject2.name); expect(bpiSubjects[1].description).toEqual( existingBpiSubject2.description, ); - expect(bpiSubjects[1].publicKey).toEqual(existingBpiSubject2.publicKey); + expect(bpiSubjects[1].publicKeys).toEqual(existingBpiSubject2.publicKeys); }); }); @@ -150,7 +167,10 @@ describe('SubjectController', () => { // Arrange const requestDto = { desc: 'desc', - publicKey: 'publicKey', + publicKeys: [ + { type: 'ecdsa', value: 'ecdsaPk' }, + { type: 'ecdsa', value: 'ecdsaPk' }, + ], } as CreateBpiSubjectDto; // Act and assert @@ -164,7 +184,10 @@ describe('SubjectController', () => { const requestDto = { name: 'name', desc: 'desc', - publicKey: 'publicKey', + publicKeys: [ + { type: 'ecdsa', value: 'ecdsaPk' }, + { type: 'ecdsa', value: 'ecdsaPk' }, + ], } as CreateBpiSubjectDto; subjectStorageAgentMock.storeNewBpiSubject.mockResolvedValueOnce( existingBpiSubject1, @@ -186,7 +209,10 @@ describe('SubjectController', () => { const requestDto = { name: 'name', desc: 'desc', - publicKey: 'publicKey', + publicKeys: [ + { type: 'ecdsa', value: 'ecdsaPk' }, + { type: 'ecdsa', value: 'ecdsaPk' }, + ], } as UpdateBpiSubjectDto; // Act and assert @@ -203,13 +229,21 @@ describe('SubjectController', () => { const updateRequestDto = { name: 'name2', desc: 'desc2', - publicKey: 'publicKey2', + publicKeys: [ + { type: 'ecdsa', value: 'ecdsaPk' }, + { type: 'eddsa', value: 'eddsaPk' }, + ], } as UpdateBpiSubjectDto; subjectStorageAgentMock.updateBpiSubject.mockResolvedValueOnce({ ...existingBpiSubject1, name: updateRequestDto.name, description: updateRequestDto.desc, - publicKey: updateRequestDto.publicKey, + publicKeys: [ + new PublicKey('111', PublicKeyType.ECDSA, 'ecdsaPk', '123'), + , + new PublicKey('112', PublicKeyType.EDDSA, 'eddsaPk', '123'), + , + ], } as BpiSubject); // Act @@ -222,7 +256,9 @@ describe('SubjectController', () => { expect(updatedBpiSubject.id).toEqual(existingBpiSubject1.id); expect(updatedBpiSubject.name).toEqual(updateRequestDto.name); expect(updatedBpiSubject.description).toEqual(updateRequestDto.desc); - expect(updatedBpiSubject.publicKey).toEqual(updateRequestDto.publicKey); + expect(updatedBpiSubject.publicKeys[0].value).toEqual( + updateRequestDto.publicKeys[0].value, + ); }); }); diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.ts index c4095da9c..bc40275ff 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.ts @@ -43,7 +43,7 @@ export class SubjectController { new CreateBpiSubjectCommand( requestDto.name, requestDto.desc, - requestDto.publicKey, + requestDto.publicKeys, ), ); } @@ -59,7 +59,7 @@ export class SubjectController { id, requestDto.name, requestDto.desc, - requestDto.publicKey, + requestDto.publicKeys, ), ); } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubject.command.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubject.command.ts index cccecea16..7774835c7 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubject.command.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubject.command.ts @@ -2,6 +2,6 @@ export class CreateBpiSubjectCommand { constructor( public readonly name: string, public readonly description: string, - public readonly publicKey: string, + public readonly publicKeys: { type: string; value: string }[], ) {} } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubjectCommand.handler.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubjectCommand.handler.ts index 4dee36c14..0d4572cef 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubjectCommand.handler.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubjectCommand.handler.ts @@ -2,6 +2,8 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { BpiSubjectAgent } from '../../agents/bpiSubjects.agent'; import { BpiSubjectStorageAgent } from '../../agents/bpiSubjectsStorage.agent'; import { CreateBpiSubjectCommand } from './createBpiSubject.command'; +import { PublicKeyType } from '../../models/publicKey'; +import { v4 } from 'uuid'; @CommandHandler(CreateBpiSubjectCommand) export class CreateBpiSubjectCommandHandler @@ -18,13 +20,34 @@ export class CreateBpiSubjectCommandHandler const newBpiSubjectCandidate = await this.agent.createNewExternalBpiSubject( command.name, command.description, - command.publicKey, ); const newBpiSubject = await this.storageAgent.storeNewBpiSubject( newBpiSubjectCandidate, ); + const newPublicKeys = await Promise.all( + command.publicKeys.map(async (key) => { + let publicKeyType; + switch (key.type.toLowerCase()) { + case 'ecdsa': + publicKeyType = PublicKeyType.ECDSA; + break; + case 'eddsa': + publicKeyType = PublicKeyType.EDDSA; + break; + default: + } + + return await this.storageAgent.storePublicKey( + v4(), + publicKeyType, + key.value, + newBpiSubject.id, + ); + }), + ); + return newBpiSubject.id; } } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getAllBpiSubjects/getAllBpiSubjectsQuery.handler.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getAllBpiSubjects/getAllBpiSubjectsQuery.handler.ts index 5647b0605..d684ecd66 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getAllBpiSubjects/getAllBpiSubjectsQuery.handler.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getAllBpiSubjects/getAllBpiSubjectsQuery.handler.ts @@ -1,24 +1,22 @@ import { IQueryHandler, QueryHandler } from '@nestjs/cqrs'; -import { BpiSubjectDto } from '../../api/dtos/response/bpiSubject.dto'; import { BpiSubjectStorageAgent } from '../../agents/bpiSubjectsStorage.agent'; import { GetAllBpiSubjectsQuery } from './getAllBpiSubjects.query'; -import { InjectMapper } from '@automapper/nestjs'; import { BpiSubject } from '../../models/bpiSubject'; -import { Mapper } from '@automapper/core'; +import { PrismaMapper as Mapper } from '../../../../../shared/prisma/prisma.mapper'; @QueryHandler(GetAllBpiSubjectsQuery) export class GetAllBpiSubjectsQueryHandler implements IQueryHandler { constructor( - @InjectMapper() private autoMapper: Mapper, + private readonly mapper: Mapper, private readonly storageAgent: BpiSubjectStorageAgent, ) {} async execute() { const bpiSubjects = await this.storageAgent.getAllBpiSubjects(); return bpiSubjects.map((bp) => { - return this.autoMapper.map(bp, BpiSubject, BpiSubjectDto); + return this.mapper.map(bp, BpiSubject); }); } } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getBpiSubjectById/getBpiSubjectByIdQuery.handler.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getBpiSubjectById/getBpiSubjectByIdQuery.handler.ts index 429a7fb60..82e4e41f1 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getBpiSubjectById/getBpiSubjectByIdQuery.handler.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getBpiSubjectById/getBpiSubjectByIdQuery.handler.ts @@ -4,8 +4,7 @@ import { BpiSubjectStorageAgent } from '../../agents/bpiSubjectsStorage.agent'; import { GetBpiSubjectByIdQuery } from './getBpiSubjectById.query'; import { NotFoundException } from '@nestjs/common'; import { NOT_FOUND_ERR_MESSAGE } from '../../api/err.messages'; -import { Mapper } from '@automapper/core'; -import { InjectMapper } from '@automapper/nestjs'; +import { PrismaMapper as Mapper } from '../../../../../shared/prisma/prisma.mapper'; import { BpiSubject } from '../../models/bpiSubject'; @QueryHandler(GetBpiSubjectByIdQuery) @@ -13,7 +12,7 @@ export class GetBpiSubjectByIdQueryHandler implements IQueryHandler { constructor( - @InjectMapper() private autoMapper: Mapper, + private readonly mapper: Mapper, private readonly storageAgent: BpiSubjectStorageAgent, ) {} @@ -24,6 +23,6 @@ export class GetBpiSubjectByIdQueryHandler throw new NotFoundException(NOT_FOUND_ERR_MESSAGE); } - return this.autoMapper.map(bpiSubject, BpiSubject, BpiSubjectDto); + return this.mapper.map(bpiSubject, BpiSubject); } } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubject.command.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubject.command.ts index a4dc06548..d16ad4219 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubject.command.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubject.command.ts @@ -3,6 +3,9 @@ export class UpdateBpiSubjectCommand { public readonly id: string, public readonly name: string, public readonly description: string, - public readonly publicKey: string, + public readonly publicKeys: { + type: string; + value: string; + }[], ) {} } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts index dbab2567b..b63662334 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts @@ -1,18 +1,17 @@ -import { Mapper } from '@automapper/core'; -import { InjectMapper } from '@automapper/nestjs'; +import { PrismaMapper as Mapper } from '../../../../../shared/prisma/prisma.mapper'; import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { BpiSubjectAgent } from '../../agents/bpiSubjects.agent'; import { BpiSubjectStorageAgent } from '../../agents/bpiSubjectsStorage.agent'; -import { BpiSubjectDto } from '../../api/dtos/response/bpiSubject.dto'; import { BpiSubject } from '../../models/bpiSubject'; import { UpdateBpiSubjectCommand } from './updateBpiSubject.command'; +import { PublicKey, PublicKeyType } from '../../models/publicKey'; @CommandHandler(UpdateBpiSubjectCommand) export class UpdateBpiSubjectCommandHandler implements ICommandHandler { constructor( - @InjectMapper() private mapper: Mapper, + private readonly mapper: Mapper, private agent: BpiSubjectAgent, private storageAgent: BpiSubjectStorageAgent, ) {} @@ -23,17 +22,39 @@ export class UpdateBpiSubjectCommandHandler command.id, ); + const newPublicKeys = await Promise.all( + command.publicKeys.map(async (key) => { + let publicKeyType; + switch (key.type.toLowerCase()) { + case 'ecdsa': + publicKeyType = PublicKeyType.ECDSA; + break; + case 'eddsa': + publicKeyType = PublicKeyType.EDDSA; + break; + default: + } + + const newKey = await this.storageAgent.updatePublicKey( + publicKeyType, + key.value, + bpiSubjectToUpdate.id, + ); + + return newKey; + }), + ); + this.agent.updateBpiSubject( bpiSubjectToUpdate, command.name, command.description, - command.publicKey, ); const bpiSubject = await this.storageAgent.updateBpiSubject( bpiSubjectToUpdate, ); - return this.mapper.map(bpiSubject, BpiSubject, BpiSubjectDto); + return this.mapper.map(bpiSubject, BpiSubject); } } From 35a2aa839e2d9a3d17710a67ea70814da22fea8b Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 1 Apr 2024 17:46:47 +0530 Subject: [PATCH 03/29] Update authAgent to handle publicKeys --- .../bri-3/src/bri/auth/agent/auth.agent.ts | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/examples/bri-3/src/bri/auth/agent/auth.agent.ts b/examples/bri-3/src/bri/auth/agent/auth.agent.ts index fa7dd91b0..de8d95fdb 100644 --- a/examples/bri-3/src/bri/auth/agent/auth.agent.ts +++ b/examples/bri-3/src/bri/auth/agent/auth.agent.ts @@ -7,6 +7,8 @@ import { BpiSubject } from '../../../bri/identity/bpiSubjects/models/bpiSubject' import { LoggingService } from '../../../shared/logging/logging.service'; import { INVALID_SIGNATURE, USER_NOT_AUTHORIZED } from '../api/err.messages'; import { jwtConstants } from '../constants'; +import { buildBabyjub, buildEddsa } from 'circomlibjs'; +import * as crypto from 'crypto'; @Injectable() export class AuthAgent { @@ -23,12 +25,14 @@ export class AuthAgent { signature: string, publicKey: string, ): void { - if (!this.verifySignatureAgainstPublicKey(message, signature, publicKey)) { + if ( + !this.verifyEcdsaSignatureAgainstPublicKey(message, signature, publicKey) + ) { throw new UnauthorizedException(INVALID_SIGNATURE); } } - verifySignatureAgainstPublicKey( + verifyEcdsaSignatureAgainstPublicKey( message: string, signature: string, senderPublicKey: string, @@ -63,6 +67,40 @@ export class AuthAgent { return isValid; } + async verifyEddsaSignatureAgainstPublicKey( + message: string, + signature: string, + senderPublicKey: string, + ): Promise { + const eddsa = await buildEddsa(); + const babyJub = await buildBabyjub(); + + const hashedPayload = crypto + .createHash(`${process.env.MERKLE_TREE_HASH_ALGH}`) + .update(JSON.stringify(message)) + .digest(); + + const publicKey = Uint8Array.from(Buffer.from(signature, 'hex')); + const publicKeyPoints = babyJub.unpackPoint(publicKey); + + const eddsaSignature = Uint8Array.from(Buffer.from(signature, 'hex')); + const unpackedSignature = eddsa.unpackSignature(eddsaSignature); + + const isValid = eddsa.verifyPedersen( + hashedPayload, + unpackedSignature, + publicKeyPoints, + ); + + if (!isValid) { + this.logger.logWarn( + `Signature: ${signature} for public key ${senderPublicKey} is invalid.`, + ); + } + + return isValid; + } + async getBpiSubjectByPublicKey(publicKey: string) { return this.bpiSubjectStorageAgent.getBpiSubjectByPublicKey(publicKey); } From e9c459e5a4d16ded7bf6d65d21354f38a5518578 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 1 Apr 2024 17:48:03 +0530 Subject: [PATCH 04/29] Update message tests to handle public keys --- .../api/messages.controller.spec.ts | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/examples/bri-3/src/bri/communication/api/messages.controller.spec.ts b/examples/bri-3/src/bri/communication/api/messages.controller.spec.ts index 36ee0fc6b..13802136e 100644 --- a/examples/bri-3/src/bri/communication/api/messages.controller.spec.ts +++ b/examples/bri-3/src/bri/communication/api/messages.controller.spec.ts @@ -36,6 +36,10 @@ import { MessageController } from './messages.controller'; import { mockDeep, DeepMockProxy } from 'jest-mock-extended'; import { PrismaService } from '../../../shared/prisma/prisma.service'; import { PrismaClient } from '@prisma/client'; +import { + PublicKey, + PublicKeyType, +} from '../../identity/bpiSubjects/models/publicKey'; describe('MessageController', () => { let mController: MessageController; @@ -52,20 +56,37 @@ describe('MessageController', () => { }); beforeEach(async () => { - existingBpiSubject1 = new BpiSubject( - '', - 'name', - 'desc', - '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', - [], - ); - existingBpiSubject2 = new BpiSubject( - '', - 'name2', - 'desc2', - '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', - [], - ); + const publicKeys1 = [ + new PublicKey( + '111', + PublicKeyType.ECDSA, + '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', + '123', + ), + new PublicKey( + '112', + PublicKeyType.EDDSA, + '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', + '123', + ), + ]; + existingBpiSubject1 = new BpiSubject('', 'name', 'desc', publicKeys1, []); + + const publicKeys2 = [ + new PublicKey( + '111', + PublicKeyType.ECDSA, + '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + '123', + ), + new PublicKey( + '112', + PublicKeyType.EDDSA, + '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + '123', + ), + ]; + existingBpiSubject2 = new BpiSubject('', 'name2', 'desc2', publicKeys2, []); existingBpiMessage = new BpiMessage( 'f3e4295d-6a2a-4f04-8477-02f781eb93f8', From d26e7e524c70729521606e95729f976ad55b3825 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 1 Apr 2024 17:50:23 +0530 Subject: [PATCH 05/29] Use publicKeys in messaging --- .../createBpiMessageCommand.handler.ts | 9 +++++++-- .../processInboundMessageCommand.handler.ts | 18 ++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/examples/bri-3/src/bri/communication/capabilities/createBpiMessage/createBpiMessageCommand.handler.ts b/examples/bri-3/src/bri/communication/capabilities/createBpiMessage/createBpiMessageCommand.handler.ts index f6bc0b9a2..1a0369c8a 100644 --- a/examples/bri-3/src/bri/communication/capabilities/createBpiMessage/createBpiMessageCommand.handler.ts +++ b/examples/bri-3/src/bri/communication/capabilities/createBpiMessage/createBpiMessageCommand.handler.ts @@ -4,6 +4,7 @@ import { BpiMessageAgent } from '../../agents/bpiMessages.agent'; import { BpiMessageStorageAgent } from '../../agents/bpiMessagesStorage.agent'; import { MessagingAgent } from '../../agents/messaging.agent'; import { CreateBpiMessageCommand } from './createBpiMessage.command'; +import { PublicKeyType } from '../../../identity/bpiSubjects/models/publicKey'; @CommandHandler(CreateBpiMessageCommand) export class CreateBpiMessageCommandHandler @@ -30,7 +31,9 @@ export class CreateBpiMessageCommandHandler this.authAgent.throwIfSignatureVerificationFails( command.content, command.signature, - fromBpiSubject.publicKey, + fromBpiSubject.publicKeys.filter( + (key) => key.type == PublicKeyType.ECDSA, + )[0].value, ); const newBpiMessageCandidate = this.agent.createNewBpiMessage( @@ -47,7 +50,9 @@ export class CreateBpiMessageCommandHandler ); await this.messagingAgent.publishMessage( - toBpiSubject.publicKey, + toBpiSubject.publicKeys.filter( + (key) => key.type == PublicKeyType.ECDSA, + )[0].value, this.messagingAgent.serializeBpiMessage(newBpiMessage), ); diff --git a/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts b/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts index 58b2f9558..f5c7f7e7e 100644 --- a/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts +++ b/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts @@ -4,6 +4,7 @@ import { BpiMessageAgent } from '../../agents/bpiMessages.agent'; import { BpiMessageStorageAgent } from '../../agents/bpiMessagesStorage.agent'; import { MessagingAgent } from '../../agents/messaging.agent'; import { ProcessInboundBpiMessageCommand } from './processInboundMessage.command'; +import { PublicKeyType } from '../../../identity/bpiSubjects/models/publicKey'; // Difference between this and the create bpi message command handler is that this one does not // stop the execution flow by throwing a nestjs exception (which results in 404 response in the other handler) @@ -31,11 +32,14 @@ export class ProcessInboundMessageCommandHandler return false; } - const isSignatureValid = this.authAgent.verifySignatureAgainstPublicKey( - command.content, - command.signature, - fromBpiSubject.publicKey, - ); + const isSignatureValid = + this.authAgent.verifyEddsaSignatureAgainstPublicKey( + command.content, + command.signature, + fromBpiSubject.publicKeys.filter( + (key) => key.type == PublicKeyType.EDDSA, + )[0].value, + ); if (!isSignatureValid) { return false; @@ -55,7 +59,9 @@ export class ProcessInboundMessageCommandHandler ); await this.messagingAgent.publishMessage( - toBpiSubject.publicKey, + toBpiSubject.publicKeys.filter( + (key) => key.type == PublicKeyType.ECDSA, + )[0].value, this.messagingAgent.serializeBpiMessage(newBpiMessage), ); From 18ec1c2f8a3a90392f22c598c5b9e46ec4579fbe Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 1 Apr 2024 17:55:30 +0530 Subject: [PATCH 06/29] Use publicKeys in subjectAccounts test --- .../api/subjectAccounts.controller.spec.ts | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjectAccounts/api/subjectAccounts.controller.spec.ts b/examples/bri-3/src/bri/identity/bpiSubjectAccounts/api/subjectAccounts.controller.spec.ts index 7efdb1b02..637ae8c66 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjectAccounts/api/subjectAccounts.controller.spec.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjectAccounts/api/subjectAccounts.controller.spec.ts @@ -22,6 +22,7 @@ import { SubjectsProfile } from '../../bpiSubjects/subjects.profile'; import { mockDeep, DeepMockProxy } from 'jest-mock-extended'; import { BpiSubjectAccount } from '../models/bpiSubjectAccount'; import { uuid } from 'uuidv4'; +import { PublicKey, PublicKeyType } from '../../bpiSubjects/models/publicKey'; describe('SubjectAccountController', () => { let subjectAccountController: SubjectAccountController; @@ -66,18 +67,22 @@ describe('SubjectAccountController', () => { }); const createBpiSubjectAccount = async () => { + const publicKeys = [ + new PublicKey('111', PublicKeyType.ECDSA, 'ecdsaPk', '123'), + new PublicKey('112', PublicKeyType.EDDSA, 'eddsaPk', '123'), + ]; const ownerBpiSubject = new BpiSubject( '123', 'owner', 'desc', - 'publicKey', + publicKeys, [], ); const creatorBpiSubject = new BpiSubject( '321', 'creator', 'desc', - 'publicKey', + publicKeys, [], ); @@ -191,11 +196,15 @@ describe('SubjectAccountController', () => { describe('createBpiSubjectAccount', () => { it('should throw BadRequest if non existent creator provided', async () => { // Arrange + const publicKeys = [ + new PublicKey('111', PublicKeyType.ECDSA, 'ecdsaPk', '123'), + new PublicKey('112', PublicKeyType.EDDSA, 'eddsaPk', '123'), + ]; const ownerBpiSubject = new BpiSubject( '123', 'owner', 'desc', - 'publicKey', + publicKeys, [], ); const creatorBpiSubjectId = 'not-existing-id'; @@ -215,11 +224,15 @@ describe('SubjectAccountController', () => { it('should throw BadRequest if non existent owner provided', async () => { // Arrange + const publicKeys = [ + new PublicKey('111', PublicKeyType.ECDSA, 'ecdsaPk', '123'), + new PublicKey('112', PublicKeyType.EDDSA, 'eddsaPk', '123'), + ]; const creatorBpiSubject = new BpiSubject( '123', 'creator', 'desc', - 'publicKey', + publicKeys, [], ); const ownerBpiSubjectId = 'not-existing-id'; From 0e3c61b84e85f1df64ca319bad562102c45ea0cd Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 1 Apr 2024 17:57:25 +0530 Subject: [PATCH 07/29] Use publicKeys in bpiAccounts tests --- .../bpiAccounts/api/accounts.controller.spec.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts b/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts index 69c41458d..89ee27aee 100644 --- a/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts +++ b/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts @@ -28,6 +28,10 @@ import { GetAllBpiAccountsQueryHandler } from '../capabilities/getAllBpiAccounts import { GetBpiAccountByIdQueryHandler } from '../capabilities/getBpiAccountById/getBpiAccountByIdQuery.handler'; import { UpdateBpiAccountCommandHandler } from '../capabilities/updateBpiAccount/updateBpiAccountCommand.handler'; import { BpiAccount } from '../models/bpiAccount'; +import { + PublicKey, + PublicKeyType, +} from '../../../identity/bpiSubjects/models/publicKey'; import { AccountController } from './accounts.controller'; import { CreateBpiAccountDto } from './dtos/request/createBpiAccount.dto'; import { NOT_FOUND_ERR_MESSAGE } from './err.messages'; @@ -91,18 +95,23 @@ describe('AccountController', () => { }); const createBpiSubjectAccount = () => { + const publicKeys = [ + new PublicKey('111', PublicKeyType.ECDSA, 'ecdsaPk', '123'), + new PublicKey('112', PublicKeyType.EDDSA, 'eddsaPk', '123'), + ]; + const ownerBpiSubject = new BpiSubject( '123', 'owner', 'desc', - 'publicKey', + publicKeys, [], ); const creatorBpiSubject = new BpiSubject( '321', 'creator', 'desc', - 'publicKey', + publicKeys, [], ); return new BpiSubjectAccount( From 2f203d98a8793ff70311236ff2444cdbca2c177c Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 1 Apr 2024 18:01:08 +0530 Subject: [PATCH 08/29] Use publicKeys in transaction tests --- .../agents/transactions.agent.spec.ts | 70 +++++++++++++++---- .../transactions/agents/transactions.agent.ts | 16 +++-- .../api/transactions.controller.spec.ts | 12 +++- ...rocessInboundTransactionCommand.handler.ts | 14 ++-- 4 files changed, 84 insertions(+), 28 deletions(-) diff --git a/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts b/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts index 89ec6e4ca..05f31b32d 100644 --- a/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts +++ b/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts @@ -15,6 +15,7 @@ import { Workstep, BpiAccount, PrismaClient, + PublicKeyType, } from '../../../../__mocks__/@prisma/client'; import { Test, TestingModule } from '@nestjs/testing'; import { SnarkjsCircuitService } from '../../zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service'; @@ -28,6 +29,7 @@ import { NOT_FOUND_ERR_MESSAGE as WORKFLOW_NOT_FOUND_ERR_MESSAGE } from '../../w import { AuthModule } from '../../../bri/auth/auth.module'; import { AutomapperModule } from '@automapper/nestjs'; import { classes } from '@automapper/classes'; +import { uuid } from 'uuidv4'; let agent: TransactionAgent; let authAgent: AuthAgent; @@ -76,8 +78,25 @@ beforeEach(async () => { data: { name: 'name', description: 'desc', - publicKey: - '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', + publicKeys: { + createMany: { + data: [ + { + type: PublicKeyType.ECDSA, + value: + '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', + }, + { + type: PublicKeyType.EDDSA, + value: + '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', + }, + ], + }, + }, + }, + include: { + publicKeys: true, }, }); @@ -85,8 +104,23 @@ beforeEach(async () => { data: { name: 'name2', description: 'desc2', - publicKey: - '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + publicKeys: { + create: [ + { + type: PublicKeyType.ECDSA, + value: + '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + }, + { + type: PublicKeyType.EDDSA, + value: + '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + }, + ], + }, + }, + include: { + publicKeys: true, }, }); @@ -100,7 +134,11 @@ beforeEach(async () => { recoveryKey: '', }, include: { - ownerBpiSubject: true, + ownerBpiSubject: { + include: { + publicKeys: true, + }, + }, }, }); bpiSubjectAccount2 = await prisma.bpiSubjectAccount.create({ @@ -113,7 +151,11 @@ beforeEach(async () => { recoveryKey: '', }, include: { - ownerBpiSubject: true, + ownerBpiSubject: { + include: { + publicKeys: true, + }, + }, }, }); bpiAccount1 = await prisma.bpiAccount.create({ @@ -246,8 +288,8 @@ describe('Transaction Agent', () => { it('Should return false when validateTransactionForExecution invoked with tx with wrong signature', async () => { // Arrange jest - .spyOn(authAgent, 'verifySignatureAgainstPublicKey') - .mockImplementationOnce(() => false); + .spyOn(authAgent, 'verifyEddsaSignatureAgainstPublicKey') + .mockImplementationOnce(async () => false); const tx = new Transaction( '1', 1, @@ -270,8 +312,8 @@ describe('Transaction Agent', () => { it('Should return false when validateTransactionForExecution invoked with tx with status not processing', async () => { // Arrange jest - .spyOn(authAgent, 'verifySignatureAgainstPublicKey') - .mockImplementationOnce(() => true); + .spyOn(authAgent, 'verifyEddsaSignatureAgainstPublicKey') + .mockImplementationOnce(async () => true); const tx = new Transaction( '1', 1, @@ -294,8 +336,8 @@ describe('Transaction Agent', () => { it('Should return false when validateTransactionForExecution invoked with tx with nonce not bpi account nonce + 1', async () => { // Arrange jest - .spyOn(authAgent, 'verifySignatureAgainstPublicKey') - .mockImplementationOnce(() => true); + .spyOn(authAgent, 'verifyEddsaSignatureAgainstPublicKey') + .mockImplementationOnce(async () => true); const tx = new Transaction( '1', 2, @@ -318,8 +360,8 @@ describe('Transaction Agent', () => { it('Should return true when validateTransactionForExecution invoked with tx with all properties correctly set', async () => { // Arrange jest - .spyOn(authAgent, 'verifySignatureAgainstPublicKey') - .mockImplementationOnce(() => true); + .spyOn(authAgent, 'verifyEddsaSignatureAgainstPublicKey') + .mockImplementationOnce(async () => true); const tx = new Transaction( '1', 1, diff --git a/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts b/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts index 2c9d31f16..2dd23d42d 100644 --- a/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts +++ b/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts @@ -7,8 +7,6 @@ import { import { Transaction } from '../models/transaction'; import { TransactionStatus } from '../models/transactionStatus.enum'; -import MerkleTree from 'merkletreejs'; -import { Witness } from 'src/bri/zeroKnowledgeProof/models/witness'; import { AuthAgent } from '../../auth/agent/auth.agent'; import { BpiSubjectAccount } from '../../identity/bpiSubjectAccounts/models/bpiSubjectAccount'; import { MerkleTreeService } from '../../merkleTree/services/merkleTree.service'; @@ -23,6 +21,7 @@ import { } from '../api/err.messages'; import { TransactionStorageAgent } from './transactionStorage.agent'; import { TransactionResult } from '../models/transactionResult'; +import { PublicKeyType } from '../../identity/bpiSubjects/models/publicKey'; @Injectable() export class TransactionAgent { @@ -154,11 +153,14 @@ export class TransactionAgent { return false; } - const isSignatureValid = this.authAgent.verifySignatureAgainstPublicKey( - tx.payload, - tx.signature, - tx.fromBpiSubjectAccount.ownerBpiSubject.publicKey, - ); + const isSignatureValid = + await this.authAgent.verifyEddsaSignatureAgainstPublicKey( + tx.payload, + tx.signature, + tx.fromBpiSubjectAccount.ownerBpiSubject.publicKeys.filter( + (key) => key.type == PublicKeyType.EDDSA, + )[0].value, + ); if (!isSignatureValid) { return false; diff --git a/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts b/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts index 701e5d321..e65400141 100644 --- a/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts +++ b/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts @@ -29,6 +29,10 @@ import { UpdateTransactionDto } from './dtos/request/updateTransaction.dto'; import { NOT_FOUND_ERR_MESSAGE } from './err.messages'; import { TransactionController } from './transactions.controller'; import { MerkleTreeService } from '../../merkleTree/services/merkleTree.service'; +import { + PublicKey, + PublicKeyType, +} from '../../identity/bpiSubjects/models/publicKey'; describe('TransactionController', () => { let controller: TransactionController; @@ -36,18 +40,22 @@ describe('TransactionController', () => { let subjectAccountStorageAgentMock: DeepMockProxy; const createBpiSubjectAccount = (id: string) => { + const publicKeys = [ + new PublicKey('111', PublicKeyType.ECDSA, 'ecdsaPk', '123'), + new PublicKey('112', PublicKeyType.EDDSA, 'eddsaPk', '123'), + ]; const ownerBpiSubject = new BpiSubject( '123', 'owner', 'desc', - 'publicKey', + publicKeys, [], ); const creatorBpiSubject = new BpiSubject( '321', 'creator', 'desc', - 'publicKey', + publicKeys, [], ); diff --git a/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts b/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts index 9db4ef7a1..ee1c87519 100644 --- a/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts +++ b/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts @@ -4,6 +4,7 @@ import { AuthAgent } from '../../../auth/agent/auth.agent'; import { TransactionAgent } from '../../agents/transactions.agent'; import { TransactionStorageAgent } from '../../agents/transactionStorage.agent'; import { ProcessInboundBpiTransactionCommand } from './processInboundTransaction.command'; +import { PublicKeyType } from '../../../identity/bpiSubjects/models/publicKey'; // Difference between this and the create bpi transaction command handler is that this one does not // stop the execution flow by throwing a nestjs exception (which results in 404 response in the other handler) @@ -34,11 +35,14 @@ export class ProcessInboundTransactionCommandHandler return false; } - const isSignatureValid = this.authAgent.verifySignatureAgainstPublicKey( - command.payload, - command.signature, - subjectAccounts[0].ownerBpiSubject.publicKey, - ); + const isSignatureValid = + this.authAgent.verifyEddsaSignatureAgainstPublicKey( + command.payload, + command.signature, + subjectAccounts[0].ownerBpiSubject.publicKeys.filter( + (key) => key.type == PublicKeyType.EDDSA, + )[0].value, + ); if (!isSignatureValid) { return false; From 54c29ba2087da1cea7b8afa5a03d9daed2cad3d4 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 1 Apr 2024 18:04:20 +0530 Subject: [PATCH 09/29] Use publicKeys in workgroup test --- .../workstepExecutedEvent.handler.ts | 10 ++++++++-- .../workgroups/api/workgroups.controller.spec.ts | 10 +++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/examples/bri-3/src/bri/vsm/capabilites/handleWorkstepEvents/workstepExecutedEvent.handler.ts b/examples/bri-3/src/bri/vsm/capabilites/handleWorkstepEvents/workstepExecutedEvent.handler.ts index 386150a6e..1a5afba27 100644 --- a/examples/bri-3/src/bri/vsm/capabilites/handleWorkstepEvents/workstepExecutedEvent.handler.ts +++ b/examples/bri-3/src/bri/vsm/capabilites/handleWorkstepEvents/workstepExecutedEvent.handler.ts @@ -5,6 +5,7 @@ import { LoggingService } from '../../../../shared/logging/logging.service'; import { BpiMessage } from '../../../communication/models/bpiMessage'; import { BpiMessageType } from '../../../communication/models/bpiMessageType.enum'; import { MessagingAgent } from '../../../communication/agents/messaging.agent'; +import { PublicKeyType } from '../../../identity/bpiSubjects/models/publicKey'; @EventsHandler(WorkstepExecutedEvent) export class WorkstepExecutedEventHandler @@ -42,11 +43,16 @@ export class WorkstepExecutedEventHandler messageType, ); + const publicKey = + event.tx.toBpiSubjectAccount.ownerBpiSubject.publicKeys.filter( + (key) => key.type == PublicKeyType.ECDSA, + )[0].value; + // Change channels to publish message here - const channels = [event.tx.fromBpiSubjectAccount.ownerBpiSubject.publicKey]; + const channels = [publicKey]; if (event.status == 'Success') { - channels.push(event.tx.toBpiSubjectAccount.ownerBpiSubject.publicKey); + channels.push(publicKey); } await this.publishMessage(channels, bpiMessage); diff --git a/examples/bri-3/src/bri/workgroup/workgroups/api/workgroups.controller.spec.ts b/examples/bri-3/src/bri/workgroup/workgroups/api/workgroups.controller.spec.ts index 7089bd0b4..84bdf7334 100644 --- a/examples/bri-3/src/bri/workgroup/workgroups/api/workgroups.controller.spec.ts +++ b/examples/bri-3/src/bri/workgroup/workgroups/api/workgroups.controller.spec.ts @@ -28,14 +28,22 @@ import { uuid } from 'uuidv4'; import { WorkgroupProfile } from '../workgroups.profile'; import { PrismaService } from '../../../../shared/prisma/prisma.service'; import { PrismaClient } from '@prisma/client'; +import { + PublicKey, + PublicKeyType, +} from '../../../identity/bpiSubjects/models/publicKey'; describe('WorkgroupsController', () => { let workgroupController: WorkgroupController; let workgroupStorageAgentMock: DeepMockProxy; let subjectStorageAgentMock: DeepMockProxy; + const publicKeys = [ + new PublicKey('111', PublicKeyType.ECDSA, 'ecdsaPk', '123'), + new PublicKey('112', PublicKeyType.EDDSA, 'eddsaPk', '123'), + ]; const createTestBpiSubject = () => { - return new BpiSubject('123', 'name', 'desc', 'pubkey', []); + return new BpiSubject('123', 'name', 'desc', publicKeys, []); }; const createTestWorkgroup = (): Workgroup => { From 3668f47072f3b9074bd64c8e2108a86d0304df98 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 1 Apr 2024 18:07:42 +0530 Subject: [PATCH 10/29] Use publicKeys in shared test builder data --- examples/bri-3/prisma/seed.ts | 40 +++++++++++++------ examples/bri-3/src/shared/testing/builders.ts | 9 +++-- .../src/shared/testing/testData.helper.ts | 12 +++++- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/examples/bri-3/prisma/seed.ts b/examples/bri-3/prisma/seed.ts index 98f6932dd..206b8e4f7 100644 --- a/examples/bri-3/prisma/seed.ts +++ b/examples/bri-3/prisma/seed.ts @@ -1,4 +1,4 @@ -import { PrismaClient } from '@prisma/client'; +import { PrismaClient, PublicKeyType } from '@prisma/client'; const prisma = new PrismaClient(); @@ -21,19 +21,35 @@ async function main() { }, }); - await prisma.bpiSubject.create({ + const internalBpiSubject = await prisma.bpiSubject.create({ data: { - name: 'BpiAdmin', - description: 'Internal Bpi Subject of this Bpi', - publicKey: '0x044e851fa6118d0d33f11ebf8d4cae2a25dca959f06c1ab87b8fec9ccbf0ca0021b7efc27c786f9480f9f11cfe8df1ae991329654308611148a35a2277ba5909fe', - // private key 0x0fbdb56ab0fecb2f406fa807d9e6558baedacc1c15c0e2703b77d4c08441e4fe, used for testing purposes only - loginNonce: '', - roles: { - connect: { - id: internalBpiSubjectRole.id - }, + name: 'BpiAdmin', + description: 'Internal Bpi Subject of this Bpi', + // private key 0x0fbdb56ab0fecb2f406fa807d9e6558baedacc1c15c0e2703b77d4c08441e4fe, used for testing purposes only + loginNonce: '', + roles: { + connect: { + id: internalBpiSubjectRole.id, }, - } + }, + }, + }); + + await prisma.publicKey.createMany({ + data: [ + { + type: PublicKeyType.ECDSA, + value: + '0x044e851fa6118d0d33f11ebf8d4cae2a25dca959f06c1ab87b8fec9ccbf0ca0021b7efc27c786f9480f9f11cfe8df1ae991329654308611148a35a2277ba5909fe', + bpiSubjectId: internalBpiSubject.id, + }, + { + type: PublicKeyType.EDDSA, + value: + '0x044e851fa6118d0d33f11ebf8d4cae2a25dca959f06c1ab87b8fec9ccbf0ca0021b7efc27c786f9480f9f11cfe8df1ae991329654308611148a35a2277ba5909fe', + bpiSubjectId: internalBpiSubject.id, + }, + ], }); } main() diff --git a/examples/bri-3/src/shared/testing/builders.ts b/examples/bri-3/src/shared/testing/builders.ts index 8f9068cf0..0d16f1e84 100644 --- a/examples/bri-3/src/shared/testing/builders.ts +++ b/examples/bri-3/src/shared/testing/builders.ts @@ -4,6 +4,7 @@ import { BpiAccount } from '../../bri/state/bpiAccounts/models/bpiAccount'; import { BpiSubjectAccount } from '../../bri/identity/bpiSubjectAccounts/models/bpiSubjectAccount'; import { BpiSubject } from '../../bri/identity/bpiSubjects/models/bpiSubject'; import { BpiSubjectRole } from '../../bri/identity/bpiSubjects/models/bpiSubjectRole'; +import { PublicKey } from '../../bri/identity/bpiSubjects/models/publicKey'; import { BpiMerkleTree } from '../../bri/merkleTree/models/bpiMerkleTree'; import { Workflow } from '../../bri/workgroup/workflows/models/workflow'; import { Workgroup } from '../../bri/workgroup/workgroups/models/workgroup'; @@ -121,7 +122,7 @@ export class BpiSubjectBuilder { private id: string; private name: string; private description: string; - private publicKey: string; + private publicKeys: PublicKey[]; private loginNonce: string; private roles: BpiSubjectRole[]; @@ -142,8 +143,8 @@ export class BpiSubjectBuilder { return this; } - setPublicKey(publicKey: string): BpiSubjectBuilder { - this.publicKey = publicKey; + setPublicKey(publicKeys: PublicKey[]): BpiSubjectBuilder { + this.publicKeys = publicKeys; return this; } @@ -162,7 +163,7 @@ export class BpiSubjectBuilder { this.id, this.name, this.description, - this.publicKey, + this.publicKeys, this.roles, ); } diff --git a/examples/bri-3/src/shared/testing/testData.helper.ts b/examples/bri-3/src/shared/testing/testData.helper.ts index da7a555b6..916962d5b 100644 --- a/examples/bri-3/src/shared/testing/testData.helper.ts +++ b/examples/bri-3/src/shared/testing/testData.helper.ts @@ -6,6 +6,10 @@ import { BpiSubjectRole, BpiSubjectRoleName, } from '../../bri/identity/bpiSubjects/models/bpiSubjectRole'; +import { + PublicKey, + PublicKeyType, +} from '../../bri/identity/bpiSubjects/models/publicKey'; import { Workflow } from '../../bri/workgroup/workflows/models/workflow'; import { Workstep } from '../../bri/workgroup/worksteps/models/workstep'; import { @@ -51,11 +55,15 @@ export class TestDataHelper { }; public static createBpiSubject = () => { + const bpiSubjectId = uuid(); const bpiSubject = new BpiSubjectBuilder() - .setId(uuid()) + .setId(bpiSubjectId) .setName('name') .setDescription('desc') - .setPublicKey('pk') + .setPublicKey([ + new PublicKey(uuid(), PublicKeyType.ECDSA, 'ecdsaPk', bpiSubjectId), + new PublicKey(uuid(), PublicKeyType.EDDSA, 'eddsaPk', bpiSubjectId), + ]) .setRoles([ new BpiSubjectRole( uuid(), From a770b951d90780db534bef2ccf934d995a7cb2dc Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Fri, 12 Apr 2024 16:37:15 +0530 Subject: [PATCH 11/29] Add comments on Ecdsa and Eddsa --- examples/bri-3/src/bri/identity/bpiSubjects/models/publicKey.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/models/publicKey.ts b/examples/bri-3/src/bri/identity/bpiSubjects/models/publicKey.ts index 4129afb50..4f8b6fc93 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/models/publicKey.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/models/publicKey.ts @@ -1,6 +1,8 @@ import { AutoMap } from '@automapper/classes'; import { BpiSubject } from './bpiSubject'; +//ECDSA - Used for login, messaging, etc. +//EDDSA - Used for signing transactions (inside zk circuit) export enum PublicKeyType { ECDSA = 'ECDSA', EDDSA = 'EDDSA', From 9d781f9226b89454b6d162328f7f75e6da384026 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Fri, 12 Apr 2024 16:42:46 +0530 Subject: [PATCH 12/29] Add publicKeyDto to BpiSubject --- .../bpiSubjects/api/dtos/request/createBpiSubject.dto.ts | 6 ++---- .../bpiSubjects/api/dtos/request/publicKey.dto.ts | 8 ++++++++ .../bpiSubjects/api/dtos/request/updateBpiSubject.dto.ts | 6 ++---- 3 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/publicKey.dto.ts diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.ts index 9b637a4ee..48f55737a 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/createBpiSubject.dto.ts @@ -1,4 +1,5 @@ import { IsNotEmpty } from 'class-validator'; +import { PublicKeyDto } from './publicKey.dto'; export class CreateBpiSubjectDto { @IsNotEmpty() @@ -8,8 +9,5 @@ export class CreateBpiSubjectDto { desc: string; @IsNotEmpty() - publicKeys: { - type: string; - value: string; - }[]; + publicKeys: PublicKeyDto[]; } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/publicKey.dto.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/publicKey.dto.ts new file mode 100644 index 000000000..82c6eb12d --- /dev/null +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/publicKey.dto.ts @@ -0,0 +1,8 @@ +import { IsNotEmpty } from 'class-validator'; +export class PublicKeyDto { + @IsNotEmpty() + type: string; + + @IsNotEmpty() + value: string; +} diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.ts index 8edf22d52..0df339e63 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/updateBpiSubject.dto.ts @@ -1,4 +1,5 @@ import { IsNotEmpty } from 'class-validator'; +import { PublicKeyDto } from './publicKey.dto'; export class UpdateBpiSubjectDto { @IsNotEmpty() @@ -8,8 +9,5 @@ export class UpdateBpiSubjectDto { desc: string; @IsNotEmpty() - publicKeys: { - type: string; - value: string; - }[]; + publicKeys: PublicKeyDto[]; } From b3edae71a6935d899c05e34e9e108ce991d9c3a0 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Fri, 12 Apr 2024 16:48:28 +0530 Subject: [PATCH 13/29] Add publicKeyDto to response bpiSubjectDto --- .../identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts index 09b2b492a..30cd01f4c 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts @@ -1,6 +1,6 @@ import { AutoMap } from '@automapper/classes'; import { BpiSubjectRoleDto } from './bpiSubjectRole.dto'; -import { PublicKey } from '../../../models/publicKey'; +import { PublicKeyDto } from '../request/publicKey.dto'; export class BpiSubjectDto { @AutoMap() @@ -13,7 +13,7 @@ export class BpiSubjectDto { description: string; @AutoMap() - publicKeys: PublicKey[]; + publicKeys: PublicKeyDto[]; @AutoMap(() => [BpiSubjectRoleDto]) roles: BpiSubjectRoleDto[]; From b2080ccea9d75f3f2cffef5b819e5379836db3c0 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Fri, 12 Apr 2024 17:01:41 +0530 Subject: [PATCH 14/29] Add publicKeyDto to commandHandler --- .../createBpiSubject/createBpiSubject.command.ts | 3 ++- .../updateBpiSubject/updateBpiSubject.command.ts | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubject.command.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubject.command.ts index 7774835c7..4371b849d 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubject.command.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubject.command.ts @@ -1,7 +1,8 @@ +import { PublicKeyDto } from '../../api/dtos/request/publicKey.dto'; export class CreateBpiSubjectCommand { constructor( public readonly name: string, public readonly description: string, - public readonly publicKeys: { type: string; value: string }[], + public readonly publicKeys: PublicKeyDto[], ) {} } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubject.command.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubject.command.ts index d16ad4219..d1061a8b8 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubject.command.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubject.command.ts @@ -1,11 +1,9 @@ +import { PublicKeyDto } from '../../api/dtos/request/publicKey.dto'; export class UpdateBpiSubjectCommand { constructor( public readonly id: string, public readonly name: string, public readonly description: string, - public readonly publicKeys: { - type: string; - value: string; - }[], + public readonly publicKeys: PublicKeyDto[], ) {} } From 9f3a89688fcb632c4809f908dc511d9fc90def9d Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Fri, 12 Apr 2024 18:32:51 +0530 Subject: [PATCH 15/29] Build fix --- examples/bri-3/prisma/seed.ts | 39 +++++++++++++------ .../createBpiMessageCommand.handler.ts | 4 +- .../processInboundMessageCommand.handler.ts | 4 +- .../bpiSubjects/agents/bpiSubjects.agent.ts | 29 +++++++++++++- .../agents/bpiSubjectsStorage.agent.ts | 6 +-- .../createBpiSubjectCommand.handler.ts | 25 +----------- .../transactions/agents/transactions.agent.ts | 2 +- ...rocessInboundTransactionCommand.handler.ts | 2 +- .../workstepExecutedEvent.handler.ts | 8 +++- .../snarkjs/utils/computePublicInputs.ts | 5 ++- examples/bri-3/src/shared/testing/builders.ts | 5 ++- .../src/shared/testing/testData.helper.ts | 11 +++++- 12 files changed, 85 insertions(+), 55 deletions(-) diff --git a/examples/bri-3/prisma/seed.ts b/examples/bri-3/prisma/seed.ts index 98f6932dd..ef3eba7f8 100644 --- a/examples/bri-3/prisma/seed.ts +++ b/examples/bri-3/prisma/seed.ts @@ -1,4 +1,5 @@ -import { PrismaClient } from '@prisma/client'; +import { PrismaClient, PublicKeyType } from '@prisma/client'; +import { type } from 'os'; const prisma = new PrismaClient(); @@ -23,17 +24,33 @@ async function main() { await prisma.bpiSubject.create({ data: { - name: 'BpiAdmin', - description: 'Internal Bpi Subject of this Bpi', - publicKey: '0x044e851fa6118d0d33f11ebf8d4cae2a25dca959f06c1ab87b8fec9ccbf0ca0021b7efc27c786f9480f9f11cfe8df1ae991329654308611148a35a2277ba5909fe', - // private key 0x0fbdb56ab0fecb2f406fa807d9e6558baedacc1c15c0e2703b77d4c08441e4fe, used for testing purposes only - loginNonce: '', - roles: { - connect: { - id: internalBpiSubjectRole.id - }, + name: 'BpiAdmin', + description: 'Internal Bpi Subject of this Bpi', + publicKeys: { + createMany: { + data: [ + { + type: PublicKeyType.ECDSA, + value: + '0x044e851fa6118d0d33f11ebf8d4cae2a25dca959f06c1ab87b8fec9ccbf0ca0021b7efc27c786f9480f9f11cfe8df1ae991329654308611148a35a2277ba5909fe', + }, + { + type: PublicKeyType.EDDSA, + value: + '0x044e851fa6118d0d33f11ebf8d4cae2a25dca959f06c1ab87b8fec9ccbf0ca0021b7efc27c786f9480f9f11cfe8df1ae991329654308611148a35a2277ba5909fe', + }, + ], }, - } + }, + + // private key 0x0fbdb56ab0fecb2f406fa807d9e6558baedacc1c15c0e2703b77d4c08441e4fe, used for testing purposes only + loginNonce: '', + roles: { + connect: { + id: internalBpiSubjectRole.id, + }, + }, + }, }); } main() diff --git a/examples/bri-3/src/bri/communication/capabilities/createBpiMessage/createBpiMessageCommand.handler.ts b/examples/bri-3/src/bri/communication/capabilities/createBpiMessage/createBpiMessageCommand.handler.ts index f6bc0b9a2..9e87d91ad 100644 --- a/examples/bri-3/src/bri/communication/capabilities/createBpiMessage/createBpiMessageCommand.handler.ts +++ b/examples/bri-3/src/bri/communication/capabilities/createBpiMessage/createBpiMessageCommand.handler.ts @@ -30,7 +30,7 @@ export class CreateBpiMessageCommandHandler this.authAgent.throwIfSignatureVerificationFails( command.content, command.signature, - fromBpiSubject.publicKey, + fromBpiSubject.publicKeys[0].value, ); const newBpiMessageCandidate = this.agent.createNewBpiMessage( @@ -47,7 +47,7 @@ export class CreateBpiMessageCommandHandler ); await this.messagingAgent.publishMessage( - toBpiSubject.publicKey, + toBpiSubject.publicKeys[0].value, this.messagingAgent.serializeBpiMessage(newBpiMessage), ); diff --git a/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts b/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts index 58b2f9558..ee60079bb 100644 --- a/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts +++ b/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts @@ -34,7 +34,7 @@ export class ProcessInboundMessageCommandHandler const isSignatureValid = this.authAgent.verifySignatureAgainstPublicKey( command.content, command.signature, - fromBpiSubject.publicKey, + fromBpiSubject.publicKeys[0].value, ); if (!isSignatureValid) { @@ -55,7 +55,7 @@ export class ProcessInboundMessageCommandHandler ); await this.messagingAgent.publishMessage( - toBpiSubject.publicKey, + toBpiSubject.publicKeys[0].value, this.messagingAgent.serializeBpiMessage(newBpiMessage), ); diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts index dc6dc486d..64f572de4 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts @@ -11,6 +11,8 @@ import { } from '../api/err.messages'; import { BpiSubjectStorageAgent } from './bpiSubjectsStorage.agent'; import { BpiSubjectRoleName } from '../models/bpiSubjectRole'; +import { PublicKeyDto } from '../api/dtos/request/publicKey.dto'; +import { PublicKey, PublicKeyType } from '../models/publicKey'; // Agent methods have extremely declarative names and perform a single task @Injectable() @@ -27,11 +29,36 @@ export class BpiSubjectAgent { public async createNewExternalBpiSubject( name: string, description: string, + publicKeys: PublicKeyDto[], ): Promise { const externalRole = await this.storageAgent.getBpiSubjectRoleByName( BpiSubjectRoleName.EXTERNAL_BPI_SUBJECT, ); - return new BpiSubject(v4(), name, description, [], [externalRole]); + + const bpiSubjectId = v4(); + + const publicKeyCandidates = publicKeys.map((key) => { + let publicKeyType; + + switch (key.type.toLowerCase()) { + case 'ecdsa': + publicKeyType = PublicKeyType.ECDSA; + break; + case 'eddsa': + publicKeyType = PublicKeyType.EDDSA; + break; + default: + } + return new PublicKey(v4(), publicKeyType, key.value, bpiSubjectId); + }); + + return new BpiSubject( + bpiSubjectId, + name, + description, + publicKeyCandidates, + [externalRole], + ); } public async fetchUpdateCandidateAndThrowIfUpdateValidationFails( diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts index df6cfd368..96cd88d8d 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts @@ -107,11 +107,7 @@ export class BpiSubjectStorageAgent extends PrismaService { }), }, publicKeys: { - connect: bpiSubject.publicKeys.map((pk) => { - return { - id: pk.id, - }; - }), + createMany: { data: bpiSubject.publicKeys }, }, }, }); diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubjectCommand.handler.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubjectCommand.handler.ts index 0d4572cef..fa45b7ceb 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubjectCommand.handler.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/createBpiSubject/createBpiSubjectCommand.handler.ts @@ -2,8 +2,6 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { BpiSubjectAgent } from '../../agents/bpiSubjects.agent'; import { BpiSubjectStorageAgent } from '../../agents/bpiSubjectsStorage.agent'; import { CreateBpiSubjectCommand } from './createBpiSubject.command'; -import { PublicKeyType } from '../../models/publicKey'; -import { v4 } from 'uuid'; @CommandHandler(CreateBpiSubjectCommand) export class CreateBpiSubjectCommandHandler @@ -20,34 +18,13 @@ export class CreateBpiSubjectCommandHandler const newBpiSubjectCandidate = await this.agent.createNewExternalBpiSubject( command.name, command.description, + command.publicKeys, ); const newBpiSubject = await this.storageAgent.storeNewBpiSubject( newBpiSubjectCandidate, ); - const newPublicKeys = await Promise.all( - command.publicKeys.map(async (key) => { - let publicKeyType; - switch (key.type.toLowerCase()) { - case 'ecdsa': - publicKeyType = PublicKeyType.ECDSA; - break; - case 'eddsa': - publicKeyType = PublicKeyType.EDDSA; - break; - default: - } - - return await this.storageAgent.storePublicKey( - v4(), - publicKeyType, - key.value, - newBpiSubject.id, - ); - }), - ); - return newBpiSubject.id; } } diff --git a/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts b/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts index 2c9d31f16..f9d1e3baa 100644 --- a/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts +++ b/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts @@ -157,7 +157,7 @@ export class TransactionAgent { const isSignatureValid = this.authAgent.verifySignatureAgainstPublicKey( tx.payload, tx.signature, - tx.fromBpiSubjectAccount.ownerBpiSubject.publicKey, + tx.fromBpiSubjectAccount.ownerBpiSubject.publicKeys[0].value, ); if (!isSignatureValid) { diff --git a/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts b/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts index 9db4ef7a1..ab09094ab 100644 --- a/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts +++ b/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts @@ -37,7 +37,7 @@ export class ProcessInboundTransactionCommandHandler const isSignatureValid = this.authAgent.verifySignatureAgainstPublicKey( command.payload, command.signature, - subjectAccounts[0].ownerBpiSubject.publicKey, + subjectAccounts[0].ownerBpiSubject.publicKeys[0].value, ); if (!isSignatureValid) { diff --git a/examples/bri-3/src/bri/vsm/capabilites/handleWorkstepEvents/workstepExecutedEvent.handler.ts b/examples/bri-3/src/bri/vsm/capabilites/handleWorkstepEvents/workstepExecutedEvent.handler.ts index 386150a6e..8bb83ff0e 100644 --- a/examples/bri-3/src/bri/vsm/capabilites/handleWorkstepEvents/workstepExecutedEvent.handler.ts +++ b/examples/bri-3/src/bri/vsm/capabilites/handleWorkstepEvents/workstepExecutedEvent.handler.ts @@ -43,10 +43,14 @@ export class WorkstepExecutedEventHandler ); // Change channels to publish message here - const channels = [event.tx.fromBpiSubjectAccount.ownerBpiSubject.publicKey]; + const channels = [ + event.tx.fromBpiSubjectAccount.ownerBpiSubject.publicKeys[0].value, + ]; if (event.status == 'Success') { - channels.push(event.tx.toBpiSubjectAccount.ownerBpiSubject.publicKey); + channels.push( + event.tx.toBpiSubjectAccount.ownerBpiSubject.publicKeys[0].value, + ); } await this.publishMessage(channels, bpiMessage); diff --git a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/utils/computePublicInputs.ts b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/utils/computePublicInputs.ts index 2567104a4..d3793effb 100644 --- a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/utils/computePublicInputs.ts +++ b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/snarkjs/utils/computePublicInputs.ts @@ -47,7 +47,8 @@ export const computeEcdsaSigPublicInputs = (tx: Transaction) => { ethers.utils.arrayify(ethers.utils.hashMessage(tx.payload)), ); - const publicKey = tx.fromBpiSubjectAccount.ownerBpiSubject.publicKey; + const publicKey = + tx.fromBpiSubjectAccount.ownerBpiSubject.publicKeys[0].value; return computeEffectiveEcdsaSigPublicInputs( ecdsaSignature, @@ -113,7 +114,7 @@ export const computeEddsaSigPublicInputs = async (tx: Transaction) => { .digest(); const publicKey = - tx.fromBpiSubjectAccount.ownerBpiSubject.publicKey.split(','); + tx.fromBpiSubjectAccount.ownerBpiSubject.publicKeys[0].value.split(','); const publicKeyPoints = [ Uint8Array.from(Buffer.from(publicKey[0], 'hex')), diff --git a/examples/bri-3/src/shared/testing/builders.ts b/examples/bri-3/src/shared/testing/builders.ts index 8f9068cf0..730f2554c 100644 --- a/examples/bri-3/src/shared/testing/builders.ts +++ b/examples/bri-3/src/shared/testing/builders.ts @@ -8,6 +8,7 @@ import { BpiMerkleTree } from '../../bri/merkleTree/models/bpiMerkleTree'; import { Workflow } from '../../bri/workgroup/workflows/models/workflow'; import { Workgroup } from '../../bri/workgroup/workgroups/models/workgroup'; import { Workstep } from '../../bri/workgroup/worksteps/models/workstep'; +import { PublicKey } from '../../bri/identity/bpiSubjects/models/publicKey'; export class WorkstepBuilder { private id: string; @@ -121,7 +122,7 @@ export class BpiSubjectBuilder { private id: string; private name: string; private description: string; - private publicKey: string; + private publicKey: PublicKey[]; private loginNonce: string; private roles: BpiSubjectRole[]; @@ -142,7 +143,7 @@ export class BpiSubjectBuilder { return this; } - setPublicKey(publicKey: string): BpiSubjectBuilder { + setPublicKey(publicKey: PublicKey[]): BpiSubjectBuilder { this.publicKey = publicKey; return this; } diff --git a/examples/bri-3/src/shared/testing/testData.helper.ts b/examples/bri-3/src/shared/testing/testData.helper.ts index da7a555b6..b0e92dec3 100644 --- a/examples/bri-3/src/shared/testing/testData.helper.ts +++ b/examples/bri-3/src/shared/testing/testData.helper.ts @@ -16,6 +16,10 @@ import { WorkgroupBuilder, WorkstepBuilder, } from './builders'; +import { + PublicKey, + PublicKeyType, +} from '../../bri/identity/bpiSubjects/models/publicKey'; // A place to encapsulate creation of test data objects used for controller testing. // These objects will later be used to mock prisma.client calls only once during test bootstrap @@ -51,11 +55,14 @@ export class TestDataHelper { }; public static createBpiSubject = () => { + const bpiSubjectId = uuid(); const bpiSubject = new BpiSubjectBuilder() - .setId(uuid()) + .setId(bpiSubjectId) .setName('name') .setDescription('desc') - .setPublicKey('pk') + .setPublicKey([ + new PublicKey(uuid(), PublicKeyType.ECDSA, '12345', bpiSubjectId), + ]) .setRoles([ new BpiSubjectRole( uuid(), From 3d426799262ca1978cb0357bda32eac73173020e Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 14:04:37 +0530 Subject: [PATCH 16/29] Add valid Eddsa public key to seed.ts --- examples/bri-3/prisma/seed.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/bri-3/prisma/seed.ts b/examples/bri-3/prisma/seed.ts index ef3eba7f8..a664cb5be 100644 --- a/examples/bri-3/prisma/seed.ts +++ b/examples/bri-3/prisma/seed.ts @@ -37,7 +37,7 @@ async function main() { { type: PublicKeyType.EDDSA, value: - '0x044e851fa6118d0d33f11ebf8d4cae2a25dca959f06c1ab87b8fec9ccbf0ca0021b7efc27c786f9480f9f11cfe8df1ae991329654308611148a35a2277ba5909fe', + '0x038a312f5b75fbd4f677c080c7f35089c898f2cb75002d659e051fdc1c6b3e06', }, ], }, From 47c2c144342413451bf1035a5ece012dff5f9f65 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 14:08:14 +0530 Subject: [PATCH 17/29] Revert mapper changes --- .../getAllBpiSubjects/getAllBpiSubjectsQuery.handler.ts | 8 +++++--- .../getBpiSubjectById/getBpiSubjectByIdQuery.handler.ts | 7 ++++--- .../circuitInputsParser/circuitInputParser.service.ts | 4 +++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getAllBpiSubjects/getAllBpiSubjectsQuery.handler.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getAllBpiSubjects/getAllBpiSubjectsQuery.handler.ts index d684ecd66..5647b0605 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getAllBpiSubjects/getAllBpiSubjectsQuery.handler.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getAllBpiSubjects/getAllBpiSubjectsQuery.handler.ts @@ -1,22 +1,24 @@ import { IQueryHandler, QueryHandler } from '@nestjs/cqrs'; +import { BpiSubjectDto } from '../../api/dtos/response/bpiSubject.dto'; import { BpiSubjectStorageAgent } from '../../agents/bpiSubjectsStorage.agent'; import { GetAllBpiSubjectsQuery } from './getAllBpiSubjects.query'; +import { InjectMapper } from '@automapper/nestjs'; import { BpiSubject } from '../../models/bpiSubject'; -import { PrismaMapper as Mapper } from '../../../../../shared/prisma/prisma.mapper'; +import { Mapper } from '@automapper/core'; @QueryHandler(GetAllBpiSubjectsQuery) export class GetAllBpiSubjectsQueryHandler implements IQueryHandler { constructor( - private readonly mapper: Mapper, + @InjectMapper() private autoMapper: Mapper, private readonly storageAgent: BpiSubjectStorageAgent, ) {} async execute() { const bpiSubjects = await this.storageAgent.getAllBpiSubjects(); return bpiSubjects.map((bp) => { - return this.mapper.map(bp, BpiSubject); + return this.autoMapper.map(bp, BpiSubject, BpiSubjectDto); }); } } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getBpiSubjectById/getBpiSubjectByIdQuery.handler.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getBpiSubjectById/getBpiSubjectByIdQuery.handler.ts index 82e4e41f1..429a7fb60 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getBpiSubjectById/getBpiSubjectByIdQuery.handler.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/getBpiSubjectById/getBpiSubjectByIdQuery.handler.ts @@ -4,7 +4,8 @@ import { BpiSubjectStorageAgent } from '../../agents/bpiSubjectsStorage.agent'; import { GetBpiSubjectByIdQuery } from './getBpiSubjectById.query'; import { NotFoundException } from '@nestjs/common'; import { NOT_FOUND_ERR_MESSAGE } from '../../api/err.messages'; -import { PrismaMapper as Mapper } from '../../../../../shared/prisma/prisma.mapper'; +import { Mapper } from '@automapper/core'; +import { InjectMapper } from '@automapper/nestjs'; import { BpiSubject } from '../../models/bpiSubject'; @QueryHandler(GetBpiSubjectByIdQuery) @@ -12,7 +13,7 @@ export class GetBpiSubjectByIdQueryHandler implements IQueryHandler { constructor( - private readonly mapper: Mapper, + @InjectMapper() private autoMapper: Mapper, private readonly storageAgent: BpiSubjectStorageAgent, ) {} @@ -23,6 +24,6 @@ export class GetBpiSubjectByIdQueryHandler throw new NotFoundException(NOT_FOUND_ERR_MESSAGE); } - return this.mapper.map(bpiSubject, BpiSubject); + return this.autoMapper.map(bpiSubject, BpiSubject, BpiSubjectDto); } } diff --git a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts index 05fe7be54..50aeaac46 100644 --- a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts +++ b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts @@ -26,7 +26,9 @@ export class CircuitInputsParserService { switch (mapping.dataType) { case 'string': - result[mapping.circuitInput] = this.calculateStringCharCodeSum(value || mapping.defaultValue); + result[mapping.circuitInput] = this.calculateStringCharCodeSum( + value || mapping.defaultValue, + ); break; case 'integer': From 9897c83a2a4d756fa4fd0430b369c7161f2bfcfe Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 14:28:09 +0530 Subject: [PATCH 18/29] Remove unnecessary code from updateBpiSubject --- .../bpiSubjects/agents/bpiSubjects.agent.ts | 2 ++ .../updateBpiSubjectCommand.handler.ts | 24 +------------------ .../identity/bpiSubjects/models/bpiSubject.ts | 7 +++--- 3 files changed, 7 insertions(+), 26 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts index 64f572de4..ac81d1b6d 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjects.agent.ts @@ -90,9 +90,11 @@ export class BpiSubjectAgent { bpiSubjectToUpdate: BpiSubject, name: string, description: string, + publicKeys: PublicKeyDto[], ) { bpiSubjectToUpdate.updateName(name); bpiSubjectToUpdate.updateDescription(description); + bpiSubjectToUpdate.updatePublicKeys(publicKeys); } public async fetchDeleteCandidateAndThrowIfDeleteValidationFails( diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts index b63662334..b1ec6bbf8 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts @@ -22,33 +22,11 @@ export class UpdateBpiSubjectCommandHandler command.id, ); - const newPublicKeys = await Promise.all( - command.publicKeys.map(async (key) => { - let publicKeyType; - switch (key.type.toLowerCase()) { - case 'ecdsa': - publicKeyType = PublicKeyType.ECDSA; - break; - case 'eddsa': - publicKeyType = PublicKeyType.EDDSA; - break; - default: - } - - const newKey = await this.storageAgent.updatePublicKey( - publicKeyType, - key.value, - bpiSubjectToUpdate.id, - ); - - return newKey; - }), - ); - this.agent.updateBpiSubject( bpiSubjectToUpdate, command.name, command.description, + command.publicKeys, ); const bpiSubject = await this.storageAgent.updateBpiSubject( diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts b/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts index 7e35f5d74..46067da0c 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts @@ -2,6 +2,7 @@ import { AutoMap } from '@automapper/classes'; import { v4 } from 'uuid'; import { BpiSubjectRole } from './bpiSubjectRole'; import { PublicKeyType, PublicKey } from './publicKey'; +import { PublicKeyDto } from '../api/dtos/request/publicKey.dto'; export class BpiSubject { @AutoMap() @@ -43,12 +44,12 @@ export class BpiSubject { this.description = newDescription; } - public updatePublicKeys(newPKs: PublicKey[]): void { - newPKs.map((newKey: PublicKey) => { + public updatePublicKeys(newPKs: PublicKeyDto[]): void { + newPKs.map((newKey: PublicKeyDto) => { const index = this.publicKeys.findIndex( (oldKey: PublicKey) => oldKey.type == newKey.type, ); - this.publicKeys[index] = newKey; + this.publicKeys[index].value = newKey.value; }); } From 5965541fda64cc0ea8023360038e453431c8d6b1 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 14:53:30 +0530 Subject: [PATCH 19/29] Revert unnecessary changes to updateBpiSubject --- .../updateBpiSubject/updateBpiSubjectCommand.handler.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts index b1ec6bbf8..1828c55d2 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/capabilities/updateBpiSubject/updateBpiSubjectCommand.handler.ts @@ -1,17 +1,18 @@ -import { PrismaMapper as Mapper } from '../../../../../shared/prisma/prisma.mapper'; +import { Mapper } from '@automapper/core'; +import { InjectMapper } from '@automapper/nestjs'; import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { BpiSubjectAgent } from '../../agents/bpiSubjects.agent'; import { BpiSubjectStorageAgent } from '../../agents/bpiSubjectsStorage.agent'; import { BpiSubject } from '../../models/bpiSubject'; import { UpdateBpiSubjectCommand } from './updateBpiSubject.command'; -import { PublicKey, PublicKeyType } from '../../models/publicKey'; +import { BpiSubjectDto } from '../../api/dtos/response/bpiSubject.dto'; @CommandHandler(UpdateBpiSubjectCommand) export class UpdateBpiSubjectCommandHandler implements ICommandHandler { constructor( - private readonly mapper: Mapper, + @InjectMapper() private mapper: Mapper, private agent: BpiSubjectAgent, private storageAgent: BpiSubjectStorageAgent, ) {} @@ -33,6 +34,6 @@ export class UpdateBpiSubjectCommandHandler bpiSubjectToUpdate, ); - return this.mapper.map(bpiSubject, BpiSubject); + return this.mapper.map(bpiSubject, BpiSubject, BpiSubjectDto); } } From 89eb98df8e1701d36bf1ee75eaec993e2d421aaa Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 15:01:40 +0530 Subject: [PATCH 20/29] Change let to const in circuitInputParser --- .../circuit/circuitInputsParser/circuitInputParser.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts index 50aeaac46..dc30953e0 100644 --- a/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts +++ b/examples/bri-3/src/bri/zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service.ts @@ -11,7 +11,7 @@ export class CircuitInputsParserService { try { const jsonPayload = JSON.parse(payload); - for (let mapping of cim.mapping) { + for (const mapping of cim.mapping) { const value = this.getJsonValueByPath( jsonPayload, mapping.payloadJsonPath, From e964f806c17886b9c9ca62677147c4ff871afb98 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 18:28:50 +0530 Subject: [PATCH 21/29] Update publicKeys in bpiSubjectStorageAgent --- .../bpiSubjects/agents/bpiSubjectsStorage.agent.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts index 96cd88d8d..cf2c491d7 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts @@ -128,11 +128,10 @@ export class BpiSubjectStorageAgent extends PrismaService { }), }, publicKeys: { - connect: bpiSubject.publicKeys.map((pk) => { - return { - id: pk.id, - }; - }), + updateMany: bpiSubject.publicKeys.map((pk) => ({ + where: { id: pk.id }, + data: { value: pk.value }, + })), }, }, }); From 7e1623d121883c9e5a5130aeb2f019893a1a0be1 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 19:03:33 +0530 Subject: [PATCH 22/29] Add MerkleTree agent, storageAgent, service as provider --- .../workflows/api/workflows.controller.spec.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/examples/bri-3/src/bri/workgroup/workflows/api/workflows.controller.spec.ts b/examples/bri-3/src/bri/workgroup/workflows/api/workflows.controller.spec.ts index 6c978373c..1b63b6fe0 100644 --- a/examples/bri-3/src/bri/workgroup/workflows/api/workflows.controller.spec.ts +++ b/examples/bri-3/src/bri/workgroup/workflows/api/workflows.controller.spec.ts @@ -29,6 +29,9 @@ import { UpdateWorkflowDto } from './dtos/request/updateWorkflow.dto'; import { WorkflowController } from './workflows.controller'; import { PrismaService } from '../../../../shared/prisma/prisma.service'; import { PrismaClient } from '@prisma/client'; +import { MerkleTreeAgent } from '../../../merkleTree/agents/merkleTree.agent'; +import { MerkleTreeStorageAgent } from '../../../merkleTree/agents/merkleTreeStorage.agent'; +import { MerkleTreeService } from '../../../merkleTree/services/merkleTree.service'; describe('WorkflowsController', () => { let workflowController: WorkflowController; @@ -100,6 +103,7 @@ describe('WorkflowsController', () => { WorkgroupAgent, BpiAccountAgent, BpiSubjectAccountAgent, + MerkleTreeAgent, CreateWorkflowCommandHandler, UpdateWorkflowCommandHandler, DeleteWorkflowCommandHandler, @@ -107,22 +111,24 @@ describe('WorkflowsController', () => { GetAllWorkflowsQueryHandler, WorkflowStorageAgent, BpiAccountStorageAgent, + MerkleTreeStorageAgent, WorkstepProfile, WorkflowProfile, + MerkleTreeService, ], }) .overrideProvider(WorkflowStorageAgent) .useValue(mockDeep()) .overrideProvider(WorkstepStorageAgent) .useValue(mockDeep()) - .overrideProvider(BpiAccountAgent) - .useValue(mockDeep()) .overrideProvider(BpiSubjectAccountAgent) .useValue(mockDeep()) .overrideProvider(WorkgroupAgent) .useValue(mockDeep()) .overrideProvider(BpiAccountStorageAgent) .useValue(mockDeep()) + .overrideProvider(MerkleTreeStorageAgent) + .useValue(mockDeep()) .overrideProvider(PrismaService) .useValue(mockDeep()) .compile(); From 3a52e5cdd14ac2f07f519772bb83f3b8abdef92e Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 19:59:33 +0530 Subject: [PATCH 23/29] Bug fix updateBpiSubject test --- examples/bri-3/prisma/seed.ts | 3 ++- .../bpiSubjects/api/dtos/request/publicKey.dto.ts | 3 +++ .../bpiSubjects/api/dtos/response/bpiSubject.dto.ts | 2 +- .../bpiSubjects/api/subjects.controller.spec.ts | 13 +++++++++---- .../bri/identity/bpiSubjects/models/bpiSubject.ts | 5 +++-- .../bri/identity/bpiSubjects/subjects.profile.ts | 3 +++ .../bpiAccounts/api/accounts.controller.spec.ts | 9 ++++++--- 7 files changed, 27 insertions(+), 11 deletions(-) diff --git a/examples/bri-3/prisma/seed.ts b/examples/bri-3/prisma/seed.ts index a664cb5be..16af99758 100644 --- a/examples/bri-3/prisma/seed.ts +++ b/examples/bri-3/prisma/seed.ts @@ -34,16 +34,17 @@ async function main() { value: '0x044e851fa6118d0d33f11ebf8d4cae2a25dca959f06c1ab87b8fec9ccbf0ca0021b7efc27c786f9480f9f11cfe8df1ae991329654308611148a35a2277ba5909fe', }, + // private key 0x0fbdb56ab0fecb2f406fa807d9e6558baedacc1c15c0e2703b77d4c08441e4fe, used for testing purposes only { type: PublicKeyType.EDDSA, value: '0x038a312f5b75fbd4f677c080c7f35089c898f2cb75002d659e051fdc1c6b3e06', }, + // TODO private key ], }, }, - // private key 0x0fbdb56ab0fecb2f406fa807d9e6558baedacc1c15c0e2703b77d4c08441e4fe, used for testing purposes only loginNonce: '', roles: { connect: { diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/publicKey.dto.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/publicKey.dto.ts index 82c6eb12d..1b2dc85f4 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/publicKey.dto.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/request/publicKey.dto.ts @@ -1,8 +1,11 @@ +import { AutoMap } from '@automapper/classes'; import { IsNotEmpty } from 'class-validator'; export class PublicKeyDto { + @AutoMap() @IsNotEmpty() type: string; + @AutoMap() @IsNotEmpty() value: string; } diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts index 30cd01f4c..3e18ad3d6 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/dtos/response/bpiSubject.dto.ts @@ -12,7 +12,7 @@ export class BpiSubjectDto { @AutoMap() description: string; - @AutoMap() + @AutoMap(() => [PublicKeyDto]) publicKeys: PublicKeyDto[]; @AutoMap(() => [BpiSubjectRoleDto]) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.spec.ts b/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.spec.ts index 2e4ee4307..43ca3cf33 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.spec.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/api/subjects.controller.spec.ts @@ -117,8 +117,8 @@ describe('SubjectController', () => { expect(fetchedBpiSubject.description).toEqual( existingBpiSubject1.description, ); - expect(fetchedBpiSubject.publicKeys).toEqual( - existingBpiSubject1.publicKeys, + expect(fetchedBpiSubject.publicKeys[0].type).toEqual( + existingBpiSubject1.publicKeys[0].type, ); }); }); @@ -152,13 +152,18 @@ describe('SubjectController', () => { expect(bpiSubjects[0].description).toEqual( existingBpiSubject1.description, ); - expect(bpiSubjects[0].publicKeys).toEqual(existingBpiSubject1.publicKeys); + expect(bpiSubjects[0].publicKeys[0].type).toEqual( + existingBpiSubject1.publicKeys[0].type, + ); + expect(bpiSubjects[1].id).toEqual(existingBpiSubject2.id); expect(bpiSubjects[1].name).toEqual(existingBpiSubject2.name); expect(bpiSubjects[1].description).toEqual( existingBpiSubject2.description, ); - expect(bpiSubjects[1].publicKeys).toEqual(existingBpiSubject2.publicKeys); + expect(bpiSubjects[1].publicKeys[0].type).toEqual( + existingBpiSubject2.publicKeys[0].type, + ); }); }); diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts b/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts index 46067da0c..bb091d55e 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/models/bpiSubject.ts @@ -14,7 +14,7 @@ export class BpiSubject { @AutoMap() description: string; - @AutoMap() + @AutoMap(() => [PublicKey]) publicKeys: PublicKey[]; @AutoMap() @@ -47,7 +47,8 @@ export class BpiSubject { public updatePublicKeys(newPKs: PublicKeyDto[]): void { newPKs.map((newKey: PublicKeyDto) => { const index = this.publicKeys.findIndex( - (oldKey: PublicKey) => oldKey.type == newKey.type, + (oldKey: PublicKey) => + oldKey.type.toLowerCase() == newKey.type.toLowerCase(), ); this.publicKeys[index].value = newKey.value; }); diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/subjects.profile.ts b/examples/bri-3/src/bri/identity/bpiSubjects/subjects.profile.ts index 3daf2b25f..167332cb4 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/subjects.profile.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/subjects.profile.ts @@ -5,6 +5,8 @@ import { BpiSubjectDto } from './api/dtos/response/bpiSubject.dto'; import { BpiSubject } from './models/bpiSubject'; import { BpiSubjectRole } from './models/bpiSubjectRole'; import { BpiSubjectRoleDto } from './api/dtos/response/bpiSubjectRole.dto'; +import { PublicKey } from './models/publicKey'; +import { PublicKeyDto } from './api/dtos/request/publicKey.dto'; @Injectable() export class SubjectsProfile extends AutomapperProfile { @@ -16,6 +18,7 @@ export class SubjectsProfile extends AutomapperProfile { return (mapper) => { createMap(mapper, BpiSubject, BpiSubjectDto); createMap(mapper, BpiSubjectRole, BpiSubjectRoleDto); + createMap(mapper, PublicKey, PublicKeyDto); }; } } diff --git a/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts b/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts index 69c41458d..4c0c676c8 100644 --- a/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts +++ b/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts @@ -33,7 +33,10 @@ import { CreateBpiAccountDto } from './dtos/request/createBpiAccount.dto'; import { NOT_FOUND_ERR_MESSAGE } from './err.messages'; import { PrismaService } from '../../../../shared/prisma/prisma.service'; import { PrismaClient } from '@prisma/client'; - +import { + PublicKey, + PublicKeyType, +} from '../../../identity/bpiSubjects/models/publicKey'; describe('AccountController', () => { let accountController: AccountController; let accountStorageAgentMock: DeepMockProxy; @@ -95,14 +98,14 @@ describe('AccountController', () => { '123', 'owner', 'desc', - 'publicKey', + [new PublicKey('232', PublicKeyType.ECDSA, 'publicKey', '123')], [], ); const creatorBpiSubject = new BpiSubject( '321', 'creator', 'desc', - 'publicKey', + [new PublicKey('233', PublicKeyType.ECDSA, 'publicKey', '321')], [], ); return new BpiSubjectAccount( From 7b845c417ace6d50ca655ac46b001c45ada3206d Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 20:19:34 +0530 Subject: [PATCH 24/29] Update transaction.spec.ts tests to accept publicKeys --- .../bri-3/src/bri/auth/agent/auth.agent.ts | 42 ++++++++++- .../api/messages.controller.spec.ts | 23 +++++- .../processInboundMessageCommand.handler.ts | 11 +-- .../api/subjectAccounts.controller.spec.ts | 9 +-- .../agents/transactions.agent.spec.ts | 70 +++++++++++++++---- .../transactions/agents/transactions.agent.ts | 16 +++-- .../api/transactions.controller.spec.ts | 8 ++- ...rocessInboundTransactionCommand.handler.ts | 11 +-- .../api/workgroups.controller.spec.ts | 12 +++- 9 files changed, 160 insertions(+), 42 deletions(-) diff --git a/examples/bri-3/src/bri/auth/agent/auth.agent.ts b/examples/bri-3/src/bri/auth/agent/auth.agent.ts index fa7dd91b0..de8d95fdb 100644 --- a/examples/bri-3/src/bri/auth/agent/auth.agent.ts +++ b/examples/bri-3/src/bri/auth/agent/auth.agent.ts @@ -7,6 +7,8 @@ import { BpiSubject } from '../../../bri/identity/bpiSubjects/models/bpiSubject' import { LoggingService } from '../../../shared/logging/logging.service'; import { INVALID_SIGNATURE, USER_NOT_AUTHORIZED } from '../api/err.messages'; import { jwtConstants } from '../constants'; +import { buildBabyjub, buildEddsa } from 'circomlibjs'; +import * as crypto from 'crypto'; @Injectable() export class AuthAgent { @@ -23,12 +25,14 @@ export class AuthAgent { signature: string, publicKey: string, ): void { - if (!this.verifySignatureAgainstPublicKey(message, signature, publicKey)) { + if ( + !this.verifyEcdsaSignatureAgainstPublicKey(message, signature, publicKey) + ) { throw new UnauthorizedException(INVALID_SIGNATURE); } } - verifySignatureAgainstPublicKey( + verifyEcdsaSignatureAgainstPublicKey( message: string, signature: string, senderPublicKey: string, @@ -63,6 +67,40 @@ export class AuthAgent { return isValid; } + async verifyEddsaSignatureAgainstPublicKey( + message: string, + signature: string, + senderPublicKey: string, + ): Promise { + const eddsa = await buildEddsa(); + const babyJub = await buildBabyjub(); + + const hashedPayload = crypto + .createHash(`${process.env.MERKLE_TREE_HASH_ALGH}`) + .update(JSON.stringify(message)) + .digest(); + + const publicKey = Uint8Array.from(Buffer.from(signature, 'hex')); + const publicKeyPoints = babyJub.unpackPoint(publicKey); + + const eddsaSignature = Uint8Array.from(Buffer.from(signature, 'hex')); + const unpackedSignature = eddsa.unpackSignature(eddsaSignature); + + const isValid = eddsa.verifyPedersen( + hashedPayload, + unpackedSignature, + publicKeyPoints, + ); + + if (!isValid) { + this.logger.logWarn( + `Signature: ${signature} for public key ${senderPublicKey} is invalid.`, + ); + } + + return isValid; + } + async getBpiSubjectByPublicKey(publicKey: string) { return this.bpiSubjectStorageAgent.getBpiSubjectByPublicKey(publicKey); } diff --git a/examples/bri-3/src/bri/communication/api/messages.controller.spec.ts b/examples/bri-3/src/bri/communication/api/messages.controller.spec.ts index 36ee0fc6b..51ea67862 100644 --- a/examples/bri-3/src/bri/communication/api/messages.controller.spec.ts +++ b/examples/bri-3/src/bri/communication/api/messages.controller.spec.ts @@ -36,6 +36,10 @@ import { MessageController } from './messages.controller'; import { mockDeep, DeepMockProxy } from 'jest-mock-extended'; import { PrismaService } from '../../../shared/prisma/prisma.service'; import { PrismaClient } from '@prisma/client'; +import { + PublicKey, + PublicKeyType, +} from '../../identity/bpiSubjects/models/publicKey'; describe('MessageController', () => { let mController: MessageController; @@ -56,14 +60,29 @@ describe('MessageController', () => { '', 'name', 'desc', - '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', + [ + new PublicKey( + '123', + PublicKeyType.ECDSA, + '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', + '', + ), + ], + [], ); existingBpiSubject2 = new BpiSubject( '', 'name2', 'desc2', - '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + [ + new PublicKey( + '123', + PublicKeyType.ECDSA, + '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + '', + ), + ], [], ); diff --git a/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts b/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts index ee60079bb..a393f429e 100644 --- a/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts +++ b/examples/bri-3/src/bri/communication/capabilities/processInboundMessage/processInboundMessageCommand.handler.ts @@ -31,11 +31,12 @@ export class ProcessInboundMessageCommandHandler return false; } - const isSignatureValid = this.authAgent.verifySignatureAgainstPublicKey( - command.content, - command.signature, - fromBpiSubject.publicKeys[0].value, - ); + const isSignatureValid = + this.authAgent.verifyEcdsaSignatureAgainstPublicKey( + command.content, + command.signature, + fromBpiSubject.publicKeys[0].value, + ); if (!isSignatureValid) { return false; diff --git a/examples/bri-3/src/bri/identity/bpiSubjectAccounts/api/subjectAccounts.controller.spec.ts b/examples/bri-3/src/bri/identity/bpiSubjectAccounts/api/subjectAccounts.controller.spec.ts index 7efdb1b02..22d2695df 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjectAccounts/api/subjectAccounts.controller.spec.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjectAccounts/api/subjectAccounts.controller.spec.ts @@ -22,6 +22,7 @@ import { SubjectsProfile } from '../../bpiSubjects/subjects.profile'; import { mockDeep, DeepMockProxy } from 'jest-mock-extended'; import { BpiSubjectAccount } from '../models/bpiSubjectAccount'; import { uuid } from 'uuidv4'; +import { PublicKey, PublicKeyType } from '../../bpiSubjects/models/publicKey'; describe('SubjectAccountController', () => { let subjectAccountController: SubjectAccountController; @@ -70,14 +71,14 @@ describe('SubjectAccountController', () => { '123', 'owner', 'desc', - 'publicKey', + [new PublicKey('223', PublicKeyType.ECDSA, 'publicKey', '123')], [], ); const creatorBpiSubject = new BpiSubject( '321', 'creator', 'desc', - 'publicKey', + [new PublicKey('223', PublicKeyType.ECDSA, 'publicKey', '321')], [], ); @@ -195,7 +196,7 @@ describe('SubjectAccountController', () => { '123', 'owner', 'desc', - 'publicKey', + [new PublicKey('223', PublicKeyType.ECDSA, 'publicKey', '123')], [], ); const creatorBpiSubjectId = 'not-existing-id'; @@ -219,7 +220,7 @@ describe('SubjectAccountController', () => { '123', 'creator', 'desc', - 'publicKey', + [new PublicKey('223', PublicKeyType.ECDSA, 'publicKey', '123')], [], ); const ownerBpiSubjectId = 'not-existing-id'; diff --git a/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts b/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts index 89ec6e4ca..05f31b32d 100644 --- a/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts +++ b/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts @@ -15,6 +15,7 @@ import { Workstep, BpiAccount, PrismaClient, + PublicKeyType, } from '../../../../__mocks__/@prisma/client'; import { Test, TestingModule } from '@nestjs/testing'; import { SnarkjsCircuitService } from '../../zeroKnowledgeProof/services/circuit/snarkjs/snarkjs.service'; @@ -28,6 +29,7 @@ import { NOT_FOUND_ERR_MESSAGE as WORKFLOW_NOT_FOUND_ERR_MESSAGE } from '../../w import { AuthModule } from '../../../bri/auth/auth.module'; import { AutomapperModule } from '@automapper/nestjs'; import { classes } from '@automapper/classes'; +import { uuid } from 'uuidv4'; let agent: TransactionAgent; let authAgent: AuthAgent; @@ -76,8 +78,25 @@ beforeEach(async () => { data: { name: 'name', description: 'desc', - publicKey: - '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', + publicKeys: { + createMany: { + data: [ + { + type: PublicKeyType.ECDSA, + value: + '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', + }, + { + type: PublicKeyType.EDDSA, + value: + '0x047a197a795a747c154dd92b217a048d315ef9ca1bfa9c15bfefe4e02fb338a70af23e7683b565a8dece5104a85ed24a50d791d8c5cb09ee21aabc927c98516539', + }, + ], + }, + }, + }, + include: { + publicKeys: true, }, }); @@ -85,8 +104,23 @@ beforeEach(async () => { data: { name: 'name2', description: 'desc2', - publicKey: - '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + publicKeys: { + create: [ + { + type: PublicKeyType.ECDSA, + value: + '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + }, + { + type: PublicKeyType.EDDSA, + value: + '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + }, + ], + }, + }, + include: { + publicKeys: true, }, }); @@ -100,7 +134,11 @@ beforeEach(async () => { recoveryKey: '', }, include: { - ownerBpiSubject: true, + ownerBpiSubject: { + include: { + publicKeys: true, + }, + }, }, }); bpiSubjectAccount2 = await prisma.bpiSubjectAccount.create({ @@ -113,7 +151,11 @@ beforeEach(async () => { recoveryKey: '', }, include: { - ownerBpiSubject: true, + ownerBpiSubject: { + include: { + publicKeys: true, + }, + }, }, }); bpiAccount1 = await prisma.bpiAccount.create({ @@ -246,8 +288,8 @@ describe('Transaction Agent', () => { it('Should return false when validateTransactionForExecution invoked with tx with wrong signature', async () => { // Arrange jest - .spyOn(authAgent, 'verifySignatureAgainstPublicKey') - .mockImplementationOnce(() => false); + .spyOn(authAgent, 'verifyEddsaSignatureAgainstPublicKey') + .mockImplementationOnce(async () => false); const tx = new Transaction( '1', 1, @@ -270,8 +312,8 @@ describe('Transaction Agent', () => { it('Should return false when validateTransactionForExecution invoked with tx with status not processing', async () => { // Arrange jest - .spyOn(authAgent, 'verifySignatureAgainstPublicKey') - .mockImplementationOnce(() => true); + .spyOn(authAgent, 'verifyEddsaSignatureAgainstPublicKey') + .mockImplementationOnce(async () => true); const tx = new Transaction( '1', 1, @@ -294,8 +336,8 @@ describe('Transaction Agent', () => { it('Should return false when validateTransactionForExecution invoked with tx with nonce not bpi account nonce + 1', async () => { // Arrange jest - .spyOn(authAgent, 'verifySignatureAgainstPublicKey') - .mockImplementationOnce(() => true); + .spyOn(authAgent, 'verifyEddsaSignatureAgainstPublicKey') + .mockImplementationOnce(async () => true); const tx = new Transaction( '1', 2, @@ -318,8 +360,8 @@ describe('Transaction Agent', () => { it('Should return true when validateTransactionForExecution invoked with tx with all properties correctly set', async () => { // Arrange jest - .spyOn(authAgent, 'verifySignatureAgainstPublicKey') - .mockImplementationOnce(() => true); + .spyOn(authAgent, 'verifyEddsaSignatureAgainstPublicKey') + .mockImplementationOnce(async () => true); const tx = new Transaction( '1', 1, diff --git a/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts b/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts index f9d1e3baa..2dd23d42d 100644 --- a/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts +++ b/examples/bri-3/src/bri/transactions/agents/transactions.agent.ts @@ -7,8 +7,6 @@ import { import { Transaction } from '../models/transaction'; import { TransactionStatus } from '../models/transactionStatus.enum'; -import MerkleTree from 'merkletreejs'; -import { Witness } from 'src/bri/zeroKnowledgeProof/models/witness'; import { AuthAgent } from '../../auth/agent/auth.agent'; import { BpiSubjectAccount } from '../../identity/bpiSubjectAccounts/models/bpiSubjectAccount'; import { MerkleTreeService } from '../../merkleTree/services/merkleTree.service'; @@ -23,6 +21,7 @@ import { } from '../api/err.messages'; import { TransactionStorageAgent } from './transactionStorage.agent'; import { TransactionResult } from '../models/transactionResult'; +import { PublicKeyType } from '../../identity/bpiSubjects/models/publicKey'; @Injectable() export class TransactionAgent { @@ -154,11 +153,14 @@ export class TransactionAgent { return false; } - const isSignatureValid = this.authAgent.verifySignatureAgainstPublicKey( - tx.payload, - tx.signature, - tx.fromBpiSubjectAccount.ownerBpiSubject.publicKeys[0].value, - ); + const isSignatureValid = + await this.authAgent.verifyEddsaSignatureAgainstPublicKey( + tx.payload, + tx.signature, + tx.fromBpiSubjectAccount.ownerBpiSubject.publicKeys.filter( + (key) => key.type == PublicKeyType.EDDSA, + )[0].value, + ); if (!isSignatureValid) { return false; diff --git a/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts b/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts index 701e5d321..9e9d790c8 100644 --- a/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts +++ b/examples/bri-3/src/bri/transactions/api/transactions.controller.spec.ts @@ -29,6 +29,10 @@ import { UpdateTransactionDto } from './dtos/request/updateTransaction.dto'; import { NOT_FOUND_ERR_MESSAGE } from './err.messages'; import { TransactionController } from './transactions.controller'; import { MerkleTreeService } from '../../merkleTree/services/merkleTree.service'; +import { + PublicKey, + PublicKeyType, +} from '../../identity/bpiSubjects/models/publicKey'; describe('TransactionController', () => { let controller: TransactionController; @@ -40,14 +44,14 @@ describe('TransactionController', () => { '123', 'owner', 'desc', - 'publicKey', + [new PublicKey('222', PublicKeyType.ECDSA, 'publicKey', '123')], [], ); const creatorBpiSubject = new BpiSubject( '321', 'creator', 'desc', - 'publicKey', + [new PublicKey('223', PublicKeyType.ECDSA, 'publicKey', '321')], [], ); diff --git a/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts b/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts index ab09094ab..0c5e64c70 100644 --- a/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts +++ b/examples/bri-3/src/bri/transactions/capabilities/processInboundTransaction/processInboundTransactionCommand.handler.ts @@ -34,11 +34,12 @@ export class ProcessInboundTransactionCommandHandler return false; } - const isSignatureValid = this.authAgent.verifySignatureAgainstPublicKey( - command.payload, - command.signature, - subjectAccounts[0].ownerBpiSubject.publicKeys[0].value, - ); + const isSignatureValid = + this.authAgent.verifyEcdsaSignatureAgainstPublicKey( + command.payload, + command.signature, + subjectAccounts[0].ownerBpiSubject.publicKeys[0].value, + ); if (!isSignatureValid) { return false; diff --git a/examples/bri-3/src/bri/workgroup/workgroups/api/workgroups.controller.spec.ts b/examples/bri-3/src/bri/workgroup/workgroups/api/workgroups.controller.spec.ts index 7089bd0b4..c02f80302 100644 --- a/examples/bri-3/src/bri/workgroup/workgroups/api/workgroups.controller.spec.ts +++ b/examples/bri-3/src/bri/workgroup/workgroups/api/workgroups.controller.spec.ts @@ -28,6 +28,10 @@ import { uuid } from 'uuidv4'; import { WorkgroupProfile } from '../workgroups.profile'; import { PrismaService } from '../../../../shared/prisma/prisma.service'; import { PrismaClient } from '@prisma/client'; +import { + PublicKey, + PublicKeyType, +} from '../../../identity/bpiSubjects/models/publicKey'; describe('WorkgroupsController', () => { let workgroupController: WorkgroupController; @@ -35,7 +39,13 @@ describe('WorkgroupsController', () => { let subjectStorageAgentMock: DeepMockProxy; const createTestBpiSubject = () => { - return new BpiSubject('123', 'name', 'desc', 'pubkey', []); + return new BpiSubject( + '123', + 'name', + 'desc', + [new PublicKey('223', PublicKeyType.ECDSA, 'publicKey', '123')], + [], + ); }; const createTestWorkgroup = (): Workgroup => { From e7b9532c6f0c9a885aab4cb4611960581f2aa8e1 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 20:36:04 +0530 Subject: [PATCH 25/29] Change updateMany to upsert in BpiSubjectStorage agent --- .../identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts index cf2c491d7..ec859332d 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts @@ -128,9 +128,10 @@ export class BpiSubjectStorageAgent extends PrismaService { }), }, publicKeys: { - updateMany: bpiSubject.publicKeys.map((pk) => ({ + upsert: bpiSubject.publicKeys.map((pk) => ({ where: { id: pk.id }, - data: { value: pk.value }, + create: { type: pk.type, value: pk.value }, + update: { value: pk.value }, })), }, }, From ed13e539925ecd7149b6bfec4e3d066de4ef3e11 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 23:41:41 +0530 Subject: [PATCH 26/29] Bug fix in updateBpiSubject --- .../bpiSubjects/agents/bpiSubjectsStorage.agent.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts index ec859332d..96cd88d8d 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts @@ -128,11 +128,11 @@ export class BpiSubjectStorageAgent extends PrismaService { }), }, publicKeys: { - upsert: bpiSubject.publicKeys.map((pk) => ({ - where: { id: pk.id }, - create: { type: pk.type, value: pk.value }, - update: { value: pk.value }, - })), + connect: bpiSubject.publicKeys.map((pk) => { + return { + id: pk.id, + }; + }), }, }, }); From 1bffe235663f738585fc12e3befc0ecedcaa0c83 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Mon, 15 Apr 2024 23:45:38 +0530 Subject: [PATCH 27/29] Update bpiSubject publicKeys --- .../bpiSubjects/agents/bpiSubjectsStorage.agent.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts index 96cd88d8d..ec859332d 100644 --- a/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts +++ b/examples/bri-3/src/bri/identity/bpiSubjects/agents/bpiSubjectsStorage.agent.ts @@ -128,11 +128,11 @@ export class BpiSubjectStorageAgent extends PrismaService { }), }, publicKeys: { - connect: bpiSubject.publicKeys.map((pk) => { - return { - id: pk.id, - }; - }), + upsert: bpiSubject.publicKeys.map((pk) => ({ + where: { id: pk.id }, + create: { type: pk.type, value: pk.value }, + update: { value: pk.value }, + })), }, }, }); From c28e1791289cde320bfe8129010e4d772dfc1121 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Wed, 17 Apr 2024 14:29:01 +0530 Subject: [PATCH 28/29] Remove unnecessary imports --- .../bri/state/bpiAccounts/api/accounts.controller.spec.ts | 5 +---- examples/bri-3/src/shared/testing/builders.ts | 5 ----- examples/bri-3/src/shared/testing/testData.helper.ts | 4 ---- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts b/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts index 4643d0568..4a6cba6a2 100644 --- a/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts +++ b/examples/bri-3/src/bri/state/bpiAccounts/api/accounts.controller.spec.ts @@ -37,10 +37,7 @@ import { CreateBpiAccountDto } from './dtos/request/createBpiAccount.dto'; import { NOT_FOUND_ERR_MESSAGE } from './err.messages'; import { PrismaService } from '../../../../shared/prisma/prisma.service'; import { PrismaClient } from '@prisma/client'; -import { - PublicKey, - PublicKeyType, -} from '../../../identity/bpiSubjects/models/publicKey'; + describe('AccountController', () => { let accountController: AccountController; let accountStorageAgentMock: DeepMockProxy; diff --git a/examples/bri-3/src/shared/testing/builders.ts b/examples/bri-3/src/shared/testing/builders.ts index 866b461d3..0d16f1e84 100644 --- a/examples/bri-3/src/shared/testing/builders.ts +++ b/examples/bri-3/src/shared/testing/builders.ts @@ -9,7 +9,6 @@ import { BpiMerkleTree } from '../../bri/merkleTree/models/bpiMerkleTree'; import { Workflow } from '../../bri/workgroup/workflows/models/workflow'; import { Workgroup } from '../../bri/workgroup/workgroups/models/workgroup'; import { Workstep } from '../../bri/workgroup/worksteps/models/workstep'; -import { PublicKey } from '../../bri/identity/bpiSubjects/models/publicKey'; export class WorkstepBuilder { private id: string; @@ -123,11 +122,7 @@ export class BpiSubjectBuilder { private id: string; private name: string; private description: string; -<<<<<<< HEAD private publicKeys: PublicKey[]; -======= - private publicKey: PublicKey[]; ->>>>>>> feature/759-public-key-test-pass-2 private loginNonce: string; private roles: BpiSubjectRole[]; diff --git a/examples/bri-3/src/shared/testing/testData.helper.ts b/examples/bri-3/src/shared/testing/testData.helper.ts index e9f0f75de..c2fca69de 100644 --- a/examples/bri-3/src/shared/testing/testData.helper.ts +++ b/examples/bri-3/src/shared/testing/testData.helper.ts @@ -6,10 +6,6 @@ import { BpiSubjectRole, BpiSubjectRoleName, } from '../../bri/identity/bpiSubjects/models/bpiSubjectRole'; -import { - PublicKey, - PublicKeyType, -} from '../../bri/identity/bpiSubjects/models/publicKey'; import { Workflow } from '../../bri/workgroup/workflows/models/workflow'; import { Workstep } from '../../bri/workgroup/worksteps/models/workstep'; import { From d6a786c8d23cd3c2549fdfa338979ccd8c6879f1 Mon Sep 17 00:00:00 2001 From: biscuitdey Date: Wed, 17 Apr 2024 14:33:21 +0530 Subject: [PATCH 29/29] Change create to createMany --- .../agents/transactions.agent.spec.ts | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts b/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts index 05f31b32d..8565f199f 100644 --- a/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts +++ b/examples/bri-3/src/bri/transactions/agents/transactions.agent.spec.ts @@ -105,18 +105,20 @@ beforeEach(async () => { name: 'name2', description: 'desc2', publicKeys: { - create: [ - { - type: PublicKeyType.ECDSA, - value: - '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', - }, - { - type: PublicKeyType.EDDSA, - value: - '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', - }, - ], + createMany: { + data: [ + { + type: PublicKeyType.ECDSA, + value: + '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + }, + { + type: PublicKeyType.EDDSA, + value: + '0x04203db7d27bab8d711acc52479efcfa9d7846e4e176d82389689f95cf06a51818b0b9ab1c2c8d72f1a32e236e6296c91c922a0dc3d0cb9afc269834fc5646b980', + }, + ], + }, }, }, include: {