Example #1
0
class SignatureFragmentGenerator(Iterator[TryteString]):
    """
    Used to generate signature fragments progressively.

    Each instance can generate 1 signature per fragment in the private
    key.
    """

    def __init__(self, private_key: PrivateKey, hash_: Hash) -> None:
        super(SignatureFragmentGenerator, self).__init__()

        self._key_chunks = private_key.iter_chunks(FRAGMENT_LENGTH)
        self._iteration = -1
        self._normalized_hash = normalize(hash_)
        self._sponge = Kerl()

    def __iter__(self) -> 'SignatureFragmentGenerator':
        return self

    def __len__(self) -> int:
        """
        Returns the number of fragments this generator can create.

        Note: This method always returns the same result, no matter how
        many iterations have been completed.
        """
        return len(self._key_chunks)

    def __next__(self) -> TryteString:
        """
        Returns the next signature fragment.
        """
        key_trytes: TryteString = next(self._key_chunks)
        self._iteration += 1

        # If the key is long enough, loop back around to the start.
        normalized_chunk = (
            self._normalized_hash[self._iteration % len(self._normalized_hash)]
        )

        signature_fragment = key_trytes.as_trits()

        # Build the signature, one hash at a time.
        for i in range(key_trytes.count_chunks(Hash.LEN)):
            hash_start = i * HASH_LENGTH
            hash_end = hash_start + HASH_LENGTH

            buffer: List[int] = signature_fragment[hash_start:hash_end]

            for _ in range(13 - normalized_chunk[i]):
                self._sponge.reset()
                self._sponge.absorb(buffer)
                self._sponge.squeeze(buffer)

            signature_fragment[hash_start:hash_end] = buffer

        return TryteString.from_trits(signature_fragment)
Example #2
0
    def _create_sponge(self, index: int) -> Kerl:
        """
        Prepares the hash sponge for the generator.
        """
        seed = self.seed_as_trits[:]

        sponge = Kerl()
        sponge.absorb(add_trits(seed, trits_from_int(index)))

        # Squeeze all of the trits out of the sponge and re-absorb them.
        # Note that the sponge transforms several times per operation,
        # so this sequence is not as redundant as it looks at first
        # glance.
        sponge.squeeze(seed)
        sponge.reset()
        sponge.absorb(seed)

        return sponge
Example #3
0
  def _create_sponge(self, index):
    # type: (int) -> Kerl
    """
    Prepares the hash sponge for the generator.
    """
    seed = self.seed_as_trits[:]

    sponge = Kerl()
    sponge.absorb(add_trits(seed, trits_from_int(index)))

    # Squeeze all of the trits out of the sponge and re-absorb them.
    # Note that the sponge transforms several times per operation, so
    # this sequence is not as redundant as it looks at first glance.
    sponge.squeeze(seed)
    sponge.reset()
    sponge.absorb(seed)

    return sponge
Example #4
0
class SignatureFragmentGenerator(Iterator[TryteString]):
  """
  Used to generate signature fragments progressively.

  Each instance can generate 1 signature per fragment in the private
  key.
  """
  def __init__(self, private_key, hash_):
    # type: (PrivateKey, Hash) -> None
    super(SignatureFragmentGenerator, self).__init__()

    self._key_chunks      = private_key.iter_chunks(FRAGMENT_LENGTH)
    self._iteration       = -1
    self._normalized_hash = normalize(hash_)
    self._sponge          = Kerl()

  def __iter__(self):
    # type: () -> SignatureFragmentGenerator
    return self

  def __len__(self):
    # type: () -> int
    """
    Returns the number of fragments this generator can create.

    Note: This method always returns the same result, no matter how
    many iterations have been completed.
    """
    return len(self._key_chunks)

  def __next__(self):
    # type: () -> TryteString
    """
    Returns the next signature fragment.
    """
    key_trytes = next(self._key_chunks) # type: TryteString
    self._iteration += 1

    # If the key is long enough, loop back around to the start.
    normalized_chunk =\
      self._normalized_hash[self._iteration % len(self._normalized_hash)]

    signature_fragment = key_trytes.as_trits()

    # Build the signature, one hash at a time.
    for i in range(key_trytes.count_chunks(Hash.LEN)):
      hash_start  = i * HASH_LENGTH
      hash_end    = hash_start + HASH_LENGTH

      buffer = signature_fragment[hash_start:hash_end] # type: MutableSequence[int]

      for _ in range(13 - normalized_chunk[i]):
        self._sponge.reset()
        self._sponge.absorb(buffer)
        self._sponge.squeeze(buffer)

      signature_fragment[hash_start:hash_end] = buffer

    return TryteString.from_trits(signature_fragment)

  if PY2:
    next = __next__