'''
**Pointcheval-Sanders Signature (PS16) - Known Messages**
*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 4 - 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 PS01:
"""
Signatures over known messages, section 4 of the paper
"""
def __init__(self, groupObj):
global group
group = groupObj
[docs]
@staticmethod
def keygen(num_messages=1):
x = group.random(ZR)
ys = [group.random(ZR) for _ in range(num_messages)]
sk = {'x': x, 'y': ys}
g2 = group.random(G2)
pk = {'X': g2 ** x, 'Y': [g2 ** y for y in ys], 'g2': g2}
return pk, sk
[docs]
def sign(self, sk, *messages):
h = group.random(G1)
ms = [group.hash(m, ZR) for m in messages]
exp = sk['x'] + sum([sk['y'][i] * ms[i] for i in range(len(messages))])
return h, h ** exp
[docs]
def verify(self, pk, sig, *messages):
s1, s2 = sig
if group.init(G1) == s1:
return False
ms = [group.hash(m, ZR) for m in messages]
l2 = pk['X'] * self.product([pk['Y'][i] ** ms[i] for i in range(len(messages))])
return pair(s1, l2) == pair(pk['g2'], s2)
[docs]
def randomize_sig(self, sig):
s1, s2 = sig
t = group.random(ZR)
return s1 ** t, s2 ** t
[docs]
@staticmethod
def product(seq):
return reduce(lambda x, y: x * y, seq)
[docs]
def main():
grp = PairingGroup('MNT224')
ps = PS01(grp)
print("Signing a single message")
(pk, sk) = ps.keygen()
if debug:
print("Keygen...")
print("pk :=", pk)
print("sk :=", sk)
M = "Please sign this stupid message!"
sig = ps.sign(sk, M)
if debug:
print("Signature: ", sig)
result = ps.verify(pk, sig, M)
assert result, "INVALID signature!"
if debug:
print("Successful Verification!!!")
rand_sig = ps.randomize_sig(sig)
assert sig != rand_sig
if debug:
print("Randomized Signature: ", rand_sig)
result = ps.verify(pk, rand_sig, M)
assert result, "INVALID signature!"
if debug:
print("Successful Verification!!!")
print("Signing multiple messages")
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, *messages)
if debug:
print("Signature: ", sig)
result = ps.verify(pk, sig, *messages)
assert result, "INVALID signature!"
if debug:
print("Successful Verification!!!")
rand_sig = ps.randomize_sig(sig)
assert sig != rand_sig
if debug:
print("Randomized Signature: ", rand_sig)
result = ps.verify(pk, rand_sig, *messages)
assert result, "INVALID signature!"
if debug:
print("Successful Verification!!!")
if __name__ == "__main__":
debug = True
main()