move to new identity key mechanism

now we do as followed:
• Generate 16 bytes of random data
• Add 16 bytes of zeros
• Use the 16 bytes of random + 16 bytes of zeros to generate an ED25519 key pair
• Convert the ED25519 key pair to an X25519 key pair

All of this is happening with libsodiumm called over IPC
pull/1385/head
Audric Ackermann 5 years ago
parent 5d21b21fb6
commit 1f2c01722a
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -60,11 +60,11 @@
// handle shorter than 32 bytes seeds
const privKeyHexLength = 32 * 2;
if (seedHex.length !== privKeyHexLength) {
seedHex = seedHex.concat(seedHex);
seedHex = seedHex.concat('0'.repeat(32));
seedHex = seedHex.substring(0, privKeyHexLength);
}
const seed = dcodeIO.ByteBuffer.wrap(seedHex, 'hex').toArrayBuffer();
return libsignal.Curve.async.createKeyPair(seed);
return window.sessionGenerateKeyPair(seed);
};
} else {
generateKeypair = libsignal.KeyHelper.generateIdentityKeyPair;

@ -1178,6 +1178,42 @@ ipc.on('decrypt-lns-entry', (event, lnsName, ciphertext) => {
decryptLns(event, lnsName, ciphertext);
});
async function sessionGenerateKeyPair(event, seed) {
const sodium = await getSodium();
try {
const ed25519KeyPair = sodium.crypto_sign_seed_keypair(
new Uint8Array(seed)
);
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 x25519KeyPair = {
pubKey: prependedX25519PublicKey.buffer,
privKey: x25519SecretKey.buffer,
};
// null as first parameter to indivate no error
event.reply('generate-keypair-seed-response', null, x25519KeyPair);
} catch (err) {
event.reply('generate-keypair-seed-response', err);
}
}
ipc.on('generate-keypair-seed', (event, seed) => {
sessionGenerateKeyPair(event, seed);
});
ipc.on('set-auto-update-setting', (event, enabled) => {
userConfig.set('autoUpdate', !!enabled);

@ -118,7 +118,7 @@ const localeMessages = ipc.sendSync('locale-data');
window.blake2b = input =>
new Promise((resolve, reject) => {
ipc.once('blake2b-digest-response', (event, error, res) => {
ipc.once('blake2b-digest-response', (_, error, res) => {
// eslint-disable-next-line no-unused-expressions
error ? reject(error) : resolve(res);
});
@ -128,7 +128,7 @@ window.blake2b = input =>
window.decryptLnsEntry = (key, value) =>
new Promise((resolve, reject) => {
ipc.once('decrypt-lns-response', (event, error, res) => {
ipc.once('decrypt-lns-response', (_, error, res) => {
// eslint-disable-next-line no-unused-expressions
error ? reject(error) : resolve(res);
});
@ -136,6 +136,16 @@ window.decryptLnsEntry = (key, value) =>
ipc.send('decrypt-lns-entry', key, value);
});
window.sessionGenerateKeyPair = seed =>
new Promise((resolve, reject) => {
ipc.once('generate-keypair-seed-response', (_, error, res) => {
// eslint-disable-next-line no-unused-expressions
error ? reject(error) : resolve(res);
});
ipc.send('generate-keypair-seed', seed);
});
window.updateZoomFactor = () => {
const zoomFactor = window.getSettingValue('zoom-factor-setting') || 100;
window.setZoomFactor(zoomFactor / 100);

@ -174,14 +174,14 @@ export class RegistrationTabs extends React.Component<{}, State> {
// handle shorter than 32 bytes seeds
const privKeyHexLength = 32 * 2;
if (seedHex.length !== privKeyHexLength) {
seedHex = seedHex.concat(seedHex);
seedHex = seedHex.concat('0'.repeat(32));
seedHex = seedHex.substring(0, privKeyHexLength);
}
const seed = window.dcodeIO.ByteBuffer.wrap(
seedHex,
'hex'
).toArrayBuffer();
const keyPair = await window.libsignal.Curve.async.createKeyPair(seed);
const keyPair = await window.sessionGenerateKeyPair(seed);
const hexGeneratedPubKey = StringUtils.decode(keyPair.pubKey, 'hex');
this.setState({
@ -297,9 +297,7 @@ export class RegistrationTabs extends React.Component<{}, State> {
{this.renderRegistrationContent()}
<SessionButton
onClick={() => {
this.onCompleteSignUpClick();
}}
onClick={this.onCompleteSignUpClick}
buttonType={SessionButtonType.Brand}
buttonColor={SessionButtonColor.Green}
text={window.i18n('getStarted')}

1
ts/window.d.ts vendored

@ -99,5 +99,6 @@ declare global {
GroupBuffer: any;
SwarmPolling: SwarmPolling;
owsDesktopApp: any;
sessionGenerateKeyPair: (seed: ArrayBuffer) => Promise<{ pubKey: ArrayBufferLike; privKey: ArrayBufferLike; }>;
}
}

Loading…
Cancel
Save