mirror of https://github.com/nucypher/pyUmbral.git
Style fixes + pylint config
parent
9570035582
commit
48c3441344
|
@ -0,0 +1,254 @@
|
|||
[MASTER]
|
||||
|
||||
# Specify a configuration file.
|
||||
#rcfile=
|
||||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
#init-hook=
|
||||
|
||||
# Profiled execution.
|
||||
profile=no
|
||||
|
||||
# Add files or directories to the blacklist. They should be base names, not
|
||||
# paths.
|
||||
ignore=CVS
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# List of plugins (as comma separated values of python modules names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time.
|
||||
#enable=
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once).
|
||||
|
||||
# disable warnings:
|
||||
# - C0103 (we have a lot of short names)
|
||||
# - C0114 (flat package, no need for module docstrings)
|
||||
# - C0116 (we have many short self-documenting functions)
|
||||
disable=C0103,C0114,C0116
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, msvs
|
||||
# (visual studio) and html
|
||||
output-format=text
|
||||
|
||||
# Include message's id in output
|
||||
include-ids=no
|
||||
|
||||
# Put messages in a separate file for each module / package specified on the
|
||||
# command line instead of printing them on stdout. Reports (if any) will be
|
||||
# written in a file name "pylint_global.[txt|html]".
|
||||
files-output=no
|
||||
|
||||
# Tells whether to display a full report or only the messages
|
||||
reports=yes
|
||||
|
||||
# Python expression which should return a note less than 10 (10 is the highest
|
||||
# note). You have access to the variables errors warning, statement which
|
||||
# respectively contain the number of errors / warnings messages and the total
|
||||
# number of statements analyzed. This is used by the global evaluation report
|
||||
# (RP0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Add a comment according to your evaluation note. This is used by the global
|
||||
# evaluation report (RP0004).
|
||||
comment=no
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Required attributes for module, separated by a comma
|
||||
required-attributes=
|
||||
|
||||
# List of builtins function names that should not be used, separated by a comma
|
||||
bad-functions=map,filter,apply,input
|
||||
|
||||
# Regular expression which should only match correct module names
|
||||
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||
|
||||
# Regular expression which should only match correct module level names
|
||||
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
||||
|
||||
# Regular expression which should only match correct class names
|
||||
class-rgx=[A-Z_][a-zA-Z0-9]+$
|
||||
|
||||
# Regular expression which should only match correct function names
|
||||
function-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct method names
|
||||
method-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct instance attribute names
|
||||
attr-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct argument names
|
||||
argument-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct variable names
|
||||
variable-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct list comprehension /
|
||||
# generator expression variable names
|
||||
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma
|
||||
good-names=i,j,k,ex,Run,_
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma
|
||||
bad-names=foo,bar,baz,toto,tutu,tata
|
||||
|
||||
# Regular expression which should only match functions or classes name which do
|
||||
# not require a docstring
|
||||
no-docstring-rgx=__.*__
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=100
|
||||
|
||||
# Maximum number of lines in a module
|
||||
max-module-lines=1000
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,XXX,TODO
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
# Ignore comments when computing similarities.
|
||||
ignore-comments=yes
|
||||
|
||||
# Ignore docstrings when computing similarities.
|
||||
ignore-docstrings=yes
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# List of classes names for which member attributes should not be checked
|
||||
# (useful for classes with attributes dynamically set).
|
||||
ignored-classes=SQLObject
|
||||
|
||||
# When zope mode is activated, add a predefined set of Zope acquired attributes
|
||||
# to generated-members.
|
||||
zope=no
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E0201 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=REQUEST,acl_users,aq_parent
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# A regular expression matching the beginning of the name of dummy variables
|
||||
# (i.e. not used).
|
||||
dummy-variables-rgx=_|dummy
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid to define new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# List of interface methods to ignore, separated by a comma. This is used for
|
||||
# instance to not check methods defines in Zope's Interface base class.
|
||||
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,__new__,setUp
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
|
||||
[DESIGN]
|
||||
|
||||
# Maximum number of arguments for function / method
|
||||
max-args=5
|
||||
|
||||
# Argument names that match this expression will be ignored. Default to name
|
||||
# with leading underscore
|
||||
ignored-argument-names=_.*
|
||||
|
||||
# Maximum number of locals for function / method body
|
||||
max-locals=20
|
||||
|
||||
# Maximum number of return / yield for function / method body
|
||||
max-returns=6
|
||||
|
||||
# Maximum number of branch for function / method body
|
||||
max-branchs=12
|
||||
|
||||
# Maximum number of statements in function / method body
|
||||
max-statements=50
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=7
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=2
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma
|
||||
deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
|
||||
|
||||
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||
# given file (report RP0402 must not be disabled)
|
||||
import-graph=
|
||||
|
||||
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
ext-import-graph=
|
||||
|
||||
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
int-import-graph=
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "Exception"
|
||||
overgeneral-exceptions=Exception
|
|
@ -1,7 +1,8 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__all__ = [
|
||||
"__title__", "__summary__", "__version__", "__author__", "__email__", "__license__", "__copyright__", "__url__"
|
||||
"__title__", "__summary__", "__version__", "__author__",
|
||||
"__email__", "__license__", "__copyright__", "__url__"
|
||||
]
|
||||
|
||||
__title__ = "umbral"
|
||||
|
|
|
@ -5,7 +5,6 @@ from .curve_scalar import CurveScalar
|
|||
from .errors import GenericError
|
||||
from .hashing import hash_capsule_points, hash_to_polynomial_arg, hash_to_shared_secret
|
||||
from .keys import PublicKey, SecretKey
|
||||
from .params import PARAMETERS
|
||||
from .serializable import Serializable
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from .capsule_frag import CapsuleFrag
|
||||
|
@ -13,10 +12,10 @@ if TYPE_CHECKING: # pragma: no cover
|
|||
|
||||
def lambda_coeff(xs: Sequence[CurveScalar], i: int) -> CurveScalar:
|
||||
res = CurveScalar.one()
|
||||
for j in range(len(xs)):
|
||||
for j, xs_j in enumerate(xs):
|
||||
if j != i:
|
||||
inv_diff = (xs[j] - xs[i]).invert()
|
||||
res = (res * xs[j]) * inv_diff
|
||||
inv_diff = (xs_j - xs[i]).invert()
|
||||
res = (res * xs_j) * inv_diff
|
||||
return res
|
||||
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from typing import Sequence, Optional, Tuple
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from .capsule import Capsule
|
||||
from .curve_point import CurvePoint
|
||||
from .curve_scalar import CurveScalar
|
||||
from .errors import VerificationError
|
||||
from .hashing import Hash, hash_to_cfrag_verification, kfrag_signature_message
|
||||
from .keys import PublicKey, SecretKey
|
||||
from .hashing import hash_to_cfrag_verification, kfrag_signature_message
|
||||
from .keys import PublicKey
|
||||
from .key_frag import KeyFrag, KeyFragID
|
||||
from .params import PARAMETERS
|
||||
from .serializable import Serializable
|
||||
|
@ -171,7 +171,6 @@ class CapsuleFrag(Serializable):
|
|||
``metadata`` should coincide with the one given to :py:func:`reencrypt`.
|
||||
"""
|
||||
|
||||
|
||||
params = PARAMETERS
|
||||
|
||||
# Here are the formulaic constituents shared with
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Optional, Tuple
|
||||
from typing import Tuple
|
||||
|
||||
from . import openssl
|
||||
from .curve import CURVE
|
||||
|
@ -80,7 +80,7 @@ class CurvePoint(Serializable):
|
|||
"""
|
||||
Performs subtraction by adding the inverse of the `other` to the point.
|
||||
"""
|
||||
return (self + (-other))
|
||||
return self + (-other)
|
||||
|
||||
def __neg__(self) -> 'CurvePoint':
|
||||
"""
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import TYPE_CHECKING, Optional, Union, Tuple
|
||||
from typing import TYPE_CHECKING, Union, Tuple
|
||||
|
||||
from . import openssl
|
||||
from .curve import CURVE
|
||||
|
@ -66,7 +66,7 @@ class CurveScalar(Serializable):
|
|||
"""
|
||||
Compares the two BIGNUMS or int.
|
||||
"""
|
||||
if type(other) == int:
|
||||
if isinstance(other, int):
|
||||
other = CurveScalar.from_int(other)
|
||||
return openssl.bn_cmp(self._backend_bignum, other._backend_bignum) == 0
|
||||
|
||||
|
@ -83,7 +83,9 @@ class CurveScalar(Serializable):
|
|||
"""
|
||||
if isinstance(other, int):
|
||||
other = CurveScalar.from_int(other)
|
||||
return CurveScalar(openssl.bn_mul(self._backend_bignum, other._backend_bignum, CURVE.bn_order))
|
||||
return CurveScalar(openssl.bn_mul(self._backend_bignum,
|
||||
other._backend_bignum,
|
||||
CURVE.bn_order))
|
||||
|
||||
def __add__(self, other : Union[int, 'CurveScalar']) -> 'CurveScalar':
|
||||
"""
|
||||
|
@ -91,7 +93,9 @@ class CurveScalar(Serializable):
|
|||
"""
|
||||
if isinstance(other, int):
|
||||
other = CurveScalar.from_int(other)
|
||||
return CurveScalar(openssl.bn_add(self._backend_bignum, other._backend_bignum, CURVE.bn_order))
|
||||
return CurveScalar(openssl.bn_add(self._backend_bignum,
|
||||
other._backend_bignum,
|
||||
CURVE.bn_order))
|
||||
|
||||
def __sub__(self, other : Union[int, 'CurveScalar']) -> 'CurveScalar':
|
||||
"""
|
||||
|
@ -99,7 +103,9 @@ class CurveScalar(Serializable):
|
|||
"""
|
||||
if isinstance(other, int):
|
||||
other = CurveScalar.from_int(other)
|
||||
return CurveScalar(openssl.bn_sub(self._backend_bignum, other._backend_bignum, CURVE.bn_order))
|
||||
return CurveScalar(openssl.bn_sub(self._backend_bignum,
|
||||
other._backend_bignum,
|
||||
CURVE.bn_order))
|
||||
|
||||
def invert(self) -> 'CurveScalar':
|
||||
"""
|
||||
|
|
|
@ -52,18 +52,18 @@ class DEM:
|
|||
def decrypt(self, nonce_and_ciphertext: bytes, authenticated_data: bytes = b"") -> bytes:
|
||||
|
||||
if len(nonce_and_ciphertext) < self.NONCE_SIZE:
|
||||
raise ValueError(f"The ciphertext must include the nonce")
|
||||
raise ValueError("The ciphertext must include the nonce")
|
||||
|
||||
nonce = nonce_and_ciphertext[:self.NONCE_SIZE]
|
||||
ciphertext = nonce_and_ciphertext[self.NONCE_SIZE:]
|
||||
|
||||
# Prevent an out of bounds error deep in NaCl
|
||||
if len(ciphertext) < self.TAG_SIZE:
|
||||
raise ValueError(f"The authentication tag is missing or malformed")
|
||||
raise ValueError("The authentication tag is missing or malformed")
|
||||
|
||||
try:
|
||||
return xchacha_decrypt(ciphertext, authenticated_data, nonce, self._key)
|
||||
except nacl.exceptions.CryptoError:
|
||||
except nacl.exceptions.CryptoError as e:
|
||||
raise GenericError("Decryption of ciphertext failed: "
|
||||
"either someone tampered with the ciphertext or "
|
||||
"you are using an incorrect decryption key.")
|
||||
"you are using an incorrect decryption key.") from e
|
||||
|
|
|
@ -2,7 +2,6 @@ class GenericError(Exception):
|
|||
"""
|
||||
An interal Umbral error, see the message for details.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class VerificationError(GenericError):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import TYPE_CHECKING, Optional, Type, Iterable, Union, List, cast
|
||||
from typing import TYPE_CHECKING, Optional, Iterable, Union, List, cast
|
||||
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
|
||||
|
@ -63,7 +63,9 @@ def hash_to_shared_secret(precursor: CurvePoint,
|
|||
return CurveScalar.from_digest(digest)
|
||||
|
||||
|
||||
def hash_to_cfrag_verification(points: Iterable[CurvePoint], metadata: Optional[bytes] = None) -> CurveScalar:
|
||||
def hash_to_cfrag_verification(points: Iterable[CurvePoint],
|
||||
metadata: Optional[bytes] = None
|
||||
) -> CurveScalar:
|
||||
digest = Hash(b"CFRAG_VERIFICATION")
|
||||
for point in points:
|
||||
digest.update(point)
|
||||
|
@ -90,7 +92,9 @@ def kfrag_signature_message(kfrag_id: 'KeyFragID',
|
|||
if maybe_receiving_pk
|
||||
else [serialize_bool(False)])
|
||||
|
||||
components = [bytes(kfrag_id), bytes(commitment), bytes(precursor)] + delegating_part + receiving_part
|
||||
components = ([bytes(kfrag_id), bytes(commitment), bytes(precursor)] +
|
||||
delegating_part +
|
||||
receiving_part)
|
||||
|
||||
return b''.join(components)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import os
|
||||
from typing import Tuple, List, Optional
|
||||
from typing import List, Optional
|
||||
|
||||
from .curve_point import CurvePoint
|
||||
from .curve_scalar import CurveScalar
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
from contextlib import contextmanager
|
||||
from typing import Tuple
|
||||
|
||||
from cryptography.exceptions import InternalError, InvalidSignature
|
||||
from cryptography.hazmat.backends.openssl import backend
|
||||
from cryptography.hazmat.backends.openssl.ec import _EllipticCurvePrivateKey, _EllipticCurvePublicKey
|
||||
from cryptography.hazmat.backends.openssl.ec import (_EllipticCurvePrivateKey,
|
||||
_EllipticCurvePublicKey)
|
||||
from cryptography.hazmat.primitives.asymmetric import utils
|
||||
from cryptography.hazmat.primitives.asymmetric.ec import ECDSA
|
||||
|
||||
|
||||
BACKEND_LIB = backend._lib
|
||||
BACKEND_FFI = backend._ffi
|
||||
|
||||
|
||||
def tmp_bn_ctx():
|
||||
return backend._tmp_bn_ctx()
|
||||
|
||||
|
||||
class Curve:
|
||||
"""
|
||||
Acts as a container to store constant variables such as the OpenSSL
|
||||
|
@ -26,8 +34,8 @@ class Curve:
|
|||
Returns the group of a given curve via its OpenSSL nid. This must be freed
|
||||
after each use otherwise it leaks memory.
|
||||
"""
|
||||
group = backend._lib.EC_GROUP_new_by_curve_name(nid)
|
||||
backend.openssl_assert(group != backend._ffi.NULL)
|
||||
group = BACKEND_LIB.EC_GROUP_new_by_curve_name(nid)
|
||||
backend.openssl_assert(group != BACKEND_FFI.NULL)
|
||||
return group
|
||||
|
||||
@staticmethod
|
||||
|
@ -36,8 +44,8 @@ class Curve:
|
|||
Returns the order of a given curve via its OpenSSL EC_GROUP.
|
||||
"""
|
||||
ec_order = _bn_new()
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.EC_GROUP_get_order(ec_group, ec_order, bn_ctx)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.EC_GROUP_get_order(ec_group, ec_order, bn_ctx)
|
||||
backend.openssl_assert(res == 1)
|
||||
return ec_order
|
||||
|
||||
|
@ -46,9 +54,9 @@ class Curve:
|
|||
"""
|
||||
Returns the generator point of a given curve via its OpenSSL EC_GROUP.
|
||||
"""
|
||||
generator = backend._lib.EC_GROUP_get0_generator(ec_group)
|
||||
backend.openssl_assert(generator != backend._ffi.NULL)
|
||||
generator = backend._ffi.gc(generator, backend._lib.EC_POINT_clear_free)
|
||||
generator = BACKEND_LIB.EC_GROUP_get0_generator(ec_group)
|
||||
backend.openssl_assert(generator != BACKEND_FFI.NULL)
|
||||
generator = BACKEND_FFI.gc(generator, BACKEND_LIB.EC_POINT_clear_free)
|
||||
|
||||
return generator
|
||||
|
||||
|
@ -58,7 +66,7 @@ class Curve:
|
|||
Returns the number of bits needed to represent the order of the finite
|
||||
field upon the curve is based.
|
||||
"""
|
||||
return backend._lib.EC_GROUP_get_degree(ec_group)
|
||||
return BACKEND_LIB.EC_GROUP_get_degree(ec_group)
|
||||
|
||||
def __init__(self, nid: int):
|
||||
"""
|
||||
|
@ -69,8 +77,8 @@ class Curve:
|
|||
|
||||
try:
|
||||
self.name = self._supported_curves[nid]
|
||||
except KeyError:
|
||||
raise NotImplementedError("Curve NID {} is not supported.".format(nid))
|
||||
except KeyError as e:
|
||||
raise NotImplementedError("Curve NID {} is not supported.".format(nid)) from e
|
||||
|
||||
self.nid = nid
|
||||
|
||||
|
@ -120,12 +128,12 @@ def _bn_new():
|
|||
"""
|
||||
Returns a new and initialized OpenSSL BIGNUM.
|
||||
"""
|
||||
new_bn = backend._lib.BN_new()
|
||||
backend.openssl_assert(new_bn != backend._ffi.NULL)
|
||||
new_bn = backend._ffi.gc(new_bn, backend._lib.BN_clear_free)
|
||||
new_bn = BACKEND_LIB.BN_new()
|
||||
backend.openssl_assert(new_bn != BACKEND_FFI.NULL)
|
||||
new_bn = BACKEND_FFI.gc(new_bn, BACKEND_LIB.BN_clear_free)
|
||||
|
||||
# Always use constant time operations.
|
||||
backend._lib.BN_set_flags(new_bn, backend._lib.BN_FLG_CONSTTIME)
|
||||
BACKEND_LIB.BN_set_flags(new_bn, BACKEND_LIB.BN_FLG_CONSTTIME)
|
||||
return new_bn
|
||||
|
||||
|
||||
|
@ -134,11 +142,11 @@ def bn_is_normalized(check_bn, modulus):
|
|||
Returns ``True`` if ``check_bn`` is in ``[0, modulus)``, ``False`` otherwise.
|
||||
"""
|
||||
zero = backend._int_to_bn(0)
|
||||
zero = backend._ffi.gc(zero, backend._lib.BN_clear_free)
|
||||
zero = BACKEND_FFI.gc(zero, BACKEND_LIB.BN_clear_free)
|
||||
|
||||
check_sign = backend._lib.BN_cmp(check_bn, zero)
|
||||
range_check = backend._lib.BN_cmp(check_bn, modulus)
|
||||
return (check_sign == 1 or check_sign == 0) and range_check == -1
|
||||
check_sign = BACKEND_LIB.BN_cmp(check_bn, zero)
|
||||
range_check = BACKEND_LIB.BN_cmp(check_bn, modulus)
|
||||
return check_sign in (0, 1) and range_check == -1
|
||||
|
||||
|
||||
def bn_from_int(py_int: int, check_modulus=None):
|
||||
|
@ -147,12 +155,12 @@ def bn_from_int(py_int: int, check_modulus=None):
|
|||
provided, it will check if the Python integer is within ``[0, modulus)``.
|
||||
"""
|
||||
conv_bn = backend._int_to_bn(py_int)
|
||||
conv_bn = backend._ffi.gc(conv_bn, backend._lib.BN_clear_free)
|
||||
conv_bn = BACKEND_FFI.gc(conv_bn, BACKEND_LIB.BN_clear_free)
|
||||
|
||||
if check_modulus and not bn_is_normalized(conv_bn, check_modulus):
|
||||
raise ValueError(f"The Python integer given ({py_int}) is not under the provided modulus.")
|
||||
|
||||
backend._lib.BN_set_flags(conv_bn, backend._lib.BN_FLG_CONSTTIME)
|
||||
BACKEND_LIB.BN_set_flags(conv_bn, BACKEND_LIB.BN_FLG_CONSTTIME)
|
||||
return conv_bn
|
||||
|
||||
|
||||
|
@ -161,8 +169,8 @@ def bn_from_bytes(bytes_seq: bytes, check_modulus=None, apply_modulus=None):
|
|||
Converts the given byte sequence to an OpenSSL BIGNUM.
|
||||
"""
|
||||
bn = _bn_new()
|
||||
backend._lib.BN_bin2bn(bytes_seq, len(bytes_seq), bn)
|
||||
backend.openssl_assert(bn != backend._ffi.NULL)
|
||||
BACKEND_LIB.BN_bin2bn(bytes_seq, len(bytes_seq), bn)
|
||||
backend.openssl_assert(bn != BACKEND_FFI.NULL)
|
||||
|
||||
if check_modulus and not bn_is_normalized(bn, check_modulus):
|
||||
raise ValueError(f"The integer encoded with given bytes ({repr(bytes_seq)}) "
|
||||
|
@ -170,12 +178,12 @@ def bn_from_bytes(bytes_seq: bytes, check_modulus=None, apply_modulus=None):
|
|||
|
||||
if apply_modulus:
|
||||
bignum =_bn_new()
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.BN_mod(bignum, bn, apply_modulus, bn_ctx)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.BN_mod(bignum, bn, apply_modulus, bn_ctx)
|
||||
backend.openssl_assert(res == 1)
|
||||
return bignum
|
||||
else:
|
||||
return bn
|
||||
|
||||
return bn
|
||||
|
||||
|
||||
def bn_to_bytes(bn, length: int):
|
||||
|
@ -186,17 +194,17 @@ def bn_to_bytes(bn, length: int):
|
|||
"""
|
||||
|
||||
# Sanity check, CurveScalar ensures it won't happen.
|
||||
bn_num_bytes = backend._lib.BN_num_bytes(bn)
|
||||
bn_num_bytes = BACKEND_LIB.BN_num_bytes(bn)
|
||||
assert bn_num_bytes <= length, f"Input BIGNUM doesn't fit in {length} B"
|
||||
|
||||
bin_ptr = backend._ffi.new("unsigned char []", length)
|
||||
bin_len = backend._lib.BN_bn2bin(bn, bin_ptr)
|
||||
return bytes.rjust(backend._ffi.buffer(bin_ptr, bin_len)[:], length, b'\0')
|
||||
bin_ptr = BACKEND_FFI.new("unsigned char []", length)
|
||||
bin_len = BACKEND_LIB.BN_bn2bin(bn, bin_ptr)
|
||||
return bytes.rjust(BACKEND_FFI.buffer(bin_ptr, bin_len)[:], length, b'\0')
|
||||
|
||||
|
||||
def bn_random_nonzero(modulus):
|
||||
|
||||
one = backend._lib.BN_value_one()
|
||||
one = BACKEND_LIB.BN_value_one()
|
||||
|
||||
# TODO: in most cases, we want this number to be secret.
|
||||
# OpenSSL 1.1.1 has `BN_priv_rand_range()`, but it is not
|
||||
|
@ -205,24 +213,24 @@ def bn_random_nonzero(modulus):
|
|||
|
||||
# Calculate `modulus - 1`
|
||||
modulus_minus_1 = _bn_new()
|
||||
res = backend._lib.BN_sub(modulus_minus_1, modulus, one)
|
||||
res = BACKEND_LIB.BN_sub(modulus_minus_1, modulus, one)
|
||||
backend.openssl_assert(res == 1)
|
||||
|
||||
# Get a random in range `[0, modulus - 1)`
|
||||
new_rand_bn = _bn_new()
|
||||
res = backend._lib.BN_rand_range(new_rand_bn, modulus_minus_1)
|
||||
res = BACKEND_LIB.BN_rand_range(new_rand_bn, modulus_minus_1)
|
||||
backend.openssl_assert(res == 1)
|
||||
|
||||
# Turn it into a random in range `[1, modulus)`
|
||||
op_sum = _bn_new()
|
||||
res = backend._lib.BN_add(op_sum, new_rand_bn, one)
|
||||
res = BACKEND_LIB.BN_add(op_sum, new_rand_bn, one)
|
||||
backend.openssl_assert(res == 1)
|
||||
|
||||
return op_sum
|
||||
|
||||
|
||||
def _bn_size(bn):
|
||||
return backend._lib.BN_num_bytes(bn)
|
||||
return BACKEND_LIB.BN_num_bytes(bn)
|
||||
|
||||
|
||||
def bn_to_int(bn):
|
||||
|
@ -231,11 +239,11 @@ def bn_to_int(bn):
|
|||
|
||||
def bn_cmp(bn1, bn2):
|
||||
# -1 less than, 0 is equal to, 1 is greater than
|
||||
return backend._lib.BN_cmp(bn1, bn2)
|
||||
return BACKEND_LIB.BN_cmp(bn1, bn2)
|
||||
|
||||
|
||||
def bn_one():
|
||||
return backend._lib.BN_value_one()
|
||||
return BACKEND_LIB.BN_value_one()
|
||||
|
||||
|
||||
def bn_is_zero(bn):
|
||||
|
@ -244,47 +252,47 @@ def bn_is_zero(bn):
|
|||
|
||||
|
||||
def bn_invert(bn, modulus):
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
inv = backend._lib.BN_mod_inverse(backend._ffi.NULL, bn, modulus, bn_ctx)
|
||||
backend.openssl_assert(inv != backend._ffi.NULL)
|
||||
inv = backend._ffi.gc(inv, backend._lib.BN_clear_free)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
inv = BACKEND_LIB.BN_mod_inverse(BACKEND_FFI.NULL, bn, modulus, bn_ctx)
|
||||
backend.openssl_assert(inv != BACKEND_FFI.NULL)
|
||||
inv = BACKEND_FFI.gc(inv, BACKEND_LIB.BN_clear_free)
|
||||
return inv
|
||||
|
||||
|
||||
def bn_sub(bn1, bn2, modulus):
|
||||
diff = _bn_new()
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.BN_mod_sub(diff, bn1, bn2, modulus, bn_ctx)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.BN_mod_sub(diff, bn1, bn2, modulus, bn_ctx)
|
||||
backend.openssl_assert(res == 1)
|
||||
return diff
|
||||
|
||||
|
||||
def bn_add(bn1, bn2, modulus):
|
||||
op_sum = _bn_new()
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.BN_mod_add(op_sum, bn1, bn2, modulus, bn_ctx)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.BN_mod_add(op_sum, bn1, bn2, modulus, bn_ctx)
|
||||
backend.openssl_assert(res == 1)
|
||||
return op_sum
|
||||
|
||||
|
||||
def bn_mul(bn1, bn2, modulus):
|
||||
product = _bn_new()
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.BN_mod_mul(product, bn1, bn2, modulus, bn_ctx)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.BN_mod_mul(product, bn1, bn2, modulus, bn_ctx)
|
||||
backend.openssl_assert(res == 1)
|
||||
return product
|
||||
|
||||
|
||||
def bn_to_privkey(curve: Curve, bn):
|
||||
|
||||
ec_key = backend._lib.EC_KEY_new()
|
||||
backend.openssl_assert(ec_key != backend._ffi.NULL)
|
||||
ec_key = backend._ffi.gc(ec_key, backend._lib.EC_KEY_free)
|
||||
ec_key = BACKEND_LIB.EC_KEY_new()
|
||||
backend.openssl_assert(ec_key != BACKEND_FFI.NULL)
|
||||
ec_key = BACKEND_FFI.gc(ec_key, BACKEND_LIB.EC_KEY_free)
|
||||
|
||||
set_group_result = backend._lib.EC_KEY_set_group(ec_key, curve.ec_group)
|
||||
set_group_result = BACKEND_LIB.EC_KEY_set_group(ec_key, curve.ec_group)
|
||||
backend.openssl_assert(set_group_result == 1)
|
||||
|
||||
set_privkey_result = backend._lib.EC_KEY_set_private_key(ec_key, bn)
|
||||
set_privkey_result = BACKEND_LIB.EC_KEY_set_private_key(ec_key, bn)
|
||||
backend.openssl_assert(set_privkey_result == 1)
|
||||
|
||||
evp_pkey = backend._ec_cdata_to_evp_pkey(ec_key)
|
||||
|
@ -301,9 +309,9 @@ def _point_new(ec_group):
|
|||
Returns a new and initialized OpenSSL EC_POINT given the group of a curve.
|
||||
If __curve_nid is provided, it retrieves the group from the curve provided.
|
||||
"""
|
||||
new_point = backend._lib.EC_POINT_new(ec_group)
|
||||
backend.openssl_assert(new_point != backend._ffi.NULL)
|
||||
new_point = backend._ffi.gc(new_point, backend._lib.EC_POINT_clear_free)
|
||||
new_point = BACKEND_LIB.EC_POINT_new(ec_group)
|
||||
backend.openssl_assert(new_point != BACKEND_FFI.NULL)
|
||||
new_point = BACKEND_FFI.gc(new_point, BACKEND_LIB.EC_POINT_clear_free)
|
||||
|
||||
return new_point
|
||||
|
||||
|
@ -317,8 +325,8 @@ def point_from_affine_coords(curve: Curve, affine_x: int, affine_y: int):
|
|||
bn_affine_y = bn_from_int(affine_y)
|
||||
|
||||
new_point = _point_new(curve.ec_group)
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.EC_POINT_set_affine_coordinates_GFp(
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.EC_POINT_set_affine_coordinates_GFp(
|
||||
curve.ec_group, new_point, bn_affine_x, bn_affine_y, bn_ctx
|
||||
)
|
||||
backend.openssl_assert(res == 1)
|
||||
|
@ -332,8 +340,8 @@ def point_to_affine_coords(curve: Curve, point) -> Tuple[int, int]:
|
|||
affine_x = _bn_new()
|
||||
affine_y = _bn_new()
|
||||
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.EC_POINT_get_affine_coordinates_GFp(
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.EC_POINT_get_affine_coordinates_GFp(
|
||||
curve.ec_group, point, affine_x, affine_y, bn_ctx
|
||||
)
|
||||
backend.openssl_assert(res == 1)
|
||||
|
@ -352,8 +360,8 @@ class ErrorInvalidPointEncoding(Exception):
|
|||
def point_from_bytes(curve: Curve, data):
|
||||
point = _point_new(curve.ec_group)
|
||||
try:
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.EC_POINT_oct2point(curve.ec_group, point, data, len(data), bn_ctx);
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.EC_POINT_oct2point(curve.ec_group, point, data, len(data), bn_ctx)
|
||||
backend.openssl_assert(res == 1)
|
||||
except InternalError as e:
|
||||
# We want to catch specific InternalExceptions.
|
||||
|
@ -361,35 +369,35 @@ def point_from_bytes(curve: Curve, data):
|
|||
# There is also EC_R_POINT_IS_NOT_ON_CURVE (code 107),
|
||||
# but somehow it is never triggered during deserialization.
|
||||
if e.err_code[0].reason == 110: # EC_R_INVALID_COMPRESSED_POINT
|
||||
raise ErrorInvalidCompressedPoint
|
||||
elif e.err_code[0].reason == 102: # EC_R_INVALID_ENCODING
|
||||
raise ErrorInvalidPointEncoding
|
||||
else:
|
||||
# Any other exception, we raise it.
|
||||
# (although at the moment I'm not sure what should one do to cause it)
|
||||
raise e # pragma: no cover
|
||||
raise ErrorInvalidCompressedPoint from e
|
||||
if e.err_code[0].reason == 102: # EC_R_INVALID_ENCODING
|
||||
raise ErrorInvalidPointEncoding from e
|
||||
|
||||
# Any other exception, we raise it.
|
||||
# (although at the moment I'm not sure what should one do to cause it)
|
||||
raise # pragma: no cover
|
||||
return point
|
||||
|
||||
|
||||
def point_to_bytes_compressed(curve: Curve, point):
|
||||
point_conversion_form = backend._lib.POINT_CONVERSION_COMPRESSED
|
||||
point_conversion_form = BACKEND_LIB.POINT_CONVERSION_COMPRESSED
|
||||
|
||||
size = curve.field_element_size + 1 # compressed point size
|
||||
|
||||
bin_ptr = backend._ffi.new("unsigned char[]", size)
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
bin_len = backend._lib.EC_POINT_point2oct(
|
||||
bin_ptr = BACKEND_FFI.new("unsigned char[]", size)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
bin_len = BACKEND_LIB.EC_POINT_point2oct(
|
||||
curve.ec_group, point, point_conversion_form,
|
||||
bin_ptr, size, bn_ctx
|
||||
)
|
||||
backend.openssl_assert(bin_len != 0)
|
||||
|
||||
return bytes(backend._ffi.buffer(bin_ptr, bin_len)[:])
|
||||
return bytes(BACKEND_FFI.buffer(bin_ptr, bin_len)[:])
|
||||
|
||||
|
||||
def point_eq(curve: Curve, point1, point2):
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
is_equal = backend._lib.EC_POINT_cmp(curve.ec_group, point1, point2, bn_ctx)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
is_equal = BACKEND_LIB.EC_POINT_cmp(curve.ec_group, point1, point2, bn_ctx)
|
||||
backend.openssl_assert(is_equal != -1)
|
||||
|
||||
# 1 is not-equal, 0 is equal, -1 is error
|
||||
|
@ -398,27 +406,27 @@ def point_eq(curve: Curve, point1, point2):
|
|||
|
||||
def point_mul_bn(curve: Curve, point, bn):
|
||||
prod = _point_new(curve.ec_group)
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.EC_POINT_mul(curve.ec_group, prod, backend._ffi.NULL, point, bn, bn_ctx)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.EC_POINT_mul(curve.ec_group, prod, BACKEND_FFI.NULL, point, bn, bn_ctx)
|
||||
backend.openssl_assert(res == 1)
|
||||
return prod
|
||||
|
||||
|
||||
def point_add(curve: Curve, point1, point2):
|
||||
op_sum = _point_new(curve.ec_group)
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.EC_POINT_add(curve.ec_group, op_sum, point1, point2, bn_ctx)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.EC_POINT_add(curve.ec_group, op_sum, point1, point2, bn_ctx)
|
||||
backend.openssl_assert(res == 1)
|
||||
return op_sum
|
||||
|
||||
|
||||
def point_neg(curve: Curve, point):
|
||||
inv = backend._lib.EC_POINT_dup(point, curve.ec_group)
|
||||
backend.openssl_assert(inv != backend._ffi.NULL)
|
||||
inv = backend._ffi.gc(inv, backend._lib.EC_POINT_clear_free)
|
||||
inv = BACKEND_LIB.EC_POINT_dup(point, curve.ec_group)
|
||||
backend.openssl_assert(inv != BACKEND_FFI.NULL)
|
||||
inv = BACKEND_FFI.gc(inv, BACKEND_LIB.EC_POINT_clear_free)
|
||||
|
||||
with backend._tmp_bn_ctx() as bn_ctx:
|
||||
res = backend._lib.EC_POINT_invert(curve.ec_group, inv, bn_ctx)
|
||||
with tmp_bn_ctx() as bn_ctx:
|
||||
res = BACKEND_LIB.EC_POINT_invert(curve.ec_group, inv, bn_ctx)
|
||||
backend.openssl_assert(res == 1)
|
||||
|
||||
return inv
|
||||
|
@ -426,14 +434,14 @@ def point_neg(curve: Curve, point):
|
|||
|
||||
def point_to_pubkey(curve: Curve, point):
|
||||
|
||||
ec_key = backend._lib.EC_KEY_new()
|
||||
backend.openssl_assert(ec_key != backend._ffi.NULL)
|
||||
ec_key = backend._ffi.gc(ec_key, backend._lib.EC_KEY_free)
|
||||
ec_key = BACKEND_LIB.EC_KEY_new()
|
||||
backend.openssl_assert(ec_key != BACKEND_FFI.NULL)
|
||||
ec_key = BACKEND_FFI.gc(ec_key, BACKEND_LIB.EC_KEY_free)
|
||||
|
||||
set_group_result = backend._lib.EC_KEY_set_group(ec_key, curve.ec_group)
|
||||
set_group_result = BACKEND_LIB.EC_KEY_set_group(ec_key, curve.ec_group)
|
||||
backend.openssl_assert(set_group_result == 1)
|
||||
|
||||
set_pubkey_result = backend._lib.EC_KEY_set_public_key(ec_key, point)
|
||||
set_pubkey_result = BACKEND_LIB.EC_KEY_set_public_key(ec_key, point)
|
||||
backend.openssl_assert(set_pubkey_result == 1)
|
||||
|
||||
evp_pkey = backend._ec_cdata_to_evp_pkey(ec_key)
|
||||
|
@ -444,7 +452,11 @@ def point_to_pubkey(curve: Curve, point):
|
|||
# Signing
|
||||
#
|
||||
|
||||
def ecdsa_sign(curve: Curve, secret_bn, prehashed_message: bytes, hash_algorithm) -> Tuple[int, int]:
|
||||
def ecdsa_sign(curve: Curve,
|
||||
secret_bn,
|
||||
prehashed_message: bytes,
|
||||
hash_algorithm
|
||||
) -> Tuple[int, int]:
|
||||
signature_algorithm = ECDSA(utils.Prehashed(hash_algorithm))
|
||||
private_key = bn_to_privkey(curve, secret_bn)
|
||||
signature_der_bytes = private_key.sign(prehashed_message, signature_algorithm)
|
||||
|
|
|
@ -50,7 +50,8 @@ def generate_kfrags(delegating_sk: SecretKey,
|
|||
|
||||
# Technically we could allow it, but what would be the use of these kfrags?
|
||||
if num_kfrags < threshold:
|
||||
raise ValueError(f"Creating less kfrags ({num_kfrags}) than threshold ({threshold}) makes them useless")
|
||||
raise ValueError(f"Creating less kfrags ({num_kfrags}) "
|
||||
f"than threshold ({threshold}) makes them useless")
|
||||
|
||||
kfrags = [KeyFrag.from_base(base, sign_delegating_key, sign_receiving_key)
|
||||
for _ in range(num_kfrags)]
|
||||
|
@ -97,4 +98,3 @@ def decrypt_reencrypted(decrypting_sk: SecretKey,
|
|||
key_seed = capsule.open_reencrypted(decrypting_sk, delegating_pk, cfrags)
|
||||
dem = DEM(bytes(key_seed))
|
||||
return dem.decrypt(ciphertext, authenticated_data=bytes(capsule))
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ class Serializable(ABC):
|
|||
Takes ``size`` bytes from the bytestring and returns them along with the remainder.
|
||||
"""
|
||||
if len(data) < size:
|
||||
raise ValueError(f"{cls} cannot take {size} bytes from a bytestring of size {len(data)}")
|
||||
raise ValueError(f"{cls} cannot take {size} bytes "
|
||||
f"from a bytestring of size {len(data)}")
|
||||
return data[:size], data[size:]
|
||||
|
||||
@classmethod
|
||||
|
@ -70,5 +71,6 @@ def take_bool(data: bytes) -> Tuple[bool, bytes]:
|
|||
elif bool_bytes == b'\x00':
|
||||
b = False
|
||||
else:
|
||||
raise ValueError(f"Incorrectly serialized boolean; expected b'\\x00' or b'\\x01', got {repr(bool_bytes)}")
|
||||
raise ValueError("Incorrectly serialized boolean; "
|
||||
f"expected b'\\x00' or b'\\x01', got {repr(bool_bytes)}")
|
||||
return b, data
|
||||
|
|
|
@ -24,8 +24,9 @@ class Signer:
|
|||
|
||||
def sign_digest(self, digest: 'Hash') -> 'Signature':
|
||||
|
||||
secret_bn = self.__secret_key.secret_scalar()._backend_bignum
|
||||
r_int, s_int = openssl.ecdsa_sign(curve=CURVE,
|
||||
secret_bn=self.__secret_key.secret_scalar()._backend_bignum,
|
||||
secret_bn=secret_bn,
|
||||
prehashed_message=digest.finalize(),
|
||||
hash_algorithm=digest._backend_hash_algorithm)
|
||||
|
||||
|
|
Loading…
Reference in New Issue