@ -1,9 +1,13 @@
import { GroupPubkeyType } from 'libsession_util_nodejs' ;
import { MessageEncrypter , concatUInt8Array , getSodiumRenderer } from '.' ;
import { Data } from '../../data/data' ;
import { SignalService } from '../../protobuf' ;
import { assertUnreachable } from '../../types/sqlSharedTypes' ;
import { MetaGroupWrapperActions } from '../../webworker/workers/browser/libsession_worker_interface' ;
import { PubKey } from '../types' ;
import { concatUInt8Array , getSodiumRenderer , MessageEncrypter } from '.' ;
import { fromHexToArray } from '../utils/String' ;
import { Data } from '../../data/data' ;
import { UserUtils } from '../utils' ;
import { fromHexToArray } from '../utils/String' ;
import { SigningFailed } from '../utils/errors' ;
import { addMessagePadding } from './BufferPadding' ;
export { concatUInt8Array , getSodiumRenderer } ;
@ -13,57 +17,106 @@ type EncryptResult = {
cipherText : Uint8Array ;
} ;
async function encryptWithLibSession ( destination : GroupPubkeyType , plainText : Uint8Array ) {
try {
return MetaGroupWrapperActions . encryptMessage ( destination , plainText , true ) ;
} catch ( e ) {
window . log . warn ( 'encrypt message for group failed with' , e . message ) ;
throw new SigningFailed ( e . message ) ;
}
}
async function encryptForLegacyGroup ( destination : PubKey , plainText : Uint8Array ) {
const hexEncryptionKeyPair = await Data . getLatestClosedGroupEncryptionKeyPair ( destination . key ) ;
if ( ! hexEncryptionKeyPair ) {
window ? . log ? . warn ( "Couldn't get key pair for closed group during encryption" ) ;
throw new Error ( "Couldn't get key pair for closed group" ) ;
}
const destinationX25519Pk = PubKey . cast ( hexEncryptionKeyPair . publicHex ) ;
const cipherTextClosedGroup = await MessageEncrypter . encryptUsingSessionProtocol (
destinationX25519Pk ,
plainText
) ;
return {
envelopeType : SignalService.Envelope.Type.CLOSED_GROUP_MESSAGE ,
cipherText : cipherTextClosedGroup ,
} ;
}
/ * *
* Encrypt ` plainTextBuffer ` with given ` encryptionType ` for ` device ` .
* Encrypt ` plainTextBuffer ` with given ` encryptionType ` for ` de stination ` .
*
* @param device The device ` PubKey ` to encrypt for .
* @param de stination The device ` PubKey ` to encrypt for .
* @param plainTextBuffer The unpadded plaintext buffer . It will be padded
* @param encryptionType The type of encryption .
* @returns The envelope type and the base64 encoded cipher text
* /
export async function encrypt (
device : PubKey ,
de stination : PubKey ,
plainTextBuffer : Uint8Array ,
encryptionType : SignalService.Envelope.Type
) : Promise < EncryptResult > {
const { CLOSED_GROUP_MESSAGE , SESSION_MESSAGE } = SignalService . Envelope . Type ;
if ( encryptionType !== CLOSED_GROUP_MESSAGE && encryptionType !== SESSION_MESSAGE ) {
throw new Error ( ` Invalid encryption type: ${ encryptionType } ` ) ;
}
const encryptForClosedGroup = encryptionType === CLOSED_GROUP_MESSAGE ;
const plainText = addMessagePadding ( plainTextBuffer ) ;
if ( encryptForClosedGroup ) {
// window?.log?.info(
// 'Encrypting message with SessionProtocol and envelope type is CLOSED_GROUP_MESSAGE'
// );
const hexEncryptionKeyPair = await Data . getLatestClosedGroupEncryptionKeyPair ( device . key ) ;
if ( ! hexEncryptionKeyPair ) {
window ? . log ? . warn ( "Couldn't get key pair for closed group during encryption" ) ;
throw new Error ( "Couldn't get key pair for closed group" ) ;
const plainTextPadded = addMessagePadding ( plainTextBuffer ) ;
switch ( encryptionType ) {
case SESSION_MESSAGE : {
// if (destination.isPrivate || destination.isUS) {
const cipherText = await MessageEncrypter . encryptUsingSessionProtocol (
PubKey . cast ( destination . key ) ,
plainTextPadded
) ;
return { envelopeType : SESSION_MESSAGE , cipherText } ;
// }
// if (destination.isGroupV2 || destination.isLegacyGroup) {
// throw new PreConditionFailed(
// 'Encryption with SESSION_MESSAGE only work with destination private or us'
// );
// }
// assertUnreachable(
// destination,
// 'Encryption with SESSION_MESSAGE only work with destination private or us'
// );
}
const hexPubFromECKeyPair = PubKey . cast ( hexEncryptionKeyPair . publicHex ) ;
const cipherTextClosedGroup = await MessageEncrypter . encryptUsingSessionProtocol (
hexPubFromECKeyPair ,
plainText
) ;
return {
envelopeType : CLOSED_GROUP_MESSAGE ,
cipherText : cipherTextClosedGroup ,
} ;
case CLOSED_GROUP_MESSAGE : {
const groupPk = destination . key ;
if ( PubKey . isClosedGroupV2 ( groupPk ) ) {
return {
envelopeType : CLOSED_GROUP_MESSAGE ,
cipherText : await encryptWithLibSession ( groupPk , plainTextBuffer ) ,
} ;
}
// if (destination.isLegacyGroup) {
return encryptForLegacyGroup ( destination , plainTextPadded ) ; // not padding it again, it is already done by libsession
// }
// if (
// destination.isBlinded ||
// destination.isBlinded ||
// destination.isPrivate ||
// destination.isUS
// ) {
// throw new PreConditionFailed(
// 'Encryption with CLOSED_GROUP_MESSAGE only work with destination groupv2 or legacy group'
// );
// }
// assertUnreachable(
// destination,
// 'Encryption with CLOSED_GROUP_MESSAGE only work with destination groupv2 or legacy group'
// );
}
default :
assertUnreachable ( encryptionType , '' ) ;
}
const cipherText = await MessageEncrypter . encryptUsingSessionProtocol ( device , plainText ) ;
return { envelopeType : SESSION_MESSAGE , cipherText } ;
}
export async function encryptUsingSessionProtocol (
recipientHexEncodedX25519PublicKey : PubKey ,
destinationX25519Pk : PubKey ,
plaintext : Uint8Array
) : Promise < Uint8Array > {
const userED25519KeyPairHex = await UserUtils . getUserED25519KeyPair ( ) ;
@ -76,9 +129,9 @@ export async function encryptUsingSessionProtocol(
}
const sodium = await getSodiumRenderer ( ) ;
// window?.log?.info('encryptUsingSessionProtocol for ', recipientHexEncodedX25519PublicKey.key);
const recipientX25519PublicKey = recipientHexEncodedX25519PublicKey . withoutPrefixToArray ( ) ;
const recipientX25519PublicKey = fromHexToArray (
PubKey . removePrefixIfNeeded ( destinationX25519Pk . key )
) ;
const userED25519PubKeyBytes = fromHexToArray ( userED25519KeyPairHex . pubKey ) ;
const userED25519SecretKeyBytes = fromHexToArray ( userED25519KeyPairHex . privKey ) ;