Source code for pksig_ps02

'''
**Pointcheval-Sanders Signature (PS16) - Sequential Aggregate**

*Authors:* D. Pointcheval, O. Sanders

| **Title:** "Short Randomizable Signatures"
| **Published in:** CT-RSA, 2016
| **Available from:** https://eprint.iacr.org/2015/525.pdf
| **Notes:** Section 5 - Sequential aggregate signatures over known messages.

.. rubric:: Scheme Properties

* **Type:** signature (public key)
* **Setting:** bilinear groups (asymmetric)
* **Assumption:** PS assumption

.. rubric:: Implementation

:Authors: Lovesh Harchandani
:Date: 6/2018
'''
from functools import reduce

from charm.toolbox.pairinggroup import PairingGroup,ZR,G1,G2,pair

debug = False


[docs] class PS02: """ Sequential Aggregate signatures over known messages, section 5 of the paper """ def __init__(self, groupObj): global group group = groupObj
[docs] def setup(self): x = group.random(ZR) g1 = group.random(G1) g2 = group.random(G2) self.x = x self.g1 = g1 self.X1 = g1 ** x self.g2 = g2 self.X2 = g2 ** x
[docs] def keygen(self, num_messages): ys = [group.random(ZR) for _ in range(num_messages)] sk = {'y': ys} pk = {'Y': [self.g2 ** y for y in ys]} return pk, sk
[docs] def sign(self, sk, pk, messages): if not (len(pk['Y']) == len(messages) == len(sk['y'])): raise ValueError('Missing or extra messages or keys') for m in messages: if m == 0: raise ValueError('message cant be 0') for i in range(len(messages)): for j in range(i+1, len(messages)): if pk['Y'][i] == pk['Y'][j]: raise ValueError('all public keys should be distinct') prev_sig = (self.g1, self.X1) for i in range(len(messages)): if i > 0 and not self.verify({'Y': pk['Y'][:i]}, prev_sig, messages[:i]): raise ValueError('Intermediate verification error') t = group.random(ZR) s1, s2 = prev_sig m = group.hash(messages[i], ZR) prev_sig = (s1 ** t, (s2 * (s1 ** (sk['y'][i] * m))) ** t) return prev_sig
[docs] def verify(self, pk, sig, messages): if len(pk['Y']) != len(messages): raise ValueError('Missing or extra messages or keys') s1, s2 = sig if group.init(G1) == s1: return False l2 = self.X2 * self.product([pk['Y'][i] ** group.hash(messages[i], ZR) for i in range(len(messages))]) return pair(s1, l2) == pair(self.g2, s2)
[docs] @staticmethod def product(seq): return reduce(lambda x, y: x * y, seq)
[docs] def main(): grp = PairingGroup('MNT224') ps = PS02(grp) ps.setup() if debug: print("Setup...") print("x :=", ps.x) print("g1 :=", ps.g1) print("X1 :=", ps.X1) print("g2 :=", ps.g2) print("X2 :=", ps.X2) messages = ['Hi there', 'Not there', 'Some message ................', 'Dont know .............'] (pk, sk) = ps.keygen(len(messages)) if debug: print("Keygen...") print("pk :=", pk) print("sk :=", sk) sig = ps.sign(sk, pk, messages) if debug: print("Signature: ", sig) result = ps.verify(pk, sig, messages) assert result, "INVALID signature!" if debug: print("Successful Verification!!!")
if __name__ == "__main__": debug = True main()