135 lines
4.0 KiB
Python
135 lines
4.0 KiB
Python
#!/usr/bin/sage
|
|
# vim: syntax=python
|
|
# vim: set ts=2 sw=2 et:
|
|
|
|
# Constantine
|
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
|
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
|
# Licensed and distributed under either of
|
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
# ############################################################
|
|
#
|
|
# Pairing constants
|
|
#
|
|
# ############################################################
|
|
|
|
# Imports
|
|
# ---------------------------------------------------------
|
|
|
|
import os
|
|
import inspect, textwrap
|
|
|
|
# Working directory
|
|
# ---------------------------------------------------------
|
|
|
|
os.chdir(os.path.dirname(__file__))
|
|
|
|
# Sage imports
|
|
# ---------------------------------------------------------
|
|
# Accelerate arithmetic by accepting probabilistic proofs
|
|
from sage.structure.proof.all import arithmetic
|
|
arithmetic(False)
|
|
|
|
load('curves.sage')
|
|
|
|
# Utilities
|
|
# ---------------------------------------------------------
|
|
|
|
# Code generators
|
|
# ---------------------------------------------------------
|
|
|
|
def genAteParam(curve_name, curve_config):
|
|
u = curve_config[curve_name]['field']['param']
|
|
family = curve_config[curve_name]['field']['family']
|
|
if family == 'BLS12':
|
|
ate_param = u
|
|
ate_comment = ' # BLS12 Miller loop is parametrized by u\n'
|
|
elif family == 'BN':
|
|
ate_param = 6*u+2
|
|
ate_comment = ' # BN Miller loop is parametrized by 6u+2\n'
|
|
else:
|
|
raise ValueError(f'family: {family} is not implemented')
|
|
|
|
buf = '# The bit count must be exact for the Miller loop\n'
|
|
buf += f'const {curve_name}_pairing_ate_param* = block:\n'
|
|
buf += ate_comment
|
|
|
|
ate_bits = int(ate_param).bit_length()
|
|
naf_bits = int(3*ate_param).bit_length() - ate_bits
|
|
|
|
buf += f' # +{naf_bits} to bitlength so that we can mul by 3 for NAF encoding\n'
|
|
buf += f' BigInt[{ate_bits}+{naf_bits}].fromHex"0x{Integer(abs(ate_param)).hex()}"\n\n'
|
|
|
|
buf += f'const {curve_name}_pairing_ate_param_isNeg* = {"true" if ate_param < 0 else "false"}'
|
|
|
|
return buf
|
|
|
|
def genFinalExp(curve_name, curve_config):
|
|
p = curve_config[curve_name]['field']['modulus']
|
|
r = curve_config[curve_name]['field']['order']
|
|
k = curve_config[curve_name]['tower']['embedding_degree']
|
|
family = curve_config[curve_name]['field']['family']
|
|
|
|
fexp = (p^k - 1)//r
|
|
if family == 'BLS12':
|
|
fexp *= 3
|
|
|
|
buf = f'const {curve_name}_pairing_finalexponent* = block:\n'
|
|
buf += f' # (p^{k} - 1) / r' + (' * 3' if family == 'BLS12' else '')
|
|
buf += '\n'
|
|
buf += f' BigInt[{int(fexp).bit_length()}].fromHex"0x{Integer(fexp).hex()}"'
|
|
|
|
return buf
|
|
|
|
# CLI
|
|
# ---------------------------------------------------------
|
|
|
|
if __name__ == "__main__":
|
|
# Usage
|
|
# BLS12-381
|
|
# sage sage/derive_pairing.sage BLS12_381
|
|
|
|
from argparse import ArgumentParser
|
|
|
|
parser = ArgumentParser()
|
|
parser.add_argument("curve",nargs="+")
|
|
args = parser.parse_args()
|
|
|
|
curve = args.curve[0]
|
|
|
|
if curve not in Curves:
|
|
raise ValueError(
|
|
curve +
|
|
' is not one of the available curves: ' +
|
|
str(Curves.keys())
|
|
)
|
|
else:
|
|
ate = genAteParam(curve, Curves)
|
|
fexp = genFinalExp(curve, Curves)
|
|
|
|
with open(f'{curve.lower()}_pairing.nim', 'w') as f:
|
|
f.write(copyright())
|
|
f.write('\n\n')
|
|
f.write(inspect.cleandoc("""
|
|
import
|
|
../config/[curves, type_bigint],
|
|
../io/io_bigints
|
|
|
|
# Slow generic implementation
|
|
# ------------------------------------------------------------
|
|
"""))
|
|
f.write('\n\n')
|
|
f.write(ate)
|
|
f.write('\n\n')
|
|
f.write(fexp)
|
|
f.write('\n\n')
|
|
f.write(inspect.cleandoc("""
|
|
# Addition chain
|
|
# ------------------------------------------------------------
|
|
"""))
|
|
|
|
print(f'Successfully created {curve}_pairing.nim')
|