All files / crypto/src Keys.js

84.62% Statements 22/26
58.33% Branches 7/12
100% Functions 3/3
84.62% Lines 22/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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112                  1x   1x 1x 1x 1x 1x                         300x     300x   300x     300x           300x   300x                                       39x 9x     30x   30x       30x                                 6x   6x         6x       6x               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 elliptic = require('elliptic/lib/elliptic/ec/index');
 
const Curve = require('@pascalcoin-sbx/common').Types.Keys.Curve;
const PrivateKey = require('@pascalcoin-sbx/common').Types.Keys.PrivateKey;
const PublicKey = require('@pascalcoin-sbx/common').Types.Keys.PublicKey;
const KeyPair = require('@pascalcoin-sbx/common').Types.Keys.KeyPair;
const BC = require('@pascalcoin-sbx/common').BC;
 
/**
 * Handles cryptographic keys.
 */
class Keys {
  /**
   * Generates a new keypair from the given curve.
   *
   * @param {Curve} curve
   * @returns {KeyPair}
   */
  static generate(curve) {
    Iif (curve === undefined) {
      // eslint-disable-next-line no-param-reassign
      curve = Curve.getDefaultCurve();
    } else Eif (!(curve instanceof Curve)) {
      // eslint-disable-next-line no-param-reassign
      curve = new Curve(curve);
    }
 
    Iif (curve.supported === false) {
      throw new Error('Unsupported curve: ' + curve.name);
    }
 
    // TODO: entropy?
    // eslint-disable-next-line new-cap
    const kp = new elliptic(curve.name).genKeyPair();
 
    return new KeyPair(
      new PrivateKey(
        new BC(kp.getPrivate().toArray()),
        curve
      ),
      new PublicKey(
        new BC(kp.getPublic().getX().toArray()),
        new BC(kp.getPublic().getY().toArray()),
        curve)
    );
  }
 
  /**
   * Creates a new keypair from the given private key.
   *
   * @param {PrivateKey} privateKey
   * @returns {KeyPair}
   */
  static fromPrivateKey(privateKey) {
 
    if (privateKey.curve.supported === false) {
      throw new Error('Unsupported curve: ' + privateKey.curve.name);
    }
 
    const kp = elliptic(privateKey.curve.name).keyFromPrivate(privateKey.key.buffer);
 
    Iif (!privateKey.key.equals(new BC(kp.getPrivate().toArray()))) {
      throw new Error('Something went wrong, the imported private key does not equal the elliptic one');
    }
 
    return new KeyPair(
      privateKey,
      new PublicKey(
        new BC(kp.getPublic().getX().toArray()),
        new BC(kp.getPublic().getY().toArray()),
        privateKey.curve)
    );
  }
 
  /**
   *
   * @param keyPair
   * @param digest
   * @returns {{r: BC, s: BC}}
   */
  static sign(keyPair, digest) {
    // create an ecpair
    const ecPair = elliptic(keyPair.curve.name).keyFromPrivate(keyPair.privateKey.key.buffer);
 
    const signature = ecPair.sign(digest.buffer, ecPair.getPrivate('hex'), 'hex', {
      canonical: false
    });
 
    // Verify signature
    Iif (ecPair.verify(digest.buffer, signature.toDER()) === false) {
      throw Error('Unable to verify the sign result.');
    }
 
    return {
      s: new BC(Buffer.from(signature.s.toArray())),
      r: new BC(Buffer.from(signature.r.toArray()))
    };
  }
 
}
 
module.exports = Keys;