1 import type { Event } from '@proton/docs-proto'
2 import { DocumentUpdate } from '@proton/docs-proto'
3 import type { EncryptionService } from '../Services/Encryption/EncryptionService'
4 import { GetAssociatedEncryptionDataForRealtimeMessage } from './GetAdditionalEncryptionData'
5 import type { EncryptionContext } from '../Services/Encryption/EncryptionContext'
6 import type { SessionKey } from '@proton/crypto'
7 import { VERIFICATION_STATUS } from '@proton/crypto'
8 import { DecryptedMessage } from '@proton/docs-shared'
9 import type { UseCaseInterface } from '../Domain/UseCase/UseCaseInterface'
10 import { Result } from '@proton/docs-shared'
12 export type DecryptMessageDTO = {
13 message: DocumentUpdate | Event
14 documentContentKey: SessionKey
18 export class DecryptMessage implements UseCaseInterface<DecryptedMessage> {
19 constructor(private encryption: EncryptionService<EncryptionContext.RealtimeMessage>) {}
21 async execute(dto: DecryptMessageDTO): Promise<Result<DecryptedMessage>> {
22 const decrypted = await this.encryption.decryptData(
23 dto.message instanceof DocumentUpdate ? dto.message.encryptedContent : dto.message.content,
24 GetAssociatedEncryptionDataForRealtimeMessage(dto.message),
25 dto.documentContentKey,
28 if (decrypted.isFailed()) {
29 return Result.fail(decrypted.getError())
33 const verificationKey = await this.encryption.getVerificationKey(dto.message.authorAddress)
35 if (verificationKey.isFailed()) {
36 return Result.fail(verificationKey.getError())
39 const verifyResult = await this.encryption.verifyData(
40 decrypted.getValue().content,
41 decrypted.getValue().signature,
42 GetAssociatedEncryptionDataForRealtimeMessage(dto.message),
43 verificationKey.getValue(),
46 if (verifyResult.isFailed()) {
47 return Result.fail(verifyResult.getError())
50 if (verifyResult.getValue() !== VERIFICATION_STATUS.SIGNED_AND_VALID) {
51 return Result.fail(`Message content verification failed: ${verifyResult.getValue()}`)
55 const message = new DecryptedMessage({
56 content: decrypted.getValue().content,
57 signature: decrypted.getValue().signature,
58 aad: GetAssociatedEncryptionDataForRealtimeMessage(dto.message),
59 authorAddress: dto.message.authorAddress,
60 timestamp: dto.message.timestamp,
63 return Result.ok(message)