Skip to content

Commit cf69a54

Browse files
authored
refactor(core): separate logic for inbound plaintext and encrypted message (openwallet-foundation#581)
* rename wire message to encrypted message Signed-off-by: Jakub Koci <[email protected]>
1 parent 3dadfc7 commit cf69a54

23 files changed

+159
-155
lines changed

Diff for: packages/core/src/agent/Agent.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ export class Agent {
204204
return this.wallet.publicDid
205205
}
206206

207-
public async receiveMessage(inboundPackedMessage: unknown, session?: TransportSession) {
208-
return await this.messageReceiver.receiveMessage(inboundPackedMessage, session)
207+
public async receiveMessage(inboundMessage: unknown, session?: TransportSession) {
208+
return await this.messageReceiver.receiveMessage(inboundMessage, session)
209209
}
210210

211211
public get injectionContainer() {

Diff for: packages/core/src/agent/EnvelopeService.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Logger } from '../logger'
2-
import type { UnpackedMessageContext, WireMessage } from '../types'
2+
import type { DecryptedMessageContext, EncryptedMessage } from '../types'
33
import type { AgentMessage } from './AgentMessage'
44

55
import { inject, scoped, Lifecycle } from 'tsyringe'
@@ -28,7 +28,7 @@ class EnvelopeService {
2828
this.config = agentConfig
2929
}
3030

31-
public async packMessage(payload: AgentMessage, keys: EnvelopeKeys): Promise<WireMessage> {
31+
public async packMessage(payload: AgentMessage, keys: EnvelopeKeys): Promise<EncryptedMessage> {
3232
const { routingKeys, senderKey } = keys
3333
let recipientKeys = keys.recipientKeys
3434

@@ -37,29 +37,29 @@ class EnvelopeService {
3737

3838
this.logger.debug(`Pack outbound message ${message['@type']}`)
3939

40-
let wireMessage = await this.wallet.pack(message, recipientKeys, senderKey ?? undefined)
40+
let encryptedMessage = await this.wallet.pack(message, recipientKeys, senderKey ?? undefined)
4141

4242
// If the message has routing keys (mediator) pack for each mediator
4343
for (const routingKey of routingKeys) {
4444
const forwardMessage = new ForwardMessage({
4545
// Forward to first recipient key
4646
to: recipientKeys[0],
47-
message: wireMessage,
47+
message: encryptedMessage,
4848
})
4949
recipientKeys = [routingKey]
5050
this.logger.debug('Forward message created', forwardMessage)
5151

5252
const forwardJson = forwardMessage.toJSON({ useLegacyDidSovPrefix: this.config.useLegacyDidSovPrefix })
5353

5454
// Forward messages are anon packed
55-
wireMessage = await this.wallet.pack(forwardJson, [routingKey], undefined)
55+
encryptedMessage = await this.wallet.pack(forwardJson, [routingKey], undefined)
5656
}
5757

58-
return wireMessage
58+
return encryptedMessage
5959
}
6060

61-
public async unpackMessage(packedMessage: WireMessage): Promise<UnpackedMessageContext> {
62-
return this.wallet.unpack(packedMessage)
61+
public async unpackMessage(encryptedMessage: EncryptedMessage): Promise<DecryptedMessageContext> {
62+
return this.wallet.unpack(encryptedMessage)
6363
}
6464
}
6565

Diff for: packages/core/src/agent/MessageReceiver.ts

+70-65
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Logger } from '../logger'
22
import type { ConnectionRecord } from '../modules/connections'
33
import type { InboundTransport } from '../transport'
4-
import type { UnpackedMessageContext, UnpackedMessage, WireMessage } from '../types'
4+
import type { DecryptedMessageContext, PlaintextMessage, EncryptedMessage } from '../types'
55
import type { AgentMessage } from './AgentMessage'
66
import type { TransportSession } from './TransportService'
77

@@ -59,21 +59,29 @@ export class MessageReceiver {
5959
}
6060

6161
/**
62-
* Receive and handle an inbound DIDComm message. It will unpack the message, transform it
62+
* Receive and handle an inbound DIDComm message. It will decrypt the message, transform it
6363
* to it's corresponding message class and finally dispatch it to the dispatcher.
6464
*
65-
* @param inboundPackedMessage the message to receive and handle
65+
* @param inboundMessage the message to receive and handle
6666
*/
67-
public async receiveMessage(inboundPackedMessage: unknown, session?: TransportSession) {
68-
if (typeof inboundPackedMessage !== 'object' || inboundPackedMessage == null) {
69-
throw new AriesFrameworkError('Invalid message received. Message should be object')
67+
public async receiveMessage(inboundMessage: unknown, session?: TransportSession) {
68+
this.logger.debug(`Agent ${this.config.label} received message`)
69+
70+
if (this.isPlaintextMessage(inboundMessage)) {
71+
await this.receivePlaintextMessage(inboundMessage)
72+
} else {
73+
await this.receiveEncryptedMessage(inboundMessage as EncryptedMessage, session)
7074
}
75+
}
7176

72-
this.logger.debug(`Agent ${this.config.label} received message`)
77+
private async receivePlaintextMessage(plaintextMessage: PlaintextMessage) {
78+
const message = await this.transformAndValidate(plaintextMessage)
79+
const messageContext = new InboundMessageContext(message, {})
80+
await this.dispatcher.dispatch(messageContext)
81+
}
7382

74-
const unpackedMessage = await this.unpackMessage(inboundPackedMessage as WireMessage)
75-
const senderKey = unpackedMessage.senderVerkey
76-
const recipientKey = unpackedMessage.recipientVerkey
83+
private async receiveEncryptedMessage(encryptedMessage: EncryptedMessage, session?: TransportSession) {
84+
const { plaintextMessage, senderKey, recipientKey } = await this.decryptMessage(encryptedMessage)
7785

7886
let connection: ConnectionRecord | null = null
7987

@@ -90,27 +98,11 @@ export class MessageReceiver {
9098
}
9199

92100
this.logger.info(
93-
`Received message with type '${unpackedMessage.message['@type']}' from connection ${connection?.id} (${connection?.theirLabel})`,
94-
unpackedMessage.message
101+
`Received message with type '${plaintextMessage['@type']}' from connection ${connection?.id} (${connection?.theirLabel})`,
102+
plaintextMessage
95103
)
96104

97-
let message: AgentMessage | null = null
98-
try {
99-
message = await this.transformMessage(unpackedMessage)
100-
await this.validateMessage(message)
101-
} catch (error) {
102-
if (connection) await this.sendProblemReportMessage(error.message, connection, unpackedMessage)
103-
throw error
104-
}
105-
106-
const messageContext = new InboundMessageContext(message, {
107-
// Only make the connection available in message context if the connection is ready
108-
// To prevent unwanted usage of unready connections. Connections can still be retrieved from
109-
// Storage if the specific protocol allows an unready connection to be used.
110-
connection: connection?.isReady ? connection : undefined,
111-
senderVerkey: senderKey,
112-
recipientVerkey: recipientKey,
113-
})
105+
const message = await this.transformAndValidate(plaintextMessage, connection)
114106

115107
// We want to save a session if there is a chance of returning outbound message via inbound transport.
116108
// That can happen when inbound message has `return_route` set to `all` or `thread`.
@@ -131,53 +123,68 @@ export class MessageReceiver {
131123
this.transportService.saveSession(session)
132124
}
133125

126+
const messageContext = new InboundMessageContext(message, {
127+
// Only make the connection available in message context if the connection is ready
128+
// To prevent unwanted usage of unready connections. Connections can still be retrieved from
129+
// Storage if the specific protocol allows an unready connection to be used.
130+
connection: connection?.isReady ? connection : undefined,
131+
senderVerkey: senderKey,
132+
recipientVerkey: recipientKey,
133+
})
134134
await this.dispatcher.dispatch(messageContext)
135135
}
136136

137137
/**
138-
* Unpack a message using the envelope service.
139-
* If message is not packed, it will be returned as is, but in the unpacked message structure
138+
* Decrypt a message using the envelope service.
140139
*
141-
* @param packedMessage the received, probably packed, message to unpack
140+
* @param message the received inbound message to decrypt
142141
*/
143-
private async unpackMessage(packedMessage: WireMessage): Promise<UnpackedMessageContext> {
144-
// If the inbound message has no @type field we assume
145-
// the message is packed and must be unpacked first
146-
if (!this.isUnpackedMessage(packedMessage)) {
147-
try {
148-
return await this.envelopeService.unpackMessage(packedMessage)
149-
} catch (error) {
150-
this.logger.error('error while unpacking message', {
151-
error,
152-
packedMessage,
153-
errorMessage: error instanceof Error ? error.message : error,
154-
})
155-
throw error
156-
}
142+
private async decryptMessage(message: EncryptedMessage): Promise<DecryptedMessageContext> {
143+
try {
144+
return await this.envelopeService.unpackMessage(message)
145+
} catch (error) {
146+
this.logger.error('Error while decrypting message', {
147+
error,
148+
encryptedMessage: message,
149+
errorMessage: error instanceof Error ? error.message : error,
150+
})
151+
throw error
157152
}
153+
}
158154

159-
// If the message does have an @type field we assume
160-
// the message is already unpacked an use it directly
161-
else {
162-
const unpackedMessage: UnpackedMessageContext = { message: packedMessage }
163-
return unpackedMessage
155+
private isPlaintextMessage(message: unknown): message is PlaintextMessage {
156+
if (typeof message !== 'object' || message == null) {
157+
throw new AriesFrameworkError('Invalid message received. Message should be object')
164158
}
159+
// If the message does have an @type field we assume the message is in plaintext and it is not encrypted.
160+
return '@type' in message
165161
}
166162

167-
private isUnpackedMessage(message: Record<string, unknown>): message is UnpackedMessage {
168-
return '@type' in message
163+
private async transformAndValidate(
164+
plaintextMessage: PlaintextMessage,
165+
connection?: ConnectionRecord | null
166+
): Promise<AgentMessage> {
167+
let message: AgentMessage
168+
try {
169+
message = await this.transformMessage(plaintextMessage)
170+
await this.validateMessage(message)
171+
} catch (error) {
172+
if (connection) await this.sendProblemReportMessage(error.message, connection, plaintextMessage)
173+
throw error
174+
}
175+
return message
169176
}
170177

171178
/**
172-
* Transform an unpacked DIDComm message into it's corresponding message class. Will look at all message types in the registered handlers.
179+
* Transform an plaintext DIDComm message into it's corresponding message class. Will look at all message types in the registered handlers.
173180
*
174-
* @param unpackedMessage the unpacked message for which to transform the message in to a class instance
181+
* @param message the plaintext message for which to transform the message in to a class instance
175182
*/
176-
private async transformMessage(unpackedMessage: UnpackedMessageContext): Promise<AgentMessage> {
183+
private async transformMessage(message: PlaintextMessage): Promise<AgentMessage> {
177184
// replace did:sov:BzCbsNYhMrjHiqZDTUASHg;spec prefix for message type with https://didcomm.org
178-
replaceLegacyDidSovPrefixOnMessage(unpackedMessage.message)
185+
replaceLegacyDidSovPrefixOnMessage(message)
179186

180-
const messageType = unpackedMessage.message['@type']
187+
const messageType = message['@type']
181188
const MessageClass = this.dispatcher.getMessageClassForType(messageType)
182189

183190
if (!MessageClass) {
@@ -187,9 +194,7 @@ export class MessageReceiver {
187194
}
188195

189196
// Cast the plain JSON object to specific instance of Message extended from AgentMessage
190-
const message = JsonTransformer.fromJSON(unpackedMessage.message, MessageClass)
191-
192-
return message
197+
return JsonTransformer.fromJSON(message, MessageClass)
193198
}
194199

195200
/**
@@ -214,14 +219,14 @@ export class MessageReceiver {
214219
* Send the problem report message (https://didcomm.org/notification/1.0/problem-report) to the recipient.
215220
* @param message error message to send
216221
* @param connection connection to send the message to
217-
* @param unpackedMessage received unpackedMessage
222+
* @param plaintextMessage received inbound message
218223
*/
219224
private async sendProblemReportMessage(
220225
message: string,
221226
connection: ConnectionRecord,
222-
unpackedMessage: UnpackedMessageContext
227+
plaintextMessage: PlaintextMessage
223228
) {
224-
if (unpackedMessage.message['@type'] === CommonMessageType.ProblemReport) {
229+
if (plaintextMessage['@type'] === CommonMessageType.ProblemReport) {
225230
throw new AriesFrameworkError(message)
226231
}
227232
const problemReportMessage = new ProblemReportMessage({
@@ -231,7 +236,7 @@ export class MessageReceiver {
231236
},
232237
})
233238
problemReportMessage.setThread({
234-
threadId: unpackedMessage.message['@id'],
239+
threadId: plaintextMessage['@id'],
235240
})
236241
const outboundMessage = createOutboundMessage(connection, problemReportMessage)
237242
if (outboundMessage) {

Diff for: packages/core/src/agent/MessageSender.ts

+13-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { DidCommService, ConnectionRecord } from '../modules/connections'
22
import type { OutboundTransport } from '../transport/OutboundTransport'
3-
import type { OutboundMessage, OutboundPackage, WireMessage } from '../types'
3+
import type { OutboundMessage, OutboundPackage, EncryptedMessage } from '../types'
44
import type { AgentMessage } from './AgentMessage'
55
import type { EnvelopeKeys } from './EnvelopeService'
66
import type { TransportSession } from './TransportService'
@@ -56,10 +56,10 @@ export class MessageSender {
5656
message: AgentMessage
5757
endpoint: string
5858
}): Promise<OutboundPackage> {
59-
const wireMessage = await this.envelopeService.packMessage(message, keys)
59+
const encryptedMessage = await this.envelopeService.packMessage(message, keys)
6060

6161
return {
62-
payload: wireMessage,
62+
payload: encryptedMessage,
6363
responseRequested: message.hasAnyReturnRoute(),
6464
endpoint,
6565
}
@@ -72,18 +72,17 @@ export class MessageSender {
7272
if (!session.keys) {
7373
throw new AriesFrameworkError(`There are no keys for the given ${session.type} transport session.`)
7474
}
75-
const wireMessage = await this.envelopeService.packMessage(message, session.keys)
76-
77-
await session.send(wireMessage)
75+
const encryptedMessage = await this.envelopeService.packMessage(message, session.keys)
76+
await session.send(encryptedMessage)
7877
}
7978

8079
public async sendPackage({
8180
connection,
82-
packedMessage,
81+
encryptedMessage,
8382
options,
8483
}: {
8584
connection: ConnectionRecord
86-
packedMessage: WireMessage
85+
encryptedMessage: EncryptedMessage
8786
options?: { transportPriority?: TransportPriorityOptions }
8887
}) {
8988
const errors: Error[] = []
@@ -92,7 +91,7 @@ export class MessageSender {
9291
const session = this.transportService.findSessionByConnectionId(connection.id)
9392
if (session?.inboundMessage?.hasReturnRouting()) {
9493
try {
95-
await session.send(packedMessage)
94+
await session.send(encryptedMessage)
9695
return
9796
} catch (error) {
9897
errors.push(error)
@@ -114,7 +113,7 @@ export class MessageSender {
114113
for (const transport of this.outboundTransports) {
115114
if (transport.supportedSchemes.includes(service.protocolScheme)) {
116115
await transport.sendMessage({
117-
payload: packedMessage,
116+
payload: encryptedMessage,
118117
endpoint: service.serviceEndpoint,
119118
connectionId: connection.id,
120119
})
@@ -137,13 +136,13 @@ export class MessageSender {
137136
// If the other party shared a queue service endpoint in their did doc we queue the message
138137
if (queueService) {
139138
this.logger.debug(`Queue packed message for connection ${connection.id} (${connection.theirLabel})`)
140-
this.messageRepository.add(connection.id, packedMessage)
139+
this.messageRepository.add(connection.id, encryptedMessage)
141140
return
142141
}
143142

144143
// Message is undeliverable
145144
this.logger.error(`Message is undeliverable to connection ${connection.id} (${connection.theirLabel})`, {
146-
message: packedMessage,
145+
message: encryptedMessage,
147146
errors,
148147
connection,
149148
})
@@ -217,8 +216,8 @@ export class MessageSender {
217216
senderKey: connection.verkey,
218217
}
219218

220-
const wireMessage = await this.envelopeService.packMessage(payload, keys)
221-
this.messageRepository.add(connection.id, wireMessage)
219+
const encryptedMessage = await this.envelopeService.packMessage(payload, keys)
220+
this.messageRepository.add(connection.id, encryptedMessage)
222221
return
223222
}
224223

Diff for: packages/core/src/agent/TransportService.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { DidDoc, IndyAgentService } from '../modules/connections/models'
22
import type { ConnectionRecord } from '../modules/connections/repository'
3-
import type { WireMessage } from '../types'
3+
import type { EncryptedMessage } from '../types'
44
import type { AgentMessage } from './AgentMessage'
55
import type { EnvelopeKeys } from './EnvelopeService'
66

@@ -64,5 +64,5 @@ export interface TransportSession {
6464
keys?: EnvelopeKeys
6565
inboundMessage?: AgentMessage
6666
connection?: ConnectionRecord
67-
send(wireMessage: WireMessage): Promise<void>
67+
send(encryptedMessage: EncryptedMessage): Promise<void>
6868
}

0 commit comments

Comments
 (0)