UNPKG

proteus-hd

Version:

Signal Protocol (with header encryption) implementation for JavaScript. Based on Proteus.js.

110 lines (92 loc) 3.57 kB
/* * 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;