210 lines
6.4 KiB
Python
210 lines
6.4 KiB
Python
|
#!/usr/bin/env python
|
|||
|
# coding=utf-8
|
|||
|
# The MIT License (MIT)
|
|||
|
#
|
|||
|
# Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
|
|||
|
#
|
|||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|||
|
# of this software and associated documentation files (the "Software"), to deal
|
|||
|
# in the Software without restriction, including without limitation the rights
|
|||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||
|
# copies of the Software, and to permit persons to whom the Software is
|
|||
|
# furnished to do so, subject to the following conditions:
|
|||
|
#
|
|||
|
# The above copyright notice and this permission notice shall be included in all
|
|||
|
# copies or substantial portions of the Software.
|
|||
|
#
|
|||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||
|
# SOFTWARE.
|
|||
|
|
|||
|
import StringIO
|
|||
|
import subprocess
|
|||
|
|
|||
|
# Base field Z_p
|
|||
|
p = 2**255 - 19
|
|||
|
|
|||
|
def modp_inv(x):
|
|||
|
return pow(x, p-2, p)
|
|||
|
|
|||
|
# Compute corresponding x-coordinate, with low bit corresponding to
|
|||
|
# sign, or return None on failure
|
|||
|
def recover_x(y, sign):
|
|||
|
if y >= p:
|
|||
|
return None
|
|||
|
x2 = (y*y-1) * modp_inv(d*y*y+1)
|
|||
|
if x2 == 0:
|
|||
|
if sign:
|
|||
|
return None
|
|||
|
else:
|
|||
|
return 0
|
|||
|
|
|||
|
# Compute square root of x2
|
|||
|
x = pow(x2, (p+3) // 8, p)
|
|||
|
if (x*x - x2) % p != 0:
|
|||
|
x = x * modp_sqrt_m1 % p
|
|||
|
if (x*x - x2) % p != 0:
|
|||
|
return None
|
|||
|
|
|||
|
if (x & 1) != sign:
|
|||
|
x = p - x
|
|||
|
return x
|
|||
|
|
|||
|
# Curve constant
|
|||
|
d = -121665 * modp_inv(121666) % p
|
|||
|
|
|||
|
# Base point
|
|||
|
g_y = 4 * modp_inv(5) % p
|
|||
|
g_x = recover_x(g_y, 0)
|
|||
|
|
|||
|
# Points are represented as affine tuples (x, y).
|
|||
|
|
|||
|
def point_add(P, Q):
|
|||
|
x1, y1 = P
|
|||
|
x2, y2 = Q
|
|||
|
x3 = ((x1*y2 + y1*x2) * modp_inv(1 + d*x1*x2*y1*y2)) % p
|
|||
|
y3 = ((y1*y2 + x1*x2) * modp_inv(1 - d*x1*x2*y1*y2)) % p
|
|||
|
return (x3, y3)
|
|||
|
|
|||
|
# Computes Q = s * P
|
|||
|
def point_mul(s, P):
|
|||
|
Q = (0, 1) # Neutral element
|
|||
|
while s > 0:
|
|||
|
if s & 1:
|
|||
|
Q = point_add(Q, P)
|
|||
|
P = point_add(P, P)
|
|||
|
s >>= 1
|
|||
|
return Q
|
|||
|
|
|||
|
def to_bytes(x):
|
|||
|
ret = bytearray(32)
|
|||
|
for i in range(len(ret)):
|
|||
|
ret[i] = x % 256
|
|||
|
x >>= 8
|
|||
|
assert x == 0
|
|||
|
return ret
|
|||
|
|
|||
|
def to_ge_precomp(P):
|
|||
|
# typedef struct {
|
|||
|
# fe_loose yplusx;
|
|||
|
# fe_loose yminusx;
|
|||
|
# fe_loose xy2d;
|
|||
|
# } ge_precomp;
|
|||
|
x, y = P
|
|||
|
return ((y + x) % p, (y - x) % p, (x * y * 2 * d) % p)
|
|||
|
|
|||
|
def to_base_25_5(x):
|
|||
|
limbs = (26, 25, 26, 25, 26, 25, 26, 25, 26, 25)
|
|||
|
ret = []
|
|||
|
for l in limbs:
|
|||
|
ret.append(x & ((1<<l) - 1))
|
|||
|
x >>= l
|
|||
|
assert x == 0
|
|||
|
return ret
|
|||
|
|
|||
|
def main():
|
|||
|
small_precomp = bytearray()
|
|||
|
for i in range(1, 16):
|
|||
|
s = (i&1) | ((i&2) << (64-1)) | ((i&4) << (128-2)) | ((i&8) << (192-3))
|
|||
|
P = point_mul(s, (g_x, g_y))
|
|||
|
small_precomp += to_bytes(P[0])
|
|||
|
small_precomp += to_bytes(P[1])
|
|||
|
|
|||
|
large_precomp = []
|
|||
|
for i in range(32):
|
|||
|
large_precomp.append([])
|
|||
|
for j in range(8):
|
|||
|
P = point_mul((j + 1) << (i * 8), (g_x, g_y))
|
|||
|
large_precomp[-1].append(to_ge_precomp(P))
|
|||
|
|
|||
|
bi_precomp = []
|
|||
|
for i in range(8):
|
|||
|
P = point_mul(2*i + 1, (g_x, g_y))
|
|||
|
bi_precomp.append(to_ge_precomp(P))
|
|||
|
|
|||
|
|
|||
|
buf = StringIO.StringIO()
|
|||
|
buf.write("""// The MIT License (MIT)
|
|||
|
//
|
|||
|
// Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
|
|||
|
//
|
|||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|||
|
// of this software and associated documentation files (the "Software"), to deal
|
|||
|
// in the Software without restriction, including without limitation the rights
|
|||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||
|
// copies of the Software, and to permit persons to whom the Software is
|
|||
|
// furnished to do so, subject to the following conditions:
|
|||
|
//
|
|||
|
// The above copyright notice and this permission notice shall be included in
|
|||
|
// all copies or substantial portions of the Software.
|
|||
|
//
|
|||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||
|
// SOFTWARE.
|
|||
|
|
|||
|
// This file is generated from
|
|||
|
// ./make_curve25519_tables.py > curve25519_tables.h
|
|||
|
|
|||
|
|
|||
|
#if defined(OPENSSL_SMALL)
|
|||
|
|
|||
|
// This block of code replaces the standard base-point table with a much smaller
|
|||
|
// one. The standard table is 30,720 bytes while this one is just 960.
|
|||
|
//
|
|||
|
// This table contains 15 pairs of group elements, (x, y), where each field
|
|||
|
// element is serialised with |fe_tobytes|. If |i| is the index of the group
|
|||
|
// element then consider i+1 as a four-bit number: (i₀, i₁, i₂, i₃) (where i₀
|
|||
|
// is the most significant bit). The value of the group element is then:
|
|||
|
// (i₀×2^192 + i₁×2^128 + i₂×2^64 + i₃)G, where G is the generator.
|
|||
|
static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = {""")
|
|||
|
for i, b in enumerate(small_precomp):
|
|||
|
buf.write("0x%02x, " % b)
|
|||
|
buf.write("""
|
|||
|
};
|
|||
|
|
|||
|
#else
|
|||
|
|
|||
|
// k25519Precomp[i][j] = (j+1)*256^i*B
|
|||
|
static const ge_precomp k25519Precomp[32][8] = {
|
|||
|
""")
|
|||
|
for child in large_precomp:
|
|||
|
buf.write("{\n")
|
|||
|
for val in child:
|
|||
|
buf.write("{\n")
|
|||
|
for term in val:
|
|||
|
buf.write("{{")
|
|||
|
buf.write(", ".join(map(str, to_base_25_5(term))))
|
|||
|
buf.write("}},\n")
|
|||
|
buf.write("},\n")
|
|||
|
buf.write("},\n")
|
|||
|
buf.write("""};
|
|||
|
|
|||
|
#endif // OPENSSL_SMALL
|
|||
|
|
|||
|
// Bi[i] = (2*i+1)*B
|
|||
|
static const ge_precomp Bi[8] = {
|
|||
|
""")
|
|||
|
for val in bi_precomp:
|
|||
|
buf.write("{\n")
|
|||
|
for term in val:
|
|||
|
buf.write("{{")
|
|||
|
buf.write(", ".join(map(str, to_base_25_5(term))))
|
|||
|
buf.write("}},\n")
|
|||
|
buf.write("},\n")
|
|||
|
buf.write("""};
|
|||
|
""")
|
|||
|
|
|||
|
proc = subprocess.Popen(["clang-format"], stdin=subprocess.PIPE)
|
|||
|
proc.communicate(buf.getvalue())
|
|||
|
|
|||
|
if __name__ == "__main__":
|
|||
|
main()
|