PHP WebShell

Текущая директория: /opt/BitGoJS/node_modules/eccrypto

Просмотр файла: browser.js

"use strict";

var EC = require("elliptic").ec;

var ec = new EC("secp256k1");
var browserCrypto = global.crypto || global.msCrypto || {};
var subtle = browserCrypto.subtle || browserCrypto.webkitSubtle;

var nodeCrypto = require('crypto');

const EC_GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex');
const ZERO32 = Buffer.alloc(32, 0);

function assert(condition, message) {
  if (!condition) {
    throw new Error(message || "Assertion failed");
  }
}

function isScalar (x) {
  return Buffer.isBuffer(x) && x.length === 32;
}

function isValidPrivateKey(privateKey) {
  if (!isScalar(privateKey))
  {
    return false;
  }
  return privateKey.compare(ZERO32) > 0 && // > 0
  privateKey.compare(EC_GROUP_ORDER) < 0; // < G
}

// Compare two buffers in constant time to prevent timing attacks.
function equalConstTime(b1, b2) {
  if (b1.length !== b2.length) {
    return false;
  }
  var res = 0;
  for (var i = 0; i < b1.length; i++) {
    res |= b1[i] ^ b2[i];  // jshint ignore:line
  }
  return res === 0;
}

/* This must check if we're in the browser or
not, since the functions are different and does
not convert using browserify */
function randomBytes(size) {
  var arr = new Uint8Array(size);
  if (typeof browserCrypto.getRandomValues === 'undefined') {
    return Buffer.from(nodeCrypto.randomBytes(size));
  } else {
    browserCrypto.getRandomValues(arr);
  }
  return Buffer.from(arr);
}

function sha512(msg) {
  return new Promise(function(resolve) {
    var hash = nodeCrypto.createHash('sha512');
    var result = hash.update(msg).digest();
    resolve(new Uint8Array(result));
  });
}

function getAes(op) {
  return function(iv, key, data) {
    return new Promise(function(resolve) {
      if (subtle) {
        var importAlgorithm = {name: "AES-CBC"};
        var keyp = subtle.importKey("raw", key, importAlgorithm, false, [op]);
        return keyp.then(function(cryptoKey) {
          var encAlgorithm = {name: "AES-CBC", iv: iv};
          return subtle[op](encAlgorithm, cryptoKey, data);
        }).then(function(result) {
          resolve(Buffer.from(new Uint8Array(result)));
        });
      } else {
        if (op === 'encrypt') {
          var cipher = nodeCrypto.createCipheriv('aes-256-cbc', key, iv);
          let firstChunk = cipher.update(data);
          let secondChunk = cipher.final();
          resolve(Buffer.concat([firstChunk, secondChunk]));
        }
        else if (op === 'decrypt') {
          var decipher = nodeCrypto.createDecipheriv('aes-256-cbc', key, iv);
          let firstChunk = decipher.update(data);
          let secondChunk = decipher.final();
          resolve(Buffer.concat([firstChunk, secondChunk]));
        }
      }
    });
  };
}

var aesCbcEncrypt = getAes("encrypt");
var aesCbcDecrypt = getAes("decrypt");

function hmacSha256Sign(key, msg) {
  return new Promise(function(resolve) {
    var hmac = nodeCrypto.createHmac('sha256', Buffer.from(key));
    hmac.update(msg);
    var result = hmac.digest();
    resolve(result);
  });
}

function hmacSha256Verify(key, msg, sig) {
  return new Promise(function(resolve) {
    var hmac = nodeCrypto.createHmac('sha256', Buffer.from(key));
    hmac.update(msg);
    var expectedSig = hmac.digest();
    resolve(equalConstTime(expectedSig, sig));
  });
}

/**
  * Generate a new valid private key. Will use the window.crypto or window.msCrypto as source
  * depending on your browser.
  * @return {Buffer} A 32-byte private key.
  * @function
  */
exports.generatePrivate = function () {
  var privateKey = randomBytes(32);
  while (!isValidPrivateKey(privateKey)) {
    privateKey = randomBytes(32);
  }
  return privateKey;
};

var getPublic = exports.getPublic = function(privateKey) {
  // This function has sync API so we throw an error immediately.
  assert(privateKey.length === 32, "Bad private key");
  assert(isValidPrivateKey(privateKey), "Bad private key");
  // XXX(Kagami): `elliptic.utils.encode` returns array for every
  // encoding except `hex`.
  return Buffer.from(ec.keyFromPrivate(privateKey).getPublic("arr"));
};

/**
 * Get compressed version of public key.
 */
var getPublicCompressed = exports.getPublicCompressed = function(privateKey) { // jshint ignore:line
  assert(privateKey.length === 32, "Bad private key");
  assert(isValidPrivateKey(privateKey), "Bad private key");
  // See https://github.com/wanderer/secp256k1-node/issues/46
  let compressed = true;
  return Buffer.from(ec.keyFromPrivate(privateKey).getPublic(compressed, "arr"));
};

// NOTE(Kagami): We don't use promise shim in Browser implementation
// because it's supported natively in new browsers (see
// <http://caniuse.com/#feat=promises>) and we can use only new browsers
// because of the WebCryptoAPI (see
// <http://caniuse.com/#feat=cryptography>).
exports.sign = function(privateKey, msg) {
  return new Promise(function(resolve) {
    assert(privateKey.length === 32, "Bad private key");
    assert(isValidPrivateKey(privateKey), "Bad private key");
    assert(msg.length > 0, "Message should not be empty");
    assert(msg.length <= 32, "Message is too long");
    resolve(Buffer.from(ec.sign(msg, privateKey, {canonical: true}).toDER()));
  });
};

exports.verify = function(publicKey, msg, sig) {
  return new Promise(function(resolve, reject) {
    assert(publicKey.length === 65 || publicKey.length === 33, "Bad public key");
    if (publicKey.length === 65)
    {
      assert(publicKey[0] === 4, "Bad public key");
    }
    if (publicKey.length === 33)
    {
      assert(publicKey[0] === 2 || publicKey[0] === 3, "Bad public key");
    }
    assert(msg.length > 0, "Message should not be empty");
    assert(msg.length <= 32, "Message is too long");
    if (ec.verify(msg, sig, publicKey)) {
      resolve(null);
    } else {
      reject(new Error("Bad signature"));
    }
  });
};

var derive = exports.derive = function(privateKeyA, publicKeyB) {
  return new Promise(function(resolve) {
    assert(Buffer.isBuffer(privateKeyA), "Bad private key");
    assert(Buffer.isBuffer(publicKeyB), "Bad public key");
    assert(privateKeyA.length === 32, "Bad private key");
    assert(isValidPrivateKey(privateKeyA), "Bad private key");
    assert(publicKeyB.length === 65 || publicKeyB.length === 33, "Bad public key");
    if (publicKeyB.length === 65)
    {
      assert(publicKeyB[0] === 4, "Bad public key");
    }
    if (publicKeyB.length === 33)
    {
      assert(publicKeyB[0] === 2 || publicKeyB[0] === 3, "Bad public key");
    }
    var keyA = ec.keyFromPrivate(privateKeyA);
    var keyB = ec.keyFromPublic(publicKeyB);
    var Px = keyA.derive(keyB.getPublic());  // BN instance
    resolve(Buffer.from(Px.toArray()));
  });
};

exports.encrypt = function(publicKeyTo, msg, opts) {
  opts = opts || {};
  // Tmp variables to save context from flat promises;
  var iv, ephemPublicKey, ciphertext, macKey;
  return new Promise(function(resolve) {
    var ephemPrivateKey = opts.ephemPrivateKey || randomBytes(32);
    // There is a very unlikely possibility that it is not a valid key
    while(!isValidPrivateKey(ephemPrivateKey))
    {
      ephemPrivateKey = opts.ephemPrivateKey || randomBytes(32);
    }
    ephemPublicKey = getPublic(ephemPrivateKey);
    resolve(derive(ephemPrivateKey, publicKeyTo));
  }).then(function(Px) {
    return sha512(Px);
  }).then(function(hash) {
    iv = opts.iv || randomBytes(16);
    var encryptionKey = hash.slice(0, 32);
    macKey = hash.slice(32);
    return aesCbcEncrypt(iv, encryptionKey, msg);
  }).then(function(data) {
    ciphertext = data;
    var dataToMac = Buffer.concat([iv, ephemPublicKey, ciphertext]);
    return hmacSha256Sign(macKey, dataToMac);
  }).then(function(mac) {
    return {
      iv: iv,
      ephemPublicKey: ephemPublicKey,
      ciphertext: ciphertext,
      mac: mac,
    };
  });
};

exports.decrypt = function(privateKey, opts) {
  // Tmp variable to save context from flat promises;
  var encryptionKey;
  return derive(privateKey, opts.ephemPublicKey).then(function(Px) {
    return sha512(Px);
  }).then(function(hash) {
    encryptionKey = hash.slice(0, 32);
    var macKey = hash.slice(32);
    var dataToMac = Buffer.concat([
      opts.iv,
      opts.ephemPublicKey,
      opts.ciphertext
    ]);
    return hmacSha256Verify(macKey, dataToMac, opts.mac);
  }).then(function(macGood) {
    assert(macGood, "Bad MAC");
    return aesCbcDecrypt(opts.iv, encryptionKey, opts.ciphertext);
  }).then(function(msg) {
    return Buffer.from(new Uint8Array(msg));
  });
};

Выполнить команду


Для локальной разработки. Не используйте в интернете!