<commit_before>"use strict";

import * as kbpgp from "kbpgp"
const Constants = kbpgp.const;

import { assert, Buffer, check } from "verifyme_utility"
import * as sig from "../../node_modules/kbpgp/lib/openpgp/packet/signature"

import BlindingContext from "./../blinding/blinding_context"

/**
 * A kind of key signature packet where the signer
 * does not know whose key is signed.
 */
export default class BlindSignaturePacket extends sig.Signature
{
  /**
   * Creates a new signature packet.
   *
   * To avoid that the signer later finds a relationship between the
   * signature request and the published signature the signature creation
   * time is randomized.
   *
   * @param {KeyManager} target_key
   *    The key to sign stored in a {KeyManger}.
   * @param {KeyManager} sig_key
   *    The signers public key stored in a {KeyManger}.
   * @param {BlindingContext} context
   *    An algorithm based signing context to encode the prepared
   *    raw signature data.
   */
  constructor(target_key, sig_key, context)
  {
    assert(check.isKeyManager(target_key));
    assert(check.isKeyManager(sig_key));
    assert(context instanceof BlindingContext);

    const hashed_subpackets = [
      new sig.CreationTime(BlindSignaturePacket.calculateRandomCreationDate(target_key))
    ];

    const unhashed_subpackets = [
      new sig.Issuer(sig_key.get_pgp_key_id())
    ];

    const ctor_args = {
      hashed_subpackets: hashed_subpackets,
      key: sig_key.get_primary_keypair(),
      key_id: sig_key.get_pgp_key_id(),
      unhashed_subpackets: unhashed_subpackets,
      type: Constants.openpgp.sig_types.persona,
      version: Constants.openpgp.versions.signature.V4
    };

    super(ctor_args);

    this.tag = kbpgp.const.openpgp.packet_tags.signature;
    this.target_key = target_key;
    this.primary = target_key.pgp.key(target_key.pgp.primary);

    this.prepareRawSignature(context);
  }

  /**
   * Calculates a random creation time between the given keys creation und expire date.
   * If no expire date exists, the maximum possible date value is used.
   *
   * @param {KeyManager} target_key
   *    The key we use as to identify the lifespan.
   * @returns {number}
   *    A random integer number somewhere in the given keys lifespan.
   */
  static calculateRandomCreationDate(target_key)
  {
    assert(check.isKeyManager(target_key));

    const lifespan = target_key.primary.lifespan;
    let key_expire = lifespan.expire_in;

    // if no expire date is available use maximum possible date in the future (8640000000000000)
    //    - 100,000,000 days measured relative to midnight at the beginning of 01 January, 1970 UTC.
    //      http://es5.github.io/#x15.9.1.1

    // pgp defines Time files as four-octet fields containing the number of seconds elapsed since 1/1/1970
    // so we have to use a smaller number (2^32 - 1)
    //    - https://tools.ietf.org/html/rfc4880#section-3.5
    if (null === key_expire || 0 >= key_expire) {
      key_expire = Math.pow(2, 32) - 1;
    }

    return Math.floor(lifespan.generated + Math.random() * (key_expire - lifespan.generated));
  }

  /**
   * Prepares the raw signature data.
   *
   * This data is unsigned and encoded for the blind sign process
   * where the given blinding context is used. To finalize the
   * signature data the related blind signature algorithm must be used.
   *
   * @param {BlindingContext} context
   *    This context should be created from the signers public key and
   *    is used to encode the data in preparation of the signing algorithm.
   */
  prepareRawSignature(context)
  {
    assert(context instanceof BlindingContext);

    const signData = this.generateSignaturePayload();

    this.raw_signature = context.encodeSignaturePayload(signData, this.hasher);
    this.signed_hash_value_hash = this.raw_signature.toBuffer().slice(0, 2);
  }

  /**
   * Generates the unsigned key signature payload.<commit_msg>Client BlindSignature: fixes expire date calculation<commit_after>"use strict";

import * as kbpgp from "kbpgp"
const Constants = kbpgp.const;

import { assert, Buffer, check } from "verifyme_utility"
import * as sig from "../../node_modules/kbpgp/lib/openpgp/packet/signature"

import BlindingContext from "./../blinding/blinding_context"

/**
 * A kind of key signature packet where the signer
 * does not know whose key is signed.
 */
export default class BlindSignaturePacket extends sig.Signature
{
  /**
   * Creates a new signature packet.
   *
   * To avoid that the signer later finds a relationship between the
   * signature request and the published signature the signature creation
   * time is randomized.
   *
   * @param {KeyManager} target_key
   *    The key to sign stored in a {KeyManger}.
   * @param {KeyManager} sig_key
   *    The signers public key stored in a {KeyManger}.
   * @param {BlindingContext} context
   *    An algorithm based signing context to encode the prepared
   *    raw signature data.
   */
  constructor(target_key, sig_key, context)
  {
    assert(check.isKeyManager(target_key));
    assert(check.isKeyManager(sig_key));
    assert(context instanceof BlindingContext);

    const hashed_subpackets = [
      new sig.CreationTime(BlindSignaturePacket.calculateRandomCreationDate(target_key))
    ];

    const unhashed_subpackets = [
      new sig.Issuer(sig_key.get_pgp_key_id())
    ];

    const ctor_args = {
      hashed_subpackets: hashed_subpackets,
      key: sig_key.get_primary_keypair(),
      key_id: sig_key.get_pgp_key_id(),
      unhashed_subpackets: unhashed_subpackets,
      type: Constants.openpgp.sig_types.persona,
      version: Constants.openpgp.versions.signature.V4
    };

    super(ctor_args);

    this.tag = kbpgp.const.openpgp.packet_tags.signature;
    this.target_key = target_key;
    this.primary = target_key.pgp.key(target_key.pgp.primary);

    this.prepareRawSignature(context);
  }

  /**
   * Calculates a random creation time between the given keys creation und expire date.
   * If no expire date exists, the maximum possible date value is used.
   *
   * @param {KeyManager} target_key
   *    The key we use as to identify the lifespan.
   * @returns {number}
   *    A random integer number somewhere in the given keys lifespan.
   */
  static calculateRandomCreationDate(target_key)
  {
    assert(check.isKeyManager(target_key));

    const lifespan = target_key.primary.lifespan;
    let key_expire = lifespan.expire_in;

    // if no expire date is available use maximum possible date in the future (8640000000000000)
    //    - 100,000,000 days measured relative to midnight at the beginning of 01 January, 1970 UTC.
    //      http://es5.github.io/#x15.9.1.1

    // pgp defines Time files as four-octet fields containing the number of seconds elapsed since 1/1/1970
    // so we have to use a smaller number (2^32 - 1)
    //    - https://tools.ietf.org/html/rfc4880#section-3.5
    if (null === key_expire || 0 >= key_expire) {
      key_expire = Math.pow(2, 32) - lifespan.generated - 1;
    }

    return Math.floor(lifespan.generated + Math.random() * key_expire);
  }

  /**
   * Prepares the raw signature data.
   *
   * This data is unsigned and encoded for the blind sign process
   * where the given blinding context is used. To finalize the
   * signature data the related blind signature algorithm must be used.
   *
   * @param {BlindingContext} context
   *    This context should be created from the signers public key and
   *    is used to encode the data in preparation of the signing algorithm.
   */
  prepareRawSignature(context)
  {
    assert(context instanceof BlindingContext);

    const signData = this.generateSignaturePayload();

    this.raw_signature = context.encodeSignaturePayload(signData, this.hasher);
    this.signed_hash_value_hash = this.raw_signature.toBuffer().slice(0, 2);
  }

  /**
   * Generates the unsigned key signature payload.
{'fraction_non_alphanumeric': 0.0900138871354627, 'fraction_numerical': 0.015402095694988006, 'mean_word_length': 3.263724434876211, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7136820', 'n_tokens_mistral': 2507, 'n_tokens_neox': 2347, 'n_words': 720}