From 66795742a01d5390ad083610efd28a8fe59fb3a3 Mon Sep 17 00:00:00 2001 From: Cody Hatfield Date: Fri, 16 Dec 2022 17:28:56 -0800 Subject: [PATCH] feat(did-comm): support DIDComm Messaging attachments (#1087) fixes #612 --- packages/core/plugin.schema.json | 180 ++++++++++++++++++ packages/core/src/types/IMessage.ts | 34 ++++ packages/did-comm/plugin.schema.json | 121 +++++++++++- .../src/__tests__/message-handler.test.ts | 10 +- packages/did-comm/src/message-handler.ts | 2 + packages/did-comm/src/types/message-types.ts | 32 ++++ packages/message-handler/src/message.ts | 9 +- 7 files changed, 385 insertions(+), 3 deletions(-) diff --git a/packages/core/plugin.schema.json b/packages/core/plugin.schema.json index f33bd89e6..967895137 100644 --- a/packages/core/plugin.schema.json +++ b/packages/core/plugin.schema.json @@ -2032,6 +2032,13 @@ "$ref": "#/components/schemas/VerifiablePresentation" }, "description": "Optional. Array of attached verifiable presentations" + }, + "attachments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IMessageAttachment" + }, + "description": "Optional. Array of generic attachments" } }, "required": [ @@ -2249,6 +2256,59 @@ "type": "string", "description": "Represents a Json Web Token in compact form. \"header.payload.signature\"" }, + "IMessageAttachment": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "description": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "media_type": { + "type": "string" + }, + "format": { + "type": "string" + }, + "lastmod_time": { + "type": "string" + }, + "byte_count": { + "type": "number" + }, + "data": { + "$ref": "#/components/schemas/IMessageAttachmentData" + } + }, + "required": [ + "data" + ], + "description": "Message attachment" + }, + "IMessageAttachmentData": { + "type": "object", + "properties": { + "jws": {}, + "hash": { + "type": "string" + }, + "links": { + "type": "array", + "items": { + "type": "string" + } + }, + "base64": { + "type": "string" + }, + "json": {} + }, + "description": "The DIDComm message structure for data in an attachment. See https://identity.foundation/didcomm-messaging/spec/#attachments" + }, "IDataStoreGetVerifiableCredentialArgs": { "type": "object", "properties": { @@ -2822,6 +2882,13 @@ "$ref": "#/components/schemas/VerifiablePresentation" }, "description": "Optional. Array of attached verifiable presentations" + }, + "attachments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IMessageAttachment" + }, + "description": "Optional. Array of generic attachments" } }, "required": [ @@ -3039,6 +3106,59 @@ "type": "string", "description": "Represents a Json Web Token in compact form. \"header.payload.signature\"" }, + "IMessageAttachment": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "description": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "media_type": { + "type": "string" + }, + "format": { + "type": "string" + }, + "lastmod_time": { + "type": "string" + }, + "byte_count": { + "type": "number" + }, + "data": { + "$ref": "#/components/schemas/IMessageAttachmentData" + } + }, + "required": [ + "data" + ], + "description": "Message attachment" + }, + "IMessageAttachmentData": { + "type": "object", + "properties": { + "jws": {}, + "hash": { + "type": "string" + }, + "links": { + "type": "array", + "items": { + "type": "string" + } + }, + "base64": { + "type": "string" + }, + "json": {} + }, + "description": "The DIDComm message structure for data in an attachment. See https://identity.foundation/didcomm-messaging/spec/#attachments" + }, "FindCredentialsArgs": { "$ref": "#/components/schemas/FindArgs-TCredentialColumns", "description": "The filter that can be used to find {@link VerifiableCredential } s in the data store. See {@link IDataStoreORM.dataStoreORMGetVerifiableCredentials }" @@ -3616,6 +3736,13 @@ "$ref": "#/components/schemas/VerifiablePresentation" }, "description": "Optional. Array of attached verifiable presentations" + }, + "attachments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IMessageAttachment" + }, + "description": "Optional. Array of generic attachments" } }, "required": [ @@ -3815,6 +3942,59 @@ "CompactJWT": { "type": "string", "description": "Represents a Json Web Token in compact form. \"header.payload.signature\"" + }, + "IMessageAttachment": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "description": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "media_type": { + "type": "string" + }, + "format": { + "type": "string" + }, + "lastmod_time": { + "type": "string" + }, + "byte_count": { + "type": "number" + }, + "data": { + "$ref": "#/components/schemas/IMessageAttachmentData" + } + }, + "required": [ + "data" + ], + "description": "Message attachment" + }, + "IMessageAttachmentData": { + "type": "object", + "properties": { + "jws": {}, + "hash": { + "type": "string" + }, + "links": { + "type": "array", + "items": { + "type": "string" + } + }, + "base64": { + "type": "string" + }, + "json": {} + }, + "description": "The DIDComm message structure for data in an attachment. See https://identity.foundation/didcomm-messaging/spec/#attachments" } }, "methods": { diff --git a/packages/core/src/types/IMessage.ts b/packages/core/src/types/IMessage.ts index c01bacb4d..eef67f317 100644 --- a/packages/core/src/types/IMessage.ts +++ b/packages/core/src/types/IMessage.ts @@ -16,6 +16,35 @@ export interface IMetaData { value?: string } +/** + * Message attachment + * @public + */ +export interface IMessageAttachment { + id?: string + description?: string + filename?: string + media_type?: string + format?: string + lastmod_time?: string + byte_count?: number + data: IMessageAttachmentData +} + +/** + * The DIDComm message structure for data in an attachment. + * See https://identity.foundation/didcomm-messaging/spec/#attachments + * + * @beta This API may change without a BREAKING CHANGE notice. + */ +export interface IMessageAttachmentData { + jws?: any + hash?: string + links?: string[] + base64?: string + json?: any +} + /** * Represents a DIDComm v1 message payload, with optionally decoded credentials and presentations. * @public @@ -90,4 +119,9 @@ export interface IMessage { * Optional. Array of attached verifiable presentations */ presentations?: VerifiablePresentation[] + + /** + * Optional. Array of generic attachments + */ + attachments?: IMessageAttachment[] } diff --git a/packages/did-comm/plugin.schema.json b/packages/did-comm/plugin.schema.json index a75f239db..107af9a6f 100644 --- a/packages/did-comm/plugin.schema.json +++ b/packages/did-comm/plugin.schema.json @@ -78,7 +78,13 @@ "from_prior": { "type": "string" }, - "body": {} + "body": {}, + "attachments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IDIDCommMessageAttachment" + } + } }, "required": [ "type", @@ -88,6 +94,59 @@ ], "description": "The DIDComm message structure. See https://identity.foundation/didcomm-messaging/spec/#plaintext-message-structure" }, + "IDIDCommMessageAttachment": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "description": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "media_type": { + "type": "string" + }, + "format": { + "type": "string" + }, + "lastmod_time": { + "type": "string" + }, + "byte_count": { + "type": "number" + }, + "data": { + "$ref": "#/components/schemas/IDIDCommMessageAttachmentData" + } + }, + "required": [ + "data" + ], + "description": "The DIDComm message structure for attachments. See https://identity.foundation/didcomm-messaging/spec/#attachments" + }, + "IDIDCommMessageAttachmentData": { + "type": "object", + "properties": { + "jws": {}, + "hash": { + "type": "string" + }, + "links": { + "type": "array", + "items": { + "type": "string" + } + }, + "base64": { + "type": "string" + }, + "json": {} + }, + "description": "The DIDComm message structure for data in an attachment. See https://identity.foundation/didcomm-messaging/spec/#attachments" + }, "DIDCommMessagePacking": { "type": "string", "enum": [ @@ -274,6 +333,13 @@ "$ref": "#/components/schemas/VerifiablePresentation" }, "description": "Optional. Array of attached verifiable presentations" + }, + "attachments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IMessageAttachment" + }, + "description": "Optional. Array of generic attachments" } }, "required": [ @@ -491,6 +557,59 @@ "type": "string", "description": "Represents a Json Web Token in compact form. \"header.payload.signature\"" }, + "IMessageAttachment": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "description": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "media_type": { + "type": "string" + }, + "format": { + "type": "string" + }, + "lastmod_time": { + "type": "string" + }, + "byte_count": { + "type": "number" + }, + "data": { + "$ref": "#/components/schemas/IMessageAttachmentData" + } + }, + "required": [ + "data" + ], + "description": "Message attachment" + }, + "IMessageAttachmentData": { + "type": "object", + "properties": { + "jws": {}, + "hash": { + "type": "string" + }, + "links": { + "type": "array", + "items": { + "type": "string" + } + }, + "base64": { + "type": "string" + }, + "json": {} + }, + "description": "The DIDComm message structure for data in an attachment. See https://identity.foundation/didcomm-messaging/spec/#attachments" + }, "IUnpackDIDCommMessageArgs": { "$ref": "#/components/schemas/IPackedDIDCommMessage", "description": "The input to the {@link DIDComm.unpackDIDCommMessage } method." diff --git a/packages/did-comm/src/__tests__/message-handler.test.ts b/packages/did-comm/src/__tests__/message-handler.test.ts index d148d3e01..7af616f61 100644 --- a/packages/did-comm/src/__tests__/message-handler.test.ts +++ b/packages/did-comm/src/__tests__/message-handler.test.ts @@ -184,6 +184,7 @@ describe('did-comm-message-handler', () => { body: { hello: 'world' }, + attachments: [{ data: { hash: 'some-hash', json: { some: 'attachment' } } }], from: sender.did, id: `${id}`, to: recipient.did, @@ -198,7 +199,14 @@ describe('did-comm-message-handler', () => { } const getRegularMessage = () => { - return { id: v4(), type: 'fake', to: recipient.did, from: sender.did, body: { hello: 'world' }} + return { + id: v4(), + type: 'fake', + to: recipient.did, + from: sender.did, + body: { hello: 'world' }, + attachments: [{ data: { hash: 'some-hash', json: { some: 'attachment' } } }], + } } it('should pack and unpack message with none packing', async () => { diff --git a/packages/did-comm/src/message-handler.ts b/packages/did-comm/src/message-handler.ts index a6a981856..afbdaa043 100644 --- a/packages/did-comm/src/message-handler.ts +++ b/packages/did-comm/src/message-handler.ts @@ -107,6 +107,7 @@ export class DIDCommMessageHandler extends AbstractMessageHandler { created_time: createdAt, expires_time: expiresAt, body: data, + attachments, } = unpackedMessage.message message.type = type @@ -117,6 +118,7 @@ export class DIDCommMessageHandler extends AbstractMessageHandler { message.createdAt = createdAt message.expiresAt = expiresAt message.data = data + message.attachments = attachments message.addMetaData({ type: 'didCommMetaData', value: JSON.stringify(unpackedMessage.metaData) }) context.agent.emit('DIDCommV2Message-received', unpackedMessage) diff --git a/packages/did-comm/src/types/message-types.ts b/packages/did-comm/src/types/message-types.ts index 81d8ef645..d840f4a98 100644 --- a/packages/did-comm/src/types/message-types.ts +++ b/packages/did-comm/src/types/message-types.ts @@ -16,6 +16,7 @@ export interface IDIDCommMessage { next?: string from_prior?: string body: any + attachments?: IDIDCommMessageAttachment[] } /** @@ -101,3 +102,34 @@ export interface IUnpackedDIDCommMessage { export interface IPackedDIDCommMessage { message: string } + +/** + * The DIDComm message structure for attachments. + * See https://identity.foundation/didcomm-messaging/spec/#attachments + * + * @beta This API may change without a BREAKING CHANGE notice. + */ +export interface IDIDCommMessageAttachment { + id?: string + description?: string + filename?: string + media_type?: string + format?: string + lastmod_time?: string + byte_count?: number + data: IDIDCommMessageAttachmentData +} + +/** + * The DIDComm message structure for data in an attachment. + * See https://identity.foundation/didcomm-messaging/spec/#attachments + * + * @beta This API may change without a BREAKING CHANGE notice. + */ +export interface IDIDCommMessageAttachmentData { + jws?: any + hash?: string + links?: string[] + base64?: string + json?: any +} diff --git a/packages/message-handler/src/message.ts b/packages/message-handler/src/message.ts index 37dc47044..43f60da6c 100644 --- a/packages/message-handler/src/message.ts +++ b/packages/message-handler/src/message.ts @@ -1,4 +1,10 @@ -import { IMessage, IMetaData, VerifiableCredential, VerifiablePresentation } from '@veramo/core' +import { + IMessage, + IMetaData, + IMessageAttachment, + VerifiableCredential, + VerifiablePresentation, +} from '@veramo/core' /** * A class implementing {@link @veramo/core#IMessage | IMessage}. @@ -45,6 +51,7 @@ export class Message implements IMessage { presentations?: VerifiablePresentation[] credentials?: VerifiableCredential[] + attachments?: IMessageAttachment[] addMetaData(meta: IMetaData) { if (this.metaData) {