[tor-commits] [stem/master] Merge ed25519_exts_ref into hsv3_crypto

atagar at torproject.org atagar at torproject.org
Sun Nov 17 23:40:39 UTC 2019


commit 4db893a68a324c3ac16ece85c4f3b36e2d768fa8
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Nov 7 15:22:13 2019 -0800

    Merge ed25519_exts_ref into hsv3_crypto
    
    Moving the subset of ed25519_exts_ref that's used into hsv3_crypto to give
    myself one fewer modules to puzzle out.
---
 stem/descriptor/ed25519_exts_ref.py | 243 ------------------------------------
 stem/descriptor/hsv3_crypto.py      |  46 +++++--
 2 files changed, 39 insertions(+), 250 deletions(-)

diff --git a/stem/descriptor/ed25519_exts_ref.py b/stem/descriptor/ed25519_exts_ref.py
deleted file mode 100644
index 23701315..00000000
--- a/stem/descriptor/ed25519_exts_ref.py
+++ /dev/null
@@ -1,243 +0,0 @@
-#!/usr/bin/python
-# Copyright 2014-2019, The Tor Project, Inc
-# See LICENSE for licensing information
-
-"""
-   Reference implementations for the ed25519 tweaks that Tor uses.
-
-   Includes self-tester and test vector generator.
-"""
-
-from stem.descriptor import slow_ed25519
-
-import os
-import unittest
-import binascii
-import textwrap
-
-# define a synonym that doesn't look like 1
-ell = slow_ed25519.l
-
-# This replaces expmod above and makes it go a lot faster.
-slow_ed25519.expmod = pow
-
-
-def blindESK(esk, param):
-  mult = 2 ** (slow_ed25519.b - 2) + sum(2 ** i * slow_ed25519.bit(param, i) for i in range(3, slow_ed25519.b - 2))
-  s = slow_ed25519.decodeint(esk[:32])
-  s_prime = (s * mult) % ell
-  k = esk[32:]
-  assert(len(k) == 32)
-  k_prime = slow_ed25519.H(b'Derive temporary signing key hash input' + k)[:32]
-  return slow_ed25519.encodeint(s_prime) + k_prime
-
-
-def blindPK(pk, param):
-  mult = 2 ** (slow_ed25519.b - 2) + sum(2 ** i * slow_ed25519.bit(param, i) for i in range(3, slow_ed25519.b - 2))
-  P = slow_ed25519.decodepoint(pk)
-  return slow_ed25519.encodepoint(slow_ed25519.scalarmult(P, mult))
-
-
-def expandSK(sk):
-  h = slow_ed25519.H(sk)
-  a = 2 ** (slow_ed25519.b - 2) + sum(2 ** i * slow_ed25519.bit(h, i) for i in range(3, slow_ed25519.b - 2))
-  k = b''.join([h[i:i + 1] for i in range(slow_ed25519.b // 8, slow_ed25519.b // 4)])
-  assert len(k) == 32
-  return slow_ed25519.encodeint(a) + k
-
-
-def publickeyFromESK(h):
-  a = slow_ed25519.decodeint(h[:32])
-  A = slow_ed25519.scalarmult(slow_ed25519.B, a)
-  return slow_ed25519.encodepoint(A)
-
-
-def signatureWithESK(m, h, pk):
-  a = slow_ed25519.decodeint(h[:32])
-  r = slow_ed25519.Hint(b''.join([h[i:i + 1] for i in range(slow_ed25519.b // 8, slow_ed25519.b // 4)]) + m)
-  R = slow_ed25519.scalarmult(slow_ed25519.B, r)
-  S = (r + slow_ed25519.Hint(slow_ed25519.encodepoint(R) + pk + m) * a) % slow_ed25519.l
-
-  return slow_ed25519.encodepoint(R) + slow_ed25519.encodeint(S)
-
-
-def newSK():
-  return os.urandom(32)
-
-
-def random_scalar(entropy_f):
-  # 0..L-1 inclusive
-  # reduce the bias to a safe level by generating 256 extra bits
-
-  oversized = int(binascii.hexlify(entropy_f(32 + 32)), 16)
-  return oversized % ell
-
-
-# ------------------------------------------------------------
-
-MSG = b'This is extremely silly. But it is also incredibly serious business!'
-
-
-class SelfTest(unittest.TestCase):
-  def _testSignatures(self, esk, pk):
-    sig = signatureWithESK(MSG, esk, pk)
-    slow_ed25519.checkvalid(sig, MSG, pk)
-    bad = False
-
-    try:
-      slow_ed25519.checkvalid(sig, MSG * 2, pk)
-      bad = True
-    except Exception:
-      pass
-
-    self.assertFalse(bad)
-
-  def testExpand(self):
-    sk = newSK()
-    pk = slow_ed25519.publickey(sk)
-    esk = expandSK(sk)
-    sig1 = slow_ed25519.signature(MSG, sk, pk)
-    sig2 = signatureWithESK(MSG, esk, pk)
-    self.assertEqual(sig1, sig2)
-
-  def testSignatures(self):
-    sk = newSK()
-    esk = expandSK(sk)
-    pk = publickeyFromESK(esk)
-    pk2 = slow_ed25519.publickey(sk)
-    self.assertEqual(pk, pk2)
-
-    self._testSignatures(esk, pk)
-
-  def testBlinding(self):
-    sk = newSK()
-    esk = expandSK(sk)
-    pk = publickeyFromESK(esk)
-    param = os.urandom(32)
-    besk = blindESK(esk, param)
-    bpk = blindPK(pk, param)
-    bpk2 = publickeyFromESK(besk)
-    self.assertEqual(bpk, bpk2)
-
-    self._testSignatures(besk, bpk)
-
-  def testIdentity(self):
-    # Get identity E by doing: E = l*B, where l is the group order
-    identity = slow_ed25519.scalarmult(slow_ed25519.B, ell)
-
-    # Get identity E by doing: E = l*A, where A is a random point
-    sk = newSK()
-    pk = slow_ed25519.decodepoint(slow_ed25519.publickey(sk))
-    identity2 = slow_ed25519.scalarmult(pk, ell)
-
-    # Check that identities match
-    assert(identity == identity2)
-    # Check that identity is the point (0, 1)
-    assert(identity == [0, 1])
-
-    # Check identity element: a*E = E, where a is a random scalar
-    scalar = random_scalar(os.urandom)
-    result = slow_ed25519.scalarmult(identity, scalar)
-    assert(result == identity == identity2)
-
-
-# ------------------------------------------------------------
-
-# From pprint.pprint([binascii.b2a_hex(os.urandom(32)) for _ in xrange(8)])
-RAND_INPUTS = [
-  '26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d36',
-  'fba7a5366b5cb98c2667a18783f5cf8f4f8d1a2ce939ad22a6e685edde85128d',
-  '67e3aa7a14fac8445d15e45e38a523481a69ae35513c9e4143eb1c2196729a0e',
-  'd51385942033a76dc17f089a59e6a5a7fe80d9c526ae8ddd8c3a506b99d3d0a6',
-  '5c8eac469bb3f1b85bc7cd893f52dc42a9ab66f1b02b5ce6a68e9b175d3bb433',
-  'eda433d483059b6d1ff8b7cfbd0fe406bfb23722c8f3c8252629284573b61b86',
-  '4377c40431c30883c5fbd9bc92ae48d1ed8a47b81d13806beac5351739b5533d',
-  'c6bbcce615839756aed2cc78b1de13884dd3618f48367a17597a16c1cd7a290b']
-
-# From pprint.pprint([binascii.b2a_hex(os.urandom(32)) for _ in xrange(8)])
-BLINDING_PARAMS = [
-  '54a513898b471d1d448a2f3c55c1de2c0ef718c447b04497eeb999ed32027823',
-  '831e9b5325b5d31b7ae6197e9c7a7baf2ec361e08248bce055908971047a2347',
-  'ac78a1d46faf3bfbbdc5af5f053dc6dc9023ed78236bec1760dadfd0b2603760',
-  'f9c84dc0ac31571507993df94da1b3d28684a12ad14e67d0a068aba5c53019fc',
-  'b1fe79d1dec9bc108df69f6612c72812755751f21ecc5af99663b30be8b9081f',
-  '81f1512b63ab5fb5c1711a4ec83d379c420574aedffa8c3368e1c3989a3a0084',
-  '97f45142597c473a4b0e9a12d64561133ad9e1155fe5a9807fe6af8a93557818',
-  '3f44f6a5a92cde816635dfc12ade70539871078d2ff097278be2a555c9859cd0']
-
-PREFIX = 'ED25519_'
-
-
-def writeArray(name, array):
-  print('static const char *{prefix}{name}[] = {{'.format(prefix = PREFIX, name = name))
-
-  for a in array:
-    h = a.hex()
-
-    if len(h) > 70:
-      h1 = h[:70]
-      h2 = h[70:]
-      print('  "{0}"\n      "{1}",'.format(h1, h2))
-    else:
-      print('  "{0}",'.format(h))
-
-  print('};\n')
-
-
-def comment(text, initial='/**'):
-  print(initial)
-  print(textwrap.fill(text, initial_indent = ' * ', subsequent_indent = ' * '))
-  print(' */')
-
-
-def makeTestVectors():
-  comment("""Test vectors for our ed25519 implementation and related
-             functions. These were automatically generated by the
-             ed25519_exts_ref.py script.""", initial = '/*')
-
-  comment("""Secret key seeds used as inputs for the ed25519 test vectors.
-             Randomly generated. """)
-  secretKeys = [bytes.fromhex(r) for r in RAND_INPUTS]
-  writeArray('SECRET_KEYS', secretKeys)
-
-  comment("""Secret ed25519 keys after expansion from seeds. This is how Tor
-             represents them internally.""")
-  expandedSecretKeys = [expandSK(sk) for sk in secretKeys]
-  writeArray('EXPANDED_SECRET_KEYS', expandedSecretKeys)
-
-  comment('Public keys derived from the above secret keys')
-  publicKeys = [slow_ed25519.publickey(sk) for sk in secretKeys]
-  writeArray('PUBLIC_KEYS', publicKeys)
-
-  comment('Parameters used for key blinding tests. Randomly generated.')
-  blindingParams = [binascii.a2b_hex(r) for r in BLINDING_PARAMS]
-  writeArray('BLINDING_PARAMS', blindingParams)
-
-  comment("""Blinded secret keys for testing key blinding.  The nth blinded
-             key corresponds to the nth secret key blidned with the nth
-             blinding parameter.""")
-
-  writeArray('BLINDED_SECRET_KEYS', (blindESK(expandSK(sk), bp) for sk, bp in zip(secretKeys, blindingParams)))
-
-  comment("""Blinded public keys for testing key blinding.  The nth blinded
-             key corresponds to the nth public key blidned with the nth
-             blinding parameter.""")
-
-  writeArray('BLINDED_PUBLIC_KEYS', (blindPK(pk, bp) for pk, bp in zip(publicKeys, blindingParams)))
-
-  comment("""Signatures of the public keys, made with their corresponding
-             secret keys.""")
-  writeArray('SELF_SIGNATURES', (slow_ed25519.signature(pk, sk, pk) for pk, sk in zip(publicKeys, secretKeys)))
-
-
-if __name__ == '__main__':
-  import sys
-
-  if len(sys.argv) == 1 or sys.argv[1] not in ('SelfTest', 'MakeVectors'):
-    print ("You should specify one of 'SelfTest' or 'MakeVectors'")
-    sys.exit(1)
-
-  if sys.argv[1] == 'SelfTest':
-    unittest.main()
-  else:
-    makeTestVectors()
diff --git a/stem/descriptor/hsv3_crypto.py b/stem/descriptor/hsv3_crypto.py
index 5bce5dcf..80759aa2 100644
--- a/stem/descriptor/hsv3_crypto.py
+++ b/stem/descriptor/hsv3_crypto.py
@@ -2,8 +2,7 @@ import hashlib
 import struct
 import os
 
-import stem.descriptor.ed25519_exts_ref
-import stem.descriptor.slow_ed25519
+from stem.descriptor import slow_ed25519
 
 
 """
@@ -21,6 +20,39 @@ certificate module.
 """
 
 
+def blindESK(esk, param):
+  mult = 2 ** (slow_ed25519.b - 2) + sum(2 ** i * slow_ed25519.bit(param, i) for i in range(3, slow_ed25519.b - 2))
+  s = slow_ed25519.decodeint(esk[:32])
+  s_prime = (s * mult) % slow_ed25519.l
+  k = esk[32:]
+  assert(len(k) == 32)
+  k_prime = slow_ed25519.H(b'Derive temporary signing key hash input' + k)[:32]
+  return slow_ed25519.encodeint(s_prime) + k_prime
+
+
+def blindPK(pk, param):
+  mult = 2 ** (slow_ed25519.b - 2) + sum(2 ** i * slow_ed25519.bit(param, i) for i in range(3, slow_ed25519.b - 2))
+  P = slow_ed25519.decodepoint(pk)
+  return slow_ed25519.encodepoint(slow_ed25519.scalarmult(P, mult))
+
+
+def expandSK(sk):
+  h = slow_ed25519.H(sk)
+  a = 2 ** (slow_ed25519.b - 2) + sum(2 ** i * slow_ed25519.bit(h, i) for i in range(3, slow_ed25519.b - 2))
+  k = b''.join([h[i:i + 1] for i in range(slow_ed25519.b // 8, slow_ed25519.b // 4)])
+  assert len(k) == 32
+  return slow_ed25519.encodeint(a) + k
+
+
+def signatureWithESK(m, h, pk):
+  a = slow_ed25519.decodeint(h[:32])
+  r = slow_ed25519.Hint(b''.join([h[i:i + 1] for i in range(slow_ed25519.b // 8, slow_ed25519.b // 4)]) + m)
+  R = slow_ed25519.scalarmult(slow_ed25519.B, r)
+  S = (r + slow_ed25519.Hint(slow_ed25519.encodepoint(R) + pk + m) * a) % slow_ed25519.l
+
+  return slow_ed25519.encodepoint(R) + slow_ed25519.encodeint(S)
+
+
 class HSv3PrivateBlindedKey(object):
   def __init__(self, hazmat_private_key, blinding_param):
     from cryptography.hazmat.primitives import serialization
@@ -28,14 +60,14 @@ class HSv3PrivateBlindedKey(object):
     secret_seed = hazmat_private_key.private_bytes(encoding = serialization.Encoding.Raw, format = serialization.PrivateFormat.Raw, encryption_algorithm = serialization.NoEncryption())
     assert(len(secret_seed) == 32)
 
-    expanded_identity_priv_key = stem.descriptor.ed25519_exts_ref.expandSK(secret_seed)
-    identity_public_key = stem.descriptor.slow_ed25519.publickey(secret_seed)
+    expanded_identity_priv_key = expandSK(secret_seed)
+    identity_public_key = slow_ed25519.publickey(secret_seed)
 
-    self.blinded_secret_key = stem.descriptor.ed25519_exts_ref.blindESK(expanded_identity_priv_key, blinding_param)
-    self.blinded_pubkey = stem.descriptor.ed25519_exts_ref.blindPK(identity_public_key, blinding_param)
+    self.blinded_secret_key = blindESK(expanded_identity_priv_key, blinding_param)
+    self.blinded_pubkey = blindPK(identity_public_key, blinding_param)
 
   def sign(self, msg):
-    return stem.descriptor.ed25519_exts_ref.signatureWithESK(msg, self.blinded_secret_key, self.blinded_pubkey)
+    return signatureWithESK(msg, self.blinded_secret_key, self.blinded_pubkey)
 
 
 """





More information about the tor-commits mailing list