api/crypto.js

// Copyright 2018 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under
// the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT> or
// the Modified BSD license <LICENSE-BSD or https://opensource.org/licenses/BSD-3-Clause>,
// at your option.
//
// This file may not be copied, modified, or distributed except according to those terms.
//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.


const lib = require('../native/lib');
const h = require('../helpers');
const errConst = require('../error_const');
const makeError = require('../native/_error.js');

/**
 * Holds the public part of an encryption key pair
 * @hideconstructor
 */
class PubEncKey extends h.NetworkObject {

  /**
   * Generate raw buffer of public encryption key
   * @returns {Promise<Buffer>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *   try {
   *     const encKeyPair = await app.crypto.generateEncKeyPair();
   *     const pubEncKey = encKeyPair.pubEncKey;
   *     const rawPubEncKey = await pubEncKey.getRaw();
   *   } catch (err) {
   *     throw err;
   *   }
   * };
   */
  getRaw() {
    return lib.enc_pub_key_get(this.app.connection, this.ref);
  }

  /**
  * @private
  * used by autoref to clean the reference
  * @param {SAFEApp} app
  * @param {handle} ref
  */
  static free(app, ref) {
    return lib.enc_pub_key_free(app.connection, ref);
  }

  /**
   * Encrypt the input using recipient's public key. Only recipient will be able to decrypt data. Read more about [sealed boxes]{@link https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes}.
   * @param {String|Buffer} data
   * @returns {Promise<Buffer>} Encrypted data
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     const stringOrBuffer = 'plain string to be encrypted';
   *     try {
   *       const rawPubEncKey = Buffer.from(<recipient's public encryption key>);
   *       const pubEncKey = await app.crypto.pubEncKeyFromRaw(rawPubEncKey.buffer);
   *       const encryptedData = await pubEncKey.encryptSealed(data);
   *     } catch(err) {
   *       throw err;
   *     }
   * };
   */
  encryptSealed(data) {
    return lib.encrypt_sealed_box(this.app.connection, data, this.ref);
  }

  /**
   * Decrypt the given cipher text using the sender's public encryption key and the recipient's secret encryption key. Read more about [authenticated encryption]{@link https://libsodium.gitbook.io/doc/public-key_cryptography/authenticated_encryption}.
   *
   * @arg {Buffer} cipher Encrypted data
   * @arg {SecEncKey} secretEncKey Recipient's secret encryption key
   * @returns {Promise<Buffer>} Decrypted data
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     const cipher = 'plain text to be encrypted';
   *     try {
   *       const encKeyPair = await app.crypto.generateEncKeyPair();
   *       const rawPubEncKey = Buffer.from(<sender's public encryption key>);
   *       const pubEncKey = await app.crypto.pubEncKeyFromRaw(rawPubEncKey.buffer);
   *       const secretEncKey = encKeyPair.secEncKey;
   *       const decryptedData = await pubEncKey.decrypt(cipher, secretEncKey)
   *     } catch(err) {
   *       throw err;
   *     }
   * };
   */
  decrypt(cipher, secretEncKey) {
    return lib.decrypt(this.app.connection, cipher, this.ref, secretEncKey.ref);
  }

  /**
   * Encrypt the input using recipient's public encryption key and sender's secret encryption key, such that each party can generate a shared secret key to verify the integrity of ciphers and to also decrypt them. Read more about [authenticated encryption]{@link https://libsodium.gitbook.io/doc/public-key_cryptography/authenticated_encryption}.
   *
   * @param {Buffer|String} data
   * @param {SecEncKey} secretEncKey Sender's secret encryption key
   * @throws {MISSING_SEC_ENC_KEY}
   * @returns {Promise<Buffer>} Encrypted data
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     const data = 'plain text to be encrypted';
   *     try {
   *       const encKeyPair = await app.crypto.generateEncKeyPair();
   *       const rawPubEncKey = Buffer.from(<recipient's public encryption key>);
   *       const pubEncKey = await app.crypto.pubEncKeyFromRaw(rawPubEncKey.buffer);
   *       const secretEncKey = encKeyPair.secEncKey;
   *       const encryptedBuffer = await pubEncKey.encrypt(data, secretEncKey)
   *     } catch(err) {
   *       throw err;
   *     }
   * };
   */
  encrypt(data, secretEncKey) {
    if (!secretEncKey) {
      throw makeError(errConst.MISSING_SEC_ENC_KEY.code, errConst.MISSING_SEC_ENC_KEY.msg(32));
    }
    return lib.encrypt(this.app.connection, data, this.ref, secretEncKey.ref);
  }
}


/**
* Holds the secret part of an encryption key
* @hideconstructor
*/
class SecEncKey extends h.NetworkObject {

  /**
   * Generate raw buffer of secret encryption key
   * @returns {Promise<Buffer>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *   try {
   *     const encKeyPair = await app.crypto.generateEncKeyPair();
   *     const secEncKey = encKeyPair.secEncKey;
   *     const rawSecEncKey = await secEncKey.getRaw();
   *   } catch (err) {
   *     throw err;
   *   }
   * };
   */
  getRaw() {
    return lib.enc_secret_key_get(this.app.connection, this.ref);
  }

  /**
  * @private
  * used by autoref to clean the reference
  * @param {SAFEApp} app
  * @param {handle} ref
  */
  static free(app, ref) {
    return lib.enc_secret_key_free(app.connection, ref);
  }

  /**
   * Decrypt the given encrypted data using the sender's public encryption key and the recipient's secret encryption key. Read more about [authenticated encryption]{@link https://libsodium.gitbook.io/doc/public-key_cryptography/authenticated_encryption}.
   *
   * An example use case for this method is if you have received messages from multiple
   * senders, you may fetch your secret key once, then iterate over the messages
   * passing each associated public encryption key to decrypt each message.
   *
   * @arg {Buffer} cipher Encrypted data
   * @arg {PubEncKey} publicEncKey Sender's public encryption key
   * @throws {MISSING_PUB_ENC_KEY}
   * @returns {Promise<Buffer>} Decrypted data
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     const cipher = 'plain text to be encrypted';
   *     try {
   *       const encKeyPair = await app.crypto.generateEncKeyPair();
   *       const rawPubEncKey = Buffer.from(<sender's public encryption key>);
   *       const pubEncKey = await app.crypto.pubEncKeyFromRaw(rawPubEncKey.buffer);
   *       const secretEncKey = encKeyPair.secEncKey;
   *       const decryptedData = await pubEncKey.decrypt(cipher, secretEncKey)
   *     } catch(err) {
   *       throw err;
   *     }
   * };
   */
  decrypt(cipher, publicEncKey) {
    if (!publicEncKey) {
      throw makeError(errConst.MISSING_PUB_ENC_KEY.code, errConst.MISSING_PUB_ENC_KEY.msg);
    }
    return lib.decrypt(this.app.connection, cipher, publicEncKey.ref, this.ref);
  }

  /**
   * Encrypt the input using recipient's public encryption key and sender's secret encryption key, such that each party can generate a shared secret key to verify the integrity of ciphers and to also decrypt them. Read more about [authenticated encryption]{@link https://libsodium.gitbook.io/doc/public-key_cryptography/authenticated_encryption}.
   *
   * @param {Buffer|String} data
   * @param {PubEncKey} recipientPubKey Recipient's public encryption key
   * @returns {Promise<Buffer>} Encrypted data
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     const data = 'plain text to be encrypted';
   *     try {
   *       const encKeyPair = await app.crypto.generateEncKeyPair();
   *       const rawPubEncKey = Buffer.from(<recipient's public encryption key>);
   *       const recipientPubKey = await app.crypto.pubEncKeyFromRaw(rawPubEncKey.buffer);
   *       const secEncKey = encKeyPair.secEncKey;
   *       const encryptedBuffer = await secEncKey.encrypt(data, recipientPubKey)
   *     } catch(err) {
   *       throw err;
   *     }
   * };
   */
  encrypt(data, recipientPubKey) {
    return lib.encrypt(this.app.connection, data, recipientPubKey.ref, this.ref);
  }
}


/**
* Asymmetric encryption keypair
*/
class EncKeyPair {

  /**
  * @hideconstructor
  */
  constructor(app, pub, secret) {
    this.app = app;
    this._public = pub;
    this._secret = secret;
  }


  /**
   * Get the public encryption key instance of this keypair
   * @returns {PubEncKey}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *   try {
   *     const encKeyPair = await app.crypto.generateEncKeyPair();
   *     const pubEncKey = encKeyPair.pubEncKey;
   *   } catch (err) {
   *     throw err;
   *   }
   * };
   */
  get pubEncKey() {
    return this._public;
  }


  /**
   * Get the secret encryption key instance of this keypair
   * @returns {secEncKey}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *   try {
   *     const encKeyPair = await app.crypto.generateEncKeyPair();
   *     const secEncKey = encKeyPair.secEncKey;
   *   } catch (err) {
   *     throw err;
   *   }
   * };
   */
  get secEncKey() {
    return this._secret;
  }

  /**
   * Decrypt the input using this generated encryption key pair. Only recipient will be able to decrypt data. Read more about [sealed boxes]{@link https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes}.
   * @param {String|Buffer} cipher Encrypted data
   * @returns {Promise<Buffer>} Decrypted data
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     const cipher = <Encrypted data as sealed box>;
   *     try {
  *        const encKeyPair = await app.crypto.generateEncKeyPair();
   *       const decryptedData = await encKeyPair.decryptSealed(cipher);
   *     } catch(err) {
   *       throw err;
   *     }
   * };
   */
  decryptSealed(cipher) {
    return lib.decrypt_sealed_box(this.app.connection, cipher,
                                  this.pubEncKey.ref, this.secEncKey.ref);
  }
}

/**
* Holds the public part of a sign key pair
* @hideconstructor
*/
class PubSignKey extends h.NetworkObject {

  /**
   * Generate raw buffer of public sign key.
   * @returns {Promise<Buffer>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const signKeyPair = await app.crypto.generateSignKeyPair();
   *         const pubSignKey = signKeyPair.pubSignKey;
   *         const rawPubSignKey = await pubSignKey.getRaw();
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  getRaw() {
    return lib.sign_pub_key_get(this.app.connection, this.ref);
  }

  /**
  * @private
  * used by autoref to clean the reference
  * @param {SAFEApp} app
  * @param {handle} ref
  */
  static free(app, ref) {
    return lib.sign_pub_key_free(app.connection, ref);
  }

  /**
   * Verify the given signed data using the public sign key
   * @param {Buffer} data Signed data to be verified
   * @returns {Promise<Buffer>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *       const signKeyPair = await app.crypto.generateSignKeyPair();
   *       const pubSignKey = signKeyPair.pubSignKey;
   *       const verifiedData = await pubSignKey.verify(data);
   *     } catch(err) {
   *       throw err;
   *     }
   * };
   */
  verify(data) {
    return lib.verify(this.app.connection, data, this.ref);
  }
}

/**
* Holds the secret part of a sign key pair
* @hideconstructor
*/
class SecSignKey extends h.NetworkObject {

  /**
   * Generate raw buffer of secret sign key
   * @returns {Promise<Buffer>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *   try {
   *     const encKeyPair = await app.crypto.generateEncKeyPair();
   *     const secSignKey = encKeyPair.secSignKey;
   *     const rawSecSignKey = await secSignKey.getRaw();
   *   } catch (err) {
   *     throw err;
   *   }
   * };
   */
  getRaw() {
    return lib.sign_sec_key_get(this.app.connection, this.ref);
  }

  /**
  * @private
  * used by autoref to clean the reference
  * @param {SAFEApp} app
  * @param {handle} ref
  */
  static free(app, ref) {
    return lib.sign_sec_key_free(app.connection, ref);
  }

  /**
   * Sign the given data (buffer or string) using the secret sign key
   * @param {Buffer} data to sign
   * @returns {Promise<Buffer>} signed data
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     const data = 'Information to be signed';
   *     try {
   *       const encKeyPair = await app.crypto.generateEncKeyPair();
   *       const secSignKey = encKeyPair.secSignKey;
   *       const signedData = await secSignKey.sign(data);
   *     } catch(err) {
   *       throw err;
   *     }
   * };
   */
  sign(data) {
    return lib.sign(this.app.connection, data, this.ref);
  }
}

/**
* Signing keypair
* @hideconstructor
*/
class SignKeyPair {

  constructor(app, pub, secret) {
    this.app = app;
    this._public = pub;
    this._secret = secret;
  }


  /**
   * get the public sign key instance of this key pair
   * @returns {PubSignKey}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *   try {
   *     const encKeyPair = await app.crypto.generateEncKeyPair();
   *     const pubSignKey = signKeyPair.pubSignKey;
   *   } catch (err) {
   *     throw err;
   *   }
   * };
   */
  get pubSignKey() {
    return this._public;
  }


  /**
   * get the secrect sign key instance of this key pair
   * @returns {SecSignKey}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *   try {
   *     const encKeyPair = await app.crypto.generateEncKeyPair();
   *     const secSignKey = await signKeyPair.secSignKey;
   *   } catch (err) {
   *     throw err;
   *   }
   * };
   */
  get secSignKey() {
    return this._secret;
  }
}

/**
 * Contains all cryptographic related functionality
 */
class CryptoInterface {

  /**
   * @hideconstructor
   */
  constructor(app) {
    this.app = app;
  }

  /**
   * Hash the given input with SHA3 Hash
   * @returns {Promise<Buffer>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const hashedString = await app.crypto.sha3Hash('1010101010101')
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  sha3Hash(data) { // eslint-disable-line class-methods-use-this
    return lib.sha3_hash(data);
  }

  /**
   * Get current app's public signing key
   * @returns {Promise<PubSignKey>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const pubSignKey = await app.crypto.getAppPubSignKey();
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  getAppPubSignKey() {
    return lib.app_pub_sign_key(this.app.connection)
        .then((c) => h.autoref(new PubSignKey(this.app, c)));
  }

  /**
   * Get current app's public encryption key
   * @returns {Promise<PubEncKey>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const pubEncKey = await app.crypto.getAppPubEncKey();
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  getAppPubEncKey() {
    return lib.app_pub_enc_key(this.app.connection)
        .then((c) => h.autoref(new PubEncKey(this.app, c)));
  }

  /**
   * Generate a new asymmetric encryption key pair
   * @returns {Promise<EncKeyPair>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const encKeyPair = await app.crypto.generateEncKeyPair();
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  generateEncKeyPair() {
    return lib.enc_generate_key_pair(this.app.connection)
        .then((r) => new EncKeyPair(this.app,
            h.autoref(new PubEncKey(this.app, r[0])),
            h.autoref(new SecEncKey(this.app, r[1]))
          ));
  }

  /**
   * Generate a new sign key pair
   * @returns {Promise<SignKeyPair>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const signKeyPair = await app.crypto.generateSignKeyPair();
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  generateSignKeyPair() {
    return lib.sign_generate_key_pair(this.app.connection)
        .then((r) => new SignKeyPair(this.app,
            h.autoref(new PubSignKey(this.app, r[0])),
            h.autoref(new SecSignKey(this.app, r[1]))
          ));
  }

  /**
   * Generate asymmetric encryption key pair instance from raw keys
   * @returns {Promise<EncKeyPair>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         let encKeyPair = await app.crypto.generateEncKeyPair();
   *         const pubEncKey = encKeyPair.pubEncKey;
   *         const secEncKey = encKeyPair.secEncKey;
   *         const rawPubEncKey = await pubEncKey.getRaw();
   *         const rawSecEncKey = await secEncKey.getRaw();
   *         encKeyPair = await app.crypto.generateEncKeyPairFromRaw(
   *             rawPubEncKey.buffer,
   *             rawSecEncKey.buffer
   *         );
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  generateEncKeyPairFromRaw(rawPublicKey, rawSecretkey) {
    let pubKey;
    return this.pubEncKeyFromRaw(rawPublicKey)
        .then((pk) => { pubKey = pk; })
        .then(() => this.secEncKeyFromRaw(rawSecretkey))
        .then((sk) => new EncKeyPair(this.app, pubKey, sk));
  }

  /**
   * Generate sign key pair from raw keys
   * @returns {Promise<SignKeyPair>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         let signKeyPair = await app.crypto.generateSignKeyPair();
   *         const pubSignKey = signKeyPair.pubSignKey;
   *         const secSignKey = signKeyPair.secSignKey;
   *         const rawPubSignKey = await pubSignKey.getRaw();
   *         const rawSecSignKey = await secSignKey.getRaw();
   *         signKeyPair = await app.crypto.generateSignKeyPairFromRaw(
   *             rawPubSignKey.buffer,
   *             rawSecSignKey.buffer
   *         );
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  generateSignKeyPairFromRaw(rawPublicKey, rawSecretkey) {
    let pubKey;
    return this.pubSignKeyFromRaw(rawPublicKey)
        .then((pk) => { pubKey = pk; })
        .then(() => this.secSignKeyFromRaw(rawSecretkey))
        .then((sk) => new SignKeyPair(this.app, pubKey, sk));
  }

  /**
   * Generates a public sign key instance from a raw buffer
   * @param {Buffer} rawPubSignKey
   * @returns {Promise<PubSignKey>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const signKeyPair = await app.crypto.generateSignKeyPair();
   *         let pubSignKey = signKeyPair.pubSignKey;
   *         const rawPubSignKey = await pubSignKey.getRaw();
   *         pubSignKey = await app.crypto.pubSignKeyFromRaw(rawPubSignKey.buffer);
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  pubSignKeyFromRaw(rawPubSignKey) {
    return lib.sign_pub_key_new(this.app.connection, rawPubSignKey)
        .then((c) => h.autoref(new PubSignKey(this.app, c)));
  }

  /**
   * Generates a secret sign key from a raw buffer
   * @param {Buffer} rawSecSignKey
   * @returns {Promise<SecSignKey>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const signKeyPair = await app.crypto.generateSignKeyPair();
   *         let secSignKey = signKeyPair.secSignKey;
   *         const rawSecSignKey = await secSignKey.getRaw();
   *         secSignKey = await app.crypto.secSignKeyFromRaw(rawSecSignKey.buffer);
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  secSignKeyFromRaw(rawSecSignKey) {
    return lib.sign_sec_key_new(this.app.connection, rawSecSignKey)
        .then((c) => h.autoref(new SecSignKey(this.app, c)));
  }

  /**
   * Generates a public encryption key instance from raw buffer
   * @arg {Buffer} rawPubEncKey
   * @returns {Promise<PubEncKey>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const encKeyPair = await app.crypto.generateEncKeyPair();
   *         let pubEncKey = encKeyPair.pubEncKey;
   *         const rawPubEncKey = await pubEncKey.getRaw();
   *         pubEncKey = await app.crypto.pubEncKeyFromRaw(rawPubEncKey.buffer);
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  pubEncKeyFromRaw(rawPubEncKey) {
    return lib.enc_pub_key_new(this.app.connection, rawPubEncKey)
        .then((c) => h.autoref(new PubEncKey(this.app, c)));
  }

  /**
   * Generates a secret encryption key instance from raw buffer
   * @arg {Buffer} raw secret encryption key raw bytes as string
   * @returns {Promise<SecEncKey>}
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const encKeyPair = await app.crypto.generateEncKeyPair();
   *         let secEncKey = encKeyPair.secEncKey;
   *         const rawSecEncKey = await secEncKey.getRaw();
   *         secEncKey = await app.crypto.secEncKeyFromRaw(rawSecEncKey.buffer);
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  secEncKeyFromRaw(raw) {
    return lib.enc_secret_key_new(this.app.connection, raw)
        .then((c) => h.autoref(new SecEncKey(this.app, c)));
  }

  /**
   * Generate a nonce that can be used when creating private {@link MutableData}
   * @returns {Promise<Nonce>} the nonce generated
   * @example
   * // Assumes {@link initialiseApp|SAFEApp} interface has been obtained
   * const asyncFn = async () => {
   *     try {
   *         const nonce = await app.crypto.generateNonce();
   *     } catch (err) {
   *         throw err;
   *     }
   * };
   */
  generateNonce() { // eslint-disable-line class-methods-use-this
    return lib.generate_nonce();
  }
}


module.exports = {
  PubEncKey,
  SecEncKey,
  EncKeyPair,
  PubSignKey,
  SecSignKey,
  SignKeyPair,
  CryptoInterface
};