Source code for pksig_lamport
'''
**Lamport One-Time Signature (Lamport79)**
*Authors:* L. Lamport
| **Title:** "Constructing Digital Signatures from a One Way Function"
| **Published in:** Technical Report, 1979
| **Available from:** http://lamport.azurewebsites.net/pubs/dig-sig.pdf
| **Notes:** One-time signature scheme based on one-way functions.
.. rubric:: Scheme Properties
* **Type:** signature (public key)
* **Setting:** hash functions
* **Assumption:** One-Way Function
.. rubric:: Implementation
:Authors: Jonas Thuresson, Martin Örndahl
:Date: 03/2018
'''
from charm.toolbox.PKSig import PKSig
from hashlib import sha256
import os
byte_masks = [2 ** b for b in range(8)]
byte_masks.reverse()
def _h(x):
return sha256(x).digest()
def _bytes_to_booleans(x):
return [byte & mask != 0 for byte in x for mask in byte_masks]
[docs]
class Lamport(PKSig):
'''
>>> sig = Lamport()
>>> pk, sk = sig.keygen()
>>> msg = 'hello'.encode('utf-8')
>>> s = sig.sign(None, sk, msg)
>>> assert sig.verify(pk, msg, s), "Signature could not be verified"
'''
def __init__(self):
super().__init__()
[docs]
def keygen(self, securityparam=256):
nbr_bytes = securityparam // 8
sk = [(os.urandom(nbr_bytes), os.urandom(nbr_bytes)) for _ in range(securityparam)]
pk = [(_h(i), _h(j)) for i, j in sk]
return pk, sk
[docs]
def sign(self, pk, sk, message):
msg_hash = _h(message)
return [sk1 if not b else sk2 for ((sk1, sk2), b) in zip(sk, _bytes_to_booleans(msg_hash))]
[docs]
def verify(self, pk, message, sig):
msg_hash = _h(message)
expected = [pk1 if not b else pk2 for ((pk1, pk2), b) in zip(pk, _bytes_to_booleans(msg_hash))]
return all([_h(s) == p for (s, p) in zip(sig, expected)])