r"""
This module provides a Python wrapper around RELIC's pairings using a
additive interface: operations in
:py:obj:`petrelic.additive.pairings.G1`,
:py:obj:`petrelic.additive.pairings.G2`, and
:py:obj:`petrelic.additive.pairings.GT` are all written
additively.
Let's see how we can use this interface to implement the Boney-Lynn-Shacham
signature scheme for type III pairings. First we generate a private key:
>>> sk = G1.order().random()
which is a random integer modulo the group order. Note that for this setting,
all three groups have the same order. Next, we generate the corresponding public
key:
>>> pk = (sk * G1.generator(), sk * G2.generator())
(For security in the type III setting, the first component is a necessary part
of the public key. It is not actually used in the scheme.) To sign a message
`m` we first hash it to the curve G1 using :py:meth:`G1.hash_to_point` and then
raise it to the power of the signing key `sk` to obtain a signature:
>>> m = b"Some message"
>>> signature = sk * G1.hash_to_point(m)
Finally, we can use the pairing operator to verify the signature:
>>> signature.pair(G2.generator()) == G1.hash_to_point(m).pair(pk[1])
True
Indeed, the pairing operator is bilinear. For example:
>>> a, b = 13, 29
>>> A = a * G1.generator()
>>> B = b * G2.generator()
>>> A.pair(B) == (a*b) * G1.generator().pair(G2.generator())
True
"""
from petrelic.bindings import _FFI, _C
from petrelic.bn import Bn, force_Bn_other
from petrelic.native.pairing import NoAffineCoordinateForECPoint
import petrelic.native.pairing as native
from petrelic.native.pairing import G2, G2Element
[docs]class BilinearGroupPair:
"""
A bilinear group pair.
Contains two origin groups G1, G2 and the image group GT.
"""
def __init__(self):
"""Initialise a bilinear group pair."""
self.GT = GT()
self.G1 = G1()
self.G2 = G2()
[docs] def groups(self):
"""
Returns the three groups in the following order : G1, G2, GT.
"""
return self.G1, self.G2, self.GT
[docs]class G1(native.G1):
"""G1 group."""
@classmethod
def _element_type(cls):
return G1Element
[docs]class G1Element(native.G1Element):
"""Element of the G1 group."""
group = G1
[docs] def pair(self, other):
"""Pair element with another element in G2
Computes the bilinear pairing between self and another element in
:py:obj:`petrelic.additive.pairing.G2`.
Examples:
>>> g1, g2 = G1.generator(), G2.generator()
>>> a, b = 10, 50
>>> A, B = g1 * a, g2 * b
>>> A.pair(B) == g1.pair(g2) * (a * b)
True
>>> A.pair(g2) == g1.pair(g2 * a)
True
>>> A.pair(g2) == g1.pair(g2) * a
True
"""
if not type(other) == G2Element:
raise TypeError("Second parameter should be of type G2Element is {}".format(type(other)))
res = GTElement()
_C.pc_map(res.pt, self.pt, other.pt)
return res
[docs]class G2(native.G2):
"""G2 group."""
@classmethod
def _element_type(cls):
return G2Element
[docs]class G2Element(native.G2Element):
"""Element of the G2 group."""
group = G2
[docs]class GT(native._GTBase):
"""GT group."""
@classmethod
def _element_type(cls):
return GTElement
#
# Replicated functions, fixing doc strings
#
[docs] @classmethod
def order(cls):
"""Return the order of the group as a Bn large integer.
Example:
>>> generator = GT.generator()
>>> neutral = GT.neutral_element()
>>> order = GT.order()
>>> order * generator == neutral
True
"""
return super().order()
[docs] @classmethod
def generator(cls):
"""Return generator of the group.
Example:
>>> generator = GT.generator()
>>> neutral = GT.neutral_element()
>>> generator + neutral == generator
True
"""
return super().generator()
[docs] @classmethod
def neutral_element(cls):
"""Return the neutral element of the group G1.
In this case, the point at infinity.
Example:
>>> generator = GT.generator()
>>> neutral = GT.neutral_element()
>>> generator + neutral == generator
True
"""
return super().neutral_element()
#
# Interface specific methods
#
[docs] @classmethod
def sum(cls, elems):
"""Efficient sum of a number of elements
In the current implementation this function is not optimized.
Example:
>>> elems = [ x * GT.generator() for x in [10, 25, 13]]
>>> GT.sum(elems) == (10 + 25 + 13) * GT.generator()
True
"""
res = cls.neutral_element()
for el in elems:
res += el
return res
[docs] @classmethod
def wsum(cls, weights, elems):
"""Efficient weighted product of a number of elements
In the current implementation this function is not optimized.
Example:
>>> weights = [1, 2, 3]
>>> elems = [ x * GT.generator() for x in [10, 25, 13]]
>>> GT.wsum(weights, elems) == (1 * 10 + 2 * 25 + 3 * 13) * GT.generator()
True
"""
res = cls.neutral_element()
for w, el in zip(weights, elems):
res += w * el
return res
#
# Aliases
#
[docs] @classmethod
def infinity(cls):
"""The unity element
Alias for :py:meth:`GT.neutral_element`
"""
return cls.neutral_element()
[docs]class GTElement(native._GTElementBase):
"""GT element."""
group = GT
#
# Unary operators
#
[docs] def double(self):
return native.GTElement.square(self)
[docs] def idouble(self):
return native.GTElement.isquare(self)
#
# Binary operators
#
def __add__(self, other):
return native.GTElement.__mul__(self, other)
def __iadd__(self, other):
return native.GTElement.__imul__(self, other)
def __sub__(self, other):
return native.GTElement.__truediv__(self, other)
def __isub__(self, other):
return native.GTElement.__itruediv__(self, other)
def __mul__(self, other):
return native.GTElement.__pow__(self, other)
def __imul__(self, other):
return native.GTElement.__ipow__(self, other)
def __rmul__(self, other):
return native.GTElement.__pow__(self, other)
# Copy documentation from native.G1Element
double.__doc__ = native.G1Element.double.__doc__.replace("G1", "GT")
idouble.__doc__ = native.G1Element.idouble.__doc__.replace("G1", "GT")
__add__.__doc__ = native.G1Element.__add__.__doc__.replace("G1", "GT")
__iadd__.__doc__ = native.G1Element.__iadd__.__doc__.replace("G1", "GT")
__sub__.__doc__ = native.G1Element.__sub__.__doc__.replace("G1", "GT")
__isub__.__doc__ = native.G1Element.__isub__.__doc__.replace("G1", "GT")
__mul__.__doc__ = native.G1Element.__mul__.__doc__.replace("G1", "GT")
__imul__.__doc__ = native.G1Element.__imul__.__doc__.replace("G1", "GT")
#
# Aliases
#
__neg__ = native._GTElementBase.inverse
neg = __neg__
add = __add__
iadd = __iadd__
sub = __sub__
isub = __isub__
mul = __mul__
imul = __imul__