add the encryptWithSessionProtocol method
This commit is contained in:
parent
cf25e89a14
commit
cd3ec67099
|
@ -16,7 +16,7 @@
|
|||
img-src 'self' blob: data:;
|
||||
media-src 'self' blob:;
|
||||
object-src 'none';
|
||||
script-src 'self';
|
||||
script-src 'self' 'unsafe-eval';
|
||||
style-src 'self' 'unsafe-inline';"
|
||||
>
|
||||
<title>Session</title>
|
||||
|
|
|
@ -8,19 +8,13 @@ import _ from 'lodash';
|
|||
|
||||
import * as SenderKeyAPI from '../session/medium_group';
|
||||
import { getChainKey } from '../session/medium_group/ratchet';
|
||||
import { StringUtils } from '../session/utils';
|
||||
import { BufferType } from '../session/utils/String';
|
||||
import { ConversationModel } from '../../js/models/conversations';
|
||||
import { fromHex, toHex } from '../session/utils/String';
|
||||
import { UserUtil } from '../util';
|
||||
import {
|
||||
createSenderKeyForGroup,
|
||||
RatchetState,
|
||||
shareSenderKeys,
|
||||
} from '../session/medium_group/senderKeys';
|
||||
|
||||
const toHex = (d: BufferType) => StringUtils.decode(d, 'hex');
|
||||
const fromHex = (d: string) => StringUtils.encode(d, 'hex');
|
||||
|
||||
async function handleSenderKeyRequest(
|
||||
envelope: EnvelopePlus,
|
||||
groupUpdate: SignalService.MediumGroupUpdate
|
||||
|
|
|
@ -6,6 +6,8 @@ import { encryptWithSenderKey } from '../../session/medium_group/ratchet';
|
|||
import { PubKey } from '../types';
|
||||
import { StringUtils } from '../utils';
|
||||
|
||||
import * as libsodiumwrappers from 'libsodium-wrappers';
|
||||
|
||||
/**
|
||||
* Add padding to a message buffer
|
||||
* @param messageBuffer The buffer to add padding to.
|
||||
|
@ -69,6 +71,76 @@ export async function encrypt(
|
|||
return encryptUsingSealedSender(device, innerCipherText);
|
||||
}
|
||||
|
||||
async function getSodium(): Promise<typeof libsodiumwrappers> {
|
||||
await libsodiumwrappers.ready;
|
||||
return libsodiumwrappers;
|
||||
}
|
||||
|
||||
const concatUInt8Array = (...args: Array<Uint8Array>): Uint8Array => {
|
||||
const totalLength = args.reduce((acc, current) => acc + current.length, 0);
|
||||
|
||||
const concatted = new Uint8Array(totalLength);
|
||||
let currentIndex = 0;
|
||||
args.forEach(arr => {
|
||||
concatted.set(arr, currentIndex);
|
||||
currentIndex += arr.length;
|
||||
});
|
||||
|
||||
return concatted;
|
||||
};
|
||||
|
||||
export async function encryptUsingSessionProtocol(
|
||||
recipientHexEncodedX25519PublicKey: PubKey,
|
||||
plaintext: Uint8Array
|
||||
): Promise<Uint8Array> {
|
||||
const userED25519KeyPairHex = await UserUtil.getUserED25519KeyPair();
|
||||
if (!userED25519KeyPairHex) {
|
||||
throw new Error("Couldn't find user ED25519 key pair.");
|
||||
}
|
||||
const sodium = await getSodium();
|
||||
|
||||
const recipientX25519PublicKeyWithoutPrefix = PubKey.remove05PrefixIfNeeded(
|
||||
recipientHexEncodedX25519PublicKey.key
|
||||
);
|
||||
|
||||
const recipientX25519PublicKey = new Uint8Array(
|
||||
StringUtils.fromHex(recipientX25519PublicKeyWithoutPrefix)
|
||||
);
|
||||
const userED25519PubKeyBytes = new Uint8Array(
|
||||
StringUtils.fromHex(userED25519KeyPairHex.pubKey)
|
||||
);
|
||||
const userED25519SecretKeyBytes = new Uint8Array(
|
||||
StringUtils.fromHex(userED25519KeyPairHex.privKey)
|
||||
);
|
||||
|
||||
// merge all arrays into one
|
||||
const data = concatUInt8Array(
|
||||
plaintext,
|
||||
userED25519PubKeyBytes,
|
||||
recipientX25519PublicKey
|
||||
);
|
||||
|
||||
const signature = sodium.crypto_sign(data, userED25519SecretKeyBytes);
|
||||
if (!signature) {
|
||||
throw new Error("Couldn't sign message");
|
||||
}
|
||||
|
||||
const dataForBoxSeal = concatUInt8Array(
|
||||
plaintext,
|
||||
userED25519PubKeyBytes,
|
||||
signature
|
||||
);
|
||||
|
||||
const ciphertext = sodium.crypto_box_seal(
|
||||
dataForBoxSeal,
|
||||
recipientX25519PublicKey
|
||||
);
|
||||
if (!ciphertext) {
|
||||
throw new Error("Couldn't encrypt message.");
|
||||
}
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
export async function encryptForMediumGroup(
|
||||
device: PubKey,
|
||||
plainTextBuffer: Uint8Array
|
||||
|
|
|
@ -68,6 +68,13 @@ export class PubKey {
|
|||
return this.regex.test(pubkeyString);
|
||||
}
|
||||
|
||||
public static remove05PrefixIfNeeded(recipient: string): string {
|
||||
if (recipient.length === 66 && recipient.startsWith('05')) {
|
||||
return recipient.substr(2);
|
||||
}
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public isEqual(comparator: PubKey | string) {
|
||||
return comparator instanceof PubKey
|
||||
? this.key === comparator.key
|
||||
|
|
|
@ -29,3 +29,6 @@ export function decode(buffer: BufferType, stringEncoding: Encoding): string {
|
|||
export function nonNullish<V>(v: V): v is NonNullable<V> {
|
||||
return v !== undefined && v !== null;
|
||||
}
|
||||
|
||||
export const toHex = (d: BufferType) => decode(d, 'hex');
|
||||
export const fromHex = (d: string) => encode(d, 'hex');
|
||||
|
|
|
@ -2,6 +2,13 @@ import { getItemById } from '../../js/modules/data';
|
|||
import { KeyPair } from '../../libtextsecure/libsignal-protocol';
|
||||
import { PrimaryPubKey } from '../session/types';
|
||||
import { MultiDeviceProtocol } from '../session/protocols';
|
||||
import { StringUtils } from '../session/utils';
|
||||
import _ from 'lodash';
|
||||
|
||||
export type HexKeyPair = {
|
||||
pubKey: string;
|
||||
privKey: string;
|
||||
};
|
||||
|
||||
export async function getCurrentDevicePubKey(): Promise<string | undefined> {
|
||||
const item = await getItemById('number_id');
|
||||
|
@ -17,8 +24,27 @@ export async function getPrimary(): Promise<PrimaryPubKey> {
|
|||
return MultiDeviceProtocol.getPrimaryDevice(ourNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* This return the stored x25519 identity keypair for that user
|
||||
*/
|
||||
export async function getIdentityKeyPair(): Promise<KeyPair | undefined> {
|
||||
const item = await getItemById('identityKey');
|
||||
|
||||
return item?.value;
|
||||
}
|
||||
|
||||
export async function getUserED25519KeyPair(): Promise<HexKeyPair | undefined> {
|
||||
// 'identityKey' keeps the ed25519KeyPair under a ed25519KeyPair field.
|
||||
// it is only set if the user migrated to the ed25519 way of generating a key
|
||||
const item = await getItemById('identityKey');
|
||||
const ed25519KeyPair = item?.value?.ed25519KeyPair;
|
||||
if (ed25519KeyPair?.publicKey && ed25519KeyPair?.privateKey) {
|
||||
const pubKeyAsArray = _.map(ed25519KeyPair.publicKey, a => a);
|
||||
const privKeyAsArray = _.map(ed25519KeyPair.privateKey, a => a);
|
||||
return {
|
||||
pubKey: StringUtils.toHex(new Uint8Array(pubKeyAsArray)),
|
||||
privKey: StringUtils.toHex(new Uint8Array(privKeyAsArray)),
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue