diff --git a/html5/js/Protocol.js b/html5/js/Protocol.js
index b03bc59c..b4bf43a3 100644
--- a/html5/js/Protocol.js
+++ b/html5/js/Protocol.js
@@ -351,12 +351,17 @@ class XpraProtocol {
this.protocol_error("encrypted packet received, but no decryption is configured");
return false;
}
+ // extract the iv:
+ const iv = packet_data.slice(0, 16);
+ const encrypted_data = packet_data.subarray(16);
+ this.cipher_in_params["iv"] = iv;
// console.log("decrypt", packet_data.byteLength, "bytes, padding=", padding, JSON.stringify(this.cipher_in_params), packet_data);
- crypto.subtle.decrypt(this.cipher_in_params, this.cipher_in_key, packet_data)
+ crypto.subtle.decrypt(this.cipher_in_params, this.cipher_in_key, encrypted_data)
.then(decrypted => {
// console.log("decrypted", decrypted.byteLength, "bytes, padding=", padding);
- if (!decrypted || decrypted.byteLength < packet_size - padding) {
- this.protocol_error(` expected ${packet_size - padding} bytes, but got ${decrypted.length}`);
+ const expected_length = packet_size - padding - iv.length;
+ if (!decrypted || decrypted.byteLength < expected_length) {
+ this.protocol_error(` expected ${expected_length} bytes, but got ${decrypted.byteLength}`);
return false;
}
if (decrypted.byteLength == packet_size - padding) {
@@ -463,12 +468,21 @@ class XpraProtocol {
this.error(error);
continue;
}
- const payload_size = bdata.length;
+ let payload_size = bdata.length;
if (this.cipher_out_key) {
//console("encrypting", packet[0], "packet using", JSON.stringify(this.cipher_out_params), ":", bdata);
+ const iv = Utilities.getSecureRandomBytes(16);
+ this.cipher_out_params["iv"] = iv;
crypto.subtle.encrypt(this.cipher_out_params, this.cipher_out_key, bdata)
- .then(encrypted => this.send_packet(new Uint8Array(encrypted), payload_size, true))
+ .then(encrypted => {
+ const enc_u8 = new Uint8Array(encrypted);
+ const packet_data = new Uint8Array(iv.byteLength + enc_u8.byteLength);
+ packet_data.set(iv, 0);
+ packet_data.set(enc_u8, iv.byteLength);
+ payload_size += iv.byteLength;
+ this.send_packet(packet_data, payload_size, true);
+ })
.catch(err => this.protocol_error("failed to encrypt packet: "+err));
return;
}
@@ -490,7 +504,6 @@ class XpraProtocol {
}
send_packet(bdata, payload_size, encrypted) {
- // console.log("send_packet", payload_size);
const level = 0;
let proto_flags = 0x10;
if (encrypted) {