diff --git a/ts/test/session/unit/libsession_wrapper/libsession_wrapper_metagroup_test.ts b/ts/test/session/unit/libsession_wrapper/libsession_wrapper_metagroup_test.ts new file mode 100644 index 000000000..4acf9a286 --- /dev/null +++ b/ts/test/session/unit/libsession_wrapper/libsession_wrapper_metagroup_test.ts @@ -0,0 +1,54 @@ +import { expect } from 'chai'; +import { MetaGroupWrapperNode, UserGroupsWrapperNode } from 'libsession_util_nodejs'; +import Sinon from 'sinon'; +import { HexString } from '../../../../node/hexStrings'; +import { toFixedUint8ArrayOfLength } from '../../../../types/sqlSharedTypes'; +import { TestUtils } from '../../../test-utils'; +import { TestUserKeyPairs } from '../../../test-utils/utils'; + +describe('libsession_metagroup', () => { + let us: TestUserKeyPairs; + let groupCreated: ReturnType; + let metaGroupWrapper: MetaGroupWrapperNode; + + beforeEach(async () => { + us = await TestUtils.generateUserKeyPairs(); + const groupWrapper = new UserGroupsWrapperNode(us.ed25519KeyPair.privateKey, null); + groupCreated = groupWrapper.createGroup(); + + metaGroupWrapper = new MetaGroupWrapperNode({ + groupEd25519Pubkey: toFixedUint8ArrayOfLength( + HexString.fromHexString(groupCreated.pubkeyHex.slice(2)), + 32 + ), + groupEd25519Secretkey: groupCreated.secretKey, + metaDumped: null, + userEd25519Secretkey: toFixedUint8ArrayOfLength(us.ed25519KeyPair.privateKey, 64), + }); + }); + afterEach(() => { + Sinon.restore(); + }); + + describe("encrypt/decrypt group's message", () => { + it('can encrypt/decrypt message for group with us as author', async () => { + const plaintext = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + const toEncrypt = new Uint8Array(plaintext); + const encrypted = metaGroupWrapper.encryptMessage(toEncrypt); + const decrypted = metaGroupWrapper.decryptMessage(encrypted); + + expect(decrypted.plaintext).to.be.deep.eq(toEncrypt); + expect(decrypted.pubkeyHex).to.be.deep.eq(us.x25519KeyPair.pubkeyHex); + }); + + it('throws when encrypt/decrypt message when content is messed up', async () => { + const plaintext = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + const toEncrypt = new Uint8Array(plaintext); + const encrypted = metaGroupWrapper.encryptMessage(toEncrypt); + + encrypted[1] = 67; + const func = () => metaGroupWrapper.decryptMessage(encrypted); + expect(func).to.throw('unable to decrypt ciphertext with any current group keys'); + }); + }); +}); diff --git a/ts/test/test-utils/utils/pubkey.ts b/ts/test/test-utils/utils/pubkey.ts index 826012e51..7247c7435 100644 --- a/ts/test/test-utils/utils/pubkey.ts +++ b/ts/test/test-utils/utils/pubkey.ts @@ -1,9 +1,11 @@ import * as crypto from 'crypto'; +import { GroupPubkeyType, UserGroupsWrapperNode } from 'libsession_util_nodejs'; +import { KeyPair, to_hex } from 'libsodium-wrappers-sumo'; import _ from 'lodash'; import { Snode } from '../../../data/data'; +import { getSodiumNode } from '../../../node/sodiumNode'; import { ECKeyPair } from '../../../receiver/keypairs'; import { PubKey } from '../../../session/types'; -import { GroupPubkeyType } from 'libsession_util_nodejs'; export function generateFakePubKey(): PubKey { // Generates a mock pubkey for testing @@ -23,6 +25,46 @@ export function generateFakePubKeyStr(): string { return pubkeyString; } +export type TestUserKeyPairs = { + x25519KeyPair: { + pubkeyHex: string; + pubKey: Uint8Array; + privKey: Uint8Array; + }; + ed25519KeyPair: KeyPair; +}; + +export async function generateUserKeyPairs(): Promise { + const sodium = await getSodiumNode(); + const ed25519KeyPair = sodium.crypto_sign_seed_keypair( + sodium.randombytes_buf(sodium.crypto_sign_SEEDBYTES) + ); + const x25519PublicKey = sodium.crypto_sign_ed25519_pk_to_curve25519(ed25519KeyPair.publicKey); + // prepend version byte (coming from `processKeys(raw_keys)`) + const origPub = new Uint8Array(x25519PublicKey); + const prependedX25519PublicKey = new Uint8Array(33); + prependedX25519PublicKey.set(origPub, 1); + prependedX25519PublicKey[0] = 5; + const x25519SecretKey = sodium.crypto_sign_ed25519_sk_to_curve25519(ed25519KeyPair.privateKey); + + // prepend with 05 the public key + const userKeys = { + x25519KeyPair: { + pubkeyHex: to_hex(prependedX25519PublicKey), + pubKey: prependedX25519PublicKey, + privKey: x25519SecretKey, + }, + ed25519KeyPair, + }; + + return userKeys; +} + +export async function generateGroupV2(privateEd25519: Uint8Array) { + const groupWrapper = new UserGroupsWrapperNode(privateEd25519, null); + return groupWrapper.createGroup(); +} + export function generateFakeClosedGroupV3PkStr(): GroupPubkeyType { // Generates a mock pubkey for testing const numBytes = PubKey.PUBKEY_LEN / 2 - 1;