/usr/lib/python2.7/dist-packages/spake2/groups.py is in python-spake2 0.7-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | from __future__ import division
import hashlib
from hkdf import Hkdf
from .six import integer_types
from .util import (size_bits, size_bytes, unbiased_randrange,
bytes_to_number, number_to_bytes)
"""Interface specification for a Group.
A cyclic abelian group, in the mathematical sense, is a collection of
'elements' and a (binary) operation that takes two elements and produces a
third. It has the following additional properties:
* there is an 'identity' element named 0, and X+0=X
* there is a distinguished 'generator' element G
* adding G to 0 'n' times is called scalar multiplication: Y=n*G
* this addition loops around after 'q' times, called the 'order'
* so (n+k*q)*X = n*X
* scalar multiplication is associative, n*(X+Y) = n*X+n*Y
* 'scalar division' is really multiplying by (q-n)
A 'scalar' is an integer in [0,q-1] inclusive. You can add scalars to each
other, invert them, and multiply them by elements. There is a one-to-one
mapping between scalars and elements. It is trivial to go from a scalar to an
element, but hard (in the cryptographic sense) to go from element to scalar.
You can ask for a random scalar, and you can convert scalars to bytes and
back again.
The form of an 'element' depends upon the group (there are integer-element
groups, and ECC groups). You can add elements together, invert them
(scalarmult by -1), and subtract them (invert then add). You can ask for a
random element (found by choosing a random scalar, then multiplying). You can
convert elements to bytes and back.
There is a distinguished element called 'Base', which is the generator
(or 'base point' in ECC groups).
Two final operations are provided. The first produces an 'arbitrary element'
from a seed. This is somewhat like a random element, but with the additional
important property that nobody knows what the corresponding scalar is. The
second takes a password (an arbitrary bytestring) and produces a scalar.
The functions that produce random scalars/elements require an entropy
function, which is expected to behave like os.urandom. The only reason to not
use os.urandom is for deterministic unit tests.
g = I2048Group # or Ed25519Group
s = g.random_scalar(entropy_f)
s = g.bytes_to_scalar(bytes)
bytes = g.scalar_to_bytes()
s = g.password_to_scalar(password)
e = g.bytes_to_element(bytes)
e = g.arbitrary_element(seed)
e = g.Base # this is an Element too, with all the methods below
e3 = e1.add(e2)
e3 = e1.scalarmult(s) # takes int, positive or negative
bytes = e.to_bytes()
# equality tests work: e1 == e2, e1 != e2
"""
def expand_password(data, num_bytes):
h = Hkdf(salt=b"", input_key_material=data, hash=hashlib.sha256)
info = b"SPAKE2 pw"
return h.expand(info, num_bytes)
def password_to_scalar(pw, scalar_size_bytes, q):
assert isinstance(pw, bytes)
# the oversized hash reduces bias in the result, so
# uniformly-random passwords give nearly-uniform scalars
oversized = expand_password(pw, scalar_size_bytes+16)
assert len(oversized) >= scalar_size_bytes
i = bytes_to_number(oversized)
return i % q
def expand_arbitrary_element_seed(data, num_bytes):
h = Hkdf(salt=b"", input_key_material=data, hash=hashlib.sha256)
info = b"SPAKE2 arbitrary element"
return h.expand(info, num_bytes)
class _Element:
def __init__(self, group, e):
self._group = group
self._e = e
def add(self, other):
return self._group._add(self, other)
def scalarmult(self, s):
return self._group._scalarmult(self, s)
def to_bytes(self):
return self._group._element_to_bytes(self)
class IntegerGroup:
def __init__(self, p, q, g):
self.q = q # the subgroup order, used for scalars
self.scalar_size_bytes = size_bytes(self.q)
_s = self.scalar_to_bytes(self.password_to_scalar(b""))
assert isinstance(_s, bytes)
assert len(_s) >= self.scalar_size_bytes
self.Zero = _Element(self, 1)
self.Base = _Element(self, g) # generator of the subgroup
# these are the public system parameters
self.p = p # the field size
self.element_size_bits = size_bits(self.p)
self.element_size_bytes = size_bytes(self.p)
# double-check that the generator has the right order
assert pow(g, self.q, self.p) == 1
def order(self):
return self.q
def random_scalar(self, entropy_f):
return unbiased_randrange(0, self.q, entropy_f)
def scalar_to_bytes(self, i):
# both for hashing into transcript, and save/restore of
# intermediate state
assert isinstance(i, integer_types)
assert 0 <= 0 < self.q
return number_to_bytes(i, self.q)
def bytes_to_scalar(self, b):
# for restore of intermediate state
assert isinstance(b, bytes)
assert len(b) == self.scalar_size_bytes
i = bytes_to_number(b)
assert 0 <= i < self.q, (0, i, self.q)
return i
def password_to_scalar(self, pw):
return password_to_scalar(pw, self.scalar_size_bytes, self.q)
def arbitrary_element(self, seed):
# we do *not* know the discrete log of this one. Nobody should.
assert isinstance(seed, bytes)
processed_seed = expand_arbitrary_element_seed(seed,
self.element_size_bytes)
assert isinstance(processed_seed, bytes)
assert len(processed_seed) == self.element_size_bytes
# The larger (non-prime-order) group (Zp*) we're using has order
# p-1. The smaller (prime-order) subgroup has order q. Subgroup
# orders always divide the larger group order, so r*q=p-1 for
# some integer r. If h is an arbitrary element of the larger
# group Zp*, then e=h^r will be an element of the subgroup. If h
# is selected uniformly at random, so will e, and nobody will
# know its discrete log. We can enforce this for pre-selected
# parameters by choosing h as the output of a hash function.
r = (self.p - 1) // self.q
assert r * self.q == self.p - 1
h = bytes_to_number(processed_seed) % self.p
element = _Element(self, pow(h, r, self.p))
assert self._is_member(element)
return element
def _is_member(self, e):
if not e._group is self:
return False
if pow(e._e, self.q, self.p) == 1:
return True
return False
def _element_to_bytes(self, e):
# for sending to other side, and hashing into transcript
assert isinstance(e, _Element)
assert e._group is self
return number_to_bytes(e._e, self.p)
def bytes_to_element(self, b):
# for receiving from other side: test group membership here
assert isinstance(b, bytes)
assert len(b) == self.element_size_bytes
i = bytes_to_number(b)
if i <= 0 or i >= self.p: # Zp* excludes 0
raise ValueError("alleged element not in the field")
e = _Element(self, i)
if not self._is_member(e):
raise ValueError("element is not in the right group")
return e
def _scalarmult(self, e1, i):
if not isinstance(e1, _Element):
raise TypeError("E*N requires E be an element")
assert e1._group is self
if not isinstance(i, integer_types):
raise TypeError("E*N requires N be a scalar")
return _Element(self, pow(e1._e, i % self.q, self.p))
def _add(self, e1, e2):
if not isinstance(e1, _Element):
raise TypeError("E*N requires E be an element")
assert e1._group is self
if not isinstance(e2, _Element):
raise TypeError("E*N requires E be an element")
assert e2._group is self
return _Element(self, (e1._e * e2._e) % self.p)
# This 1024-bit group originally came from the J-PAKE demo code,
# http://haofeng66.googlepages.com/JPAKEDemo.java . That java code
# recommended these 2048 and 3072 bit groups from this NIST document:
# http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf
# L=1024, N=160
I1024 = IntegerGroup(
p=0xE0A67598CD1B763BC98C8ABB333E5DDA0CD3AA0E5E1FB5BA8A7B4EABC10BA338FAE06DD4B90FDA70D7CF0CB0C638BE3341BEC0AF8A7330A3307DED2299A0EE606DF035177A239C34A912C202AA5F83B9C4A7CF0235B5316BFC6EFB9A248411258B30B839AF172440F32563056CB67A861158DDD90E6A894C72A5BBEF9E286C6B,
q=0xE950511EAB424B9A19A2AEB4E159B7844C589C4F,
g=0xD29D5121B0423C2769AB21843E5A3240FF19CACC792264E3BB6BE4F78EDD1B15C4DFF7F1D905431F0AB16790E1F773B5CE01C804E509066A9919F5195F4ABC58189FD9FF987389CB5BEDF21B4DAB4F8B76A055FFE2770988FE2EC2DE11AD92219F0B351869AC24DA3D7BA87011A701CE8EE7BFE49486ED4527B7186CA4610A75,
)
# L=2048, N=224
I2048 = IntegerGroup(
p=0xC196BA05AC29E1F9C3C72D56DFFC6154A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A067CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE428782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE619ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD92D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BFFAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E5320121496DC65B3930E38047294FF877831A16D5228418DE8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A0402A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83,
q=0x90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D,
g=0xA59A749A11242C58C894E9E5A91804E8FA0AC64B56288F8D47D51B1EDC4D65444FECA0111D78F35FC9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E5048B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B6E770409494B7FEE1DBB1E4B2BC2A53D4F893D418B7159592E4FFFDF6969E91D770DAEBD0B5CB14C00AD68EC7DC1E5745EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDFD049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E695515B05BD412F5B8C2F4C77EE10DA48ABD53F5DD498927EE7B692BBBCDA2FB23A516C5B4533D73980B2A3B60E384ED200AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085,
)
# L=3072, N=256
I3072 = IntegerGroup(
p=0x90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA129F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D15939487E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773EBE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941DAD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504FB0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328EC22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73,
q=0xCFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D,
g=0x5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B39AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B,
)
|