proteus-hd
Version:
Signal Protocol (with header encryption) implementation for JavaScript. Based on Proteus.js.
110 lines (92 loc) • 3.57 kB
JavaScript
/*
* Wire
* Copyright (C) 2016 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/
'use strict';
const ClassUtil = require('../util/ClassUtil');
const DontCallConstructor = require('../errors/DontCallConstructor');
const KeyDerivationUtil = require('../util/KeyDerivationUtil');
const MemoryUtil = require('../util/MemoryUtil');
const CipherKey = require('./CipherKey');
const MacKey = require('./MacKey');
const HeadKey = require('./HeadKey');
/** @module derived */
/**
* @class DerivedSecrets
* @throws {DontCallConstructor}
*/
class DerivedSecrets {
constructor() {
throw new DontCallConstructor(this);
}
/**
* @param {!Array<number>} input
* @param {!Uint8Array} salt
* @param {!string} info
* @returns {DerivedSecrets} - `this`
*/
static kdf_init(input, salt, info) {
const byte_length = 128;
const output_key_material = KeyDerivationUtil.hkdf(salt, input, info, byte_length);
const cipher_key = new Uint8Array(output_key_material.buffer.slice(0, 32));
const mac_key = new Uint8Array(output_key_material.buffer.slice(32, 64));
const head_key = new Uint8Array(output_key_material.buffer.slice(64, 96));
const next_head_key = new Uint8Array(output_key_material.buffer.slice(96, 128));
MemoryUtil.zeroize(output_key_material.buffer);
const ds = ClassUtil.new_instance(DerivedSecrets);
/** @type {derived.CipherKey} */
ds.cipher_key = CipherKey.new(cipher_key);
/** @type {derived.MacKey} */
ds.mac_key = MacKey.new(mac_key);
/** @type {derived.HeadKey} */
ds.head_key_alice = HeadKey.new(head_key);
/** @type {derived.HeadKey} */
ds.next_head_key_bob = HeadKey.new(next_head_key);
return ds;
}
/**
* @param {!Array<number>} input
* @param {!Uint8Array} salt
* @param {!string} info
* @returns {DerivedSecrets} - `this`
*/
static kdf(input, salt, info) {
const byte_length = 96;
const output_key_material = KeyDerivationUtil.hkdf(salt, input, info, byte_length);
const cipher_key = new Uint8Array(output_key_material.buffer.slice(0, 32));
const mac_key = new Uint8Array(output_key_material.buffer.slice(32, 64));
const next_head_key = new Uint8Array(output_key_material.buffer.slice(64, 96));
MemoryUtil.zeroize(output_key_material.buffer);
const ds = ClassUtil.new_instance(DerivedSecrets);
/** @type {derived.CipherKey} */
ds.cipher_key = CipherKey.new(cipher_key);
/** @type {derived.MacKey} */
ds.mac_key = MacKey.new(mac_key);
/** @type {derived.HeadKey} */
ds.next_head_key = HeadKey.new(next_head_key);
return ds;
}
/**
* @param {!Array<number>} input - Initial key material (usually the Master Key) in byte array format
* @param {!string} info - Key Derivation Data
* @returns {DerivedSecrets}
*/
static kdf_without_salt(input, info) {
return this.kdf_init(input, new Uint8Array(0), info);
}
}
module.exports = DerivedSecrets;