diff --git a/.changeset/tough-rabbits-complain.md b/.changeset/tough-rabbits-complain.md new file mode 100644 index 0000000..271c2b1 --- /dev/null +++ b/.changeset/tough-rabbits-complain.md @@ -0,0 +1,9 @@ +--- +"@zcloak/login-rpc-defines": patch +"@zcloak/message": patch +"@zcloak/login-providers": patch +"@zcloak/did": patch +"@zcloak/login-did": patch +--- + +add batch decrypt diff --git a/login/did/src/LoginDid.ts b/login/did/src/LoginDid.ts index 12c6143..7ed14ad 100644 --- a/login/did/src/LoginDid.ts +++ b/login/did/src/LoginDid.ts @@ -129,4 +129,12 @@ export class LoginDid extends Did implements IDidKeyring { }; }); } + + public override async batchDecrypt( + params: { sender: `did:zk:${string}`; message: `0x${string}` }[] + ): Promise { + const decrypts = await this.provider.batchDecrypt(params); + + return decrypts.map((data) => hexToU8a(data)); + } } diff --git a/login/providers/src/base/Provider.ts b/login/providers/src/base/Provider.ts index b4c9549..5d88bc3 100644 --- a/login/providers/src/base/Provider.ts +++ b/login/providers/src/base/Provider.ts @@ -169,4 +169,8 @@ export class BaseProvider extends Events { public async batchEncrypt(params: RpcRequest<'batch_encrypt'>): Promise> { return this.request('batch_encrypt', params); } + + public async batchDecrypt(params: RpcRequest<'batch_decrypt'>): Promise> { + return this.request('batch_decrypt', params); + } } diff --git a/login/rpc-defines/src/defineZk.ts b/login/rpc-defines/src/defineZk.ts index 58c3fc5..0af61a3 100644 --- a/login/rpc-defines/src/defineZk.ts +++ b/login/rpc-defines/src/defineZk.ts @@ -103,6 +103,7 @@ declare module '@zcloak/login-rpc/rpcs' { send_tx: [SendTxParams, any]; batch_sign: [BatchSignParams, SignedData[]]; batch_encrypt: [DidEncryptParams[], DidEncrypted[]]; + batch_decrypt: [DidDecryptParams[], HexString[]]; } interface RpcEvents { diff --git a/packages/message/src/decrypt/index.ts b/packages/message/src/decrypt/index.ts index 78690cf..6aa12a7 100644 --- a/packages/message/src/decrypt/index.ts +++ b/packages/message/src/decrypt/index.ts @@ -5,9 +5,10 @@ import type { IDidKeyring } from '@zcloak/did/types'; import type { DidResolver } from '@zcloak/did-resolver'; import type { BaseMessage, DecryptedMessage, Message, MessageData, MessageType } from '../types'; -import { assert, isHex, isNumber, u8aToString } from '@polkadot/util'; +import { assert, isHex, isNumber, u8aToHex, u8aToString } from '@polkadot/util'; import { decodeMultibase } from '@zcloak/crypto'; +import { DidKeyring } from '@zcloak/did/did/keyring'; import { isDidUrl, isSameUri } from '@zcloak/did/utils'; import { defaultResolver } from '@zcloak/did-resolver/defaults'; import { isRawCredential, isVC, isVP } from '@zcloak/vc/is'; @@ -172,3 +173,43 @@ export async function decryptMessage( return decryptedMessage; } + +export async function batchDecryptMessage( + messages: Message[], + did: DidKeyring, + resolver: DidResolver = defaultResolver +): Promise[]> { + messages.forEach((message) => verifyMessageEnvelope(message)); + + const decrypteds = await did.batchDecrypt( + messages.map((message) => { + return { + message: u8aToHex(decodeMultibase(message.encryptedMsg)), + sender: message.sender + }; + }), + undefined, + resolver + ); + + const decryptedMessages: DecryptedMessage[] = decrypteds.map((decrypted, index) => { + const message = messages[index]; + const data: MessageData[T] = JSON.parse(u8aToString(decrypted)); + + return { + id: message.id, + reply: message.reply, + createTime: message.createTime, + version: message.version, + msgType: message.msgType, + sender: message.sender, + receiver: message.receiver, + ctype: message.ctype, + data + }; + }); + + decryptedMessages.forEach((decryptedMessage) => verifyMessageData(decryptedMessage)); + + return decryptedMessages; +} diff --git a/protocol/did/src/did/keyring.ts b/protocol/did/src/did/keyring.ts index 4af30d3..02bd846 100644 --- a/protocol/did/src/did/keyring.ts +++ b/protocol/did/src/did/keyring.ts @@ -183,4 +183,17 @@ export abstract class DidKeyring extends DidDetails implements IDidKeyring { return Promise.all(encrypts); } + + public batchDecrypt( + params: { + sender: DidUrl; + message: HexString; + }[], + receiverUrl = this.getKeyUrl('keyAgreement'), + resolver: DidResolver = defaultResolver + ): Promise { + const decrypts = params.map(({ message, sender }) => this.decrypt(message, sender, receiverUrl, resolver)); + + return Promise.all(decrypts); + } }