Home Reference Source

lib6/encryption/local-key-encapsulation.js

/**
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [https://neo4j.com]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { newError } from '../error';
import CryptoProvider from './node/crypto';
function u8ToB64(u) {
    return btoa(String.fromCharCode(...u));
}
function b64Tou8(b) {
    return Uint8Array.from(atob(b), (c) => c.charCodeAt(0));
}
/**
 * An implementation of {@link KeyEncapsulationService} that uses a local, 256-bit, AES-GCM Key Encryption Key (KEK) to encrypt keys.
 *
 * @experimental Part of the Client-Side Encrytion preview feature
 */
export class LocalKeyEncapsulationService {
    constructor(kek) {
        if (kek.byteLength !== 32) {
            throw newError(`LocalKeyEncapsualationService master key must be of byteLength 32 (256 bits), got ${kek.byteLength} (${kek.byteLength * 8} bits)`);
        }
        this._kek = kek;
        this._cryptoProvider = new CryptoProvider();
    }
    /**
     * Creates a new key, encapsulates it with the local KEK and returns the result.
     *
     * @param {KeyEncapsulationOptions} options the encapsulation options, depends on the implementation
     * @return {Promise<EncapsulationResult>} a promise that resolves to the encapsulation result
     * @experimental Part of the Client-Side Encrytion preview feature
     */
    encapsulate(options) {
        return __awaiter(this, void 0, void 0, function* () {
            const DEK = this._cryptoProvider.getRandomValues(32);
            const encapulatedDEK = yield this._cryptoProvider.encrypt(this._kek, DEK.buffer, undefined);
            return new LocalEncapsulationResult(DEK, new Int8Array(encapulatedDEK.cyphertext), { iv: u8ToB64(encapulatedDEK.iv) });
        });
    }
    /**
     * Decapsulates encapsulated bytes with the local KEK.
     *
     * @param {Int8Array} encapsulation the encapsulated byte}
     * @param {KeyEncapsulationOptions} metadata the key metadata
     * @return {Promise<Uint8Array>} a promise that resolves to the decapsulated key
     * @experimental Part of the Client-Side Encrytion preview feature
     */
    decapsulate(encapsulation, metadata) {
        return __awaiter(this, void 0, void 0, function* () {
            return new Uint8Array(yield this._cryptoProvider.decrypt(this._kek, b64Tou8(metadata.iv), encapsulation.buffer, undefined));
        });
    }
}
/**
 * @private
 */
export class LocalEncapsulationResult {
    constructor(DEK, encapsulation, options) {
        this._dek = DEK;
        this._encapsulation = encapsulation;
        this._options = options;
    }
    encapsulation() {
        return this._encapsulation;
    }
    options() {
        return this._options;
    }
    key() {
        return this._dek;
    }
}
/**
 * Returns a new {@link KeyEncapsulationService} implementation that uses the provided AES-256
 * {@link SecretKey} as a master key for encapsulating and decapsulating data keys.
 *
 * @param {Uint8Array} masterKey the AES-256 master key
 * @return {KeyEncapsulationService} the new key encapsulation service
 * @experimental Part of the Client-Side Encrytion preview feature
 */
export function localKeyEncapsulationService(masterKey) {
    return new LocalKeyEncapsulationService(masterKey);
}