All files / crypto/src/Encryption/Pascal Key.js

30.77% Statements 8/26
0% Branches 0/6
0% Functions 0/2
30.77% Lines 8/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90                  1x 1x 1x 1x 1x 1x 1x                                                                                                                                                 1x  
/**
 * Copyright (c) Benjamin Ansbach - all rights reserved.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
 
'use strict';
 
const Abstract = require('./../Abstract');
const BC = require('@pascalcoin-sbx/common').BC;
const ECDH = require('./../ECDH');
const KeyData = require('./KeyCoding/KeyData');
const KeyCoding = require('./KeyCoding/KeyCoding');
const CryptoJSEncHex = require('crypto-js/enc-hex');
const CryptoJSHmacMd5 = require('crypto-js/hmac-md5');
 
/**
 * A class that can en-/decrypt payloads based on a public key / private key.
 */
class Key extends Abstract {
  /**
   * Decrypts the given encrypted value using the given key pair.
   *
   * @param {Buffer|Uint8Array|BC|String} value
   * @param {Object} options
   *
   * @return {BC|false}
   */
  static decrypt(value, options = {keyPair: null}) {
 
    let keyData = new KeyCoding().decodeFromBytes(value);
 
    const dec = ECDH.decrypt(
      keyData.encryptedData, {
        privateKey: options.keyPair.privateKey,
        publicKey: keyData.publicKey,
        origMsgLength: keyData.originalDataLength
      }
    );
 
    const mac = BC.fromHex(CryptoJSHmacMd5(
      CryptoJSEncHex.parse(keyData.encryptedData.toHex()),
      CryptoJSEncHex.parse(dec.key.toHex())
    ).toString());
 
    // var mac5 = hmac3.update(keyData.encryptedData.toString(), 'utf8').digest('hex');
 
    if (keyData.mac.equals(mac)) {
      return dec.data;
    }
 
    return false;
  }
 
  /**
   * Encrypts the given value using the given public key.
   *
   * @param {Buffer|Uint8Array|BC|String} value
   * @param {Object} options
   * @return {BC}
   */
  static encrypt(value, options = {publicKey: null}) {
    value = BC.from(value);
    const enc = ECDH.encrypt(value, options);
 
    // TODO: this causes a big polyfill
    const mac = BC.fromHex(CryptoJSHmacMd5(
      CryptoJSEncHex.Hex.parse(enc.data.toHex()),
      CryptoJSEncHex.Hex.parse(enc.key.toHex())
    ).toString());
 
    const originalDataLength = value.length;
    const originalDataLengthIncPadLength = (originalDataLength % 16) === 0 ?
      0 : 16 - (originalDataLength % 16);
 
    let keyData = new KeyData();
 
    keyData.withPublicKey(enc.publicKey);
    keyData.withMac(mac);
    keyData.withEncryptedData(enc.data);
    keyData.withOriginalDataLength(originalDataLength);
    keyData.withOriginalDataLengthIncPadLength(originalDataLengthIncPadLength);
 
    return new KeyCoding().encodeToBytes(keyData);
  }
}
 
module.exports = Key;