May 19, 2018

lamport.py

This is a script I wrote in Python to use the ideas expressed by Lamport and Stanislav.

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

#!/usr/bin/python

#
# (C) 2016 Peter Lambert. 
# You do not have, nor can you ever acquire the right to use, copy or distribute this software; 
# should you use this software for any purpose, or copy and distribute it to anyone or in any manner,
# you are breaking the laws of whatever soi-disant jurisdiction, and you promise to continue doing
# so for the indefinite future.
#

import hashlib
import os
import sys

#
# Comment out the line below with the hash you do not want to use

# sha = hashlib.sha256
sha = hashlib.sha512


def binmessagehash(filename):
    m = open(filename, 'r')
    messagehash = sha(m.read()).hexdigest()
    m.close()    
    return bin(int(messagehash, 16))[2:].zfill(len(messagehash) * 4)
    
def decode(pubkeyfile, sigfile):
    kf = open(pubkeyfile, 'r')
    pubkey = [line.strip().split() for line in kf.readlines()]
    kf.close()
    
    sf = open(sigfile, 'r')
    sig_keys = [line.strip() for line in sf.readlines()]
    sf.close()
    
    binmessage = ''
    
    for k in range(len(sig_keys)):
        key_hash = sha(sig_keys[k].decode('hex')).hexdigest()
        if key_hash in pubkey[k]:
            binmessage += str(pubkey[k].index(key_hash))
        else:
            return 'Bad signature, hash not found for %s' % sig_keys[k]
    
    hexmessage = '%x' % (int(binmessage, 2))
    return hexmessage
    
def encode(privkeyfile, messagefile):
    pkf = open(privkeyfile, 'r')
    key = [line.strip().split() for line in pkf.readlines()]
    pkf.close()
    
    bmess = binmessagehash(messagefile)
    for k in range(len(bmess)):
        print key[k][int(bmess[k])]

def generate_key(payloadbits, strengthbits):
    if '-s' in sys.argv:
        rs = randstr
    else:
        rs = os.urandom
    key = [[rs(int(strengthbits) / 8) for n in [0, 1]] for m in range(int(payloadbits))]
    for k in key:
        print ' '.join(kp.encode('hex') for kp in k)
            
def output_help():
    print '''Usage: 
        ./lamport.py -g PAYLOADBITS STRENGTHBITS > PRIVKEYFILE  
            generates a key
            
        ./lamport.py -g -s PAYLOADBITS STRENGTHBITS > PRIVKEYFILE
            generates a key with the slower, more secure /dev/random
            
        ./lamport.py -p PRIVKEYFILE > PUBKEYFILE
            creates a pubkey from a privkey file
            
        ./lamport.py -e PRIVKEYFILE MESSAGE > ENCODED.TXT
            creates a digital signature
            
        ./lamport.py -d PUBKEYFILE ENCODED.TXT
            decode the digital signature
            
        ./lamport.py -v PUBKEYFILE ENCODED.TXT MESSAGE
            check that encoded is the correct signature for message
    ''' 

def priv_to_pubkey(privkeyfile):
    pkf = open(privkeyfile, 'r')
    for line in pkf.readlines():
        print ' '.join(sha(k.decode('hex')).hexdigest() for k in line.strip().split())
    pkf.close()
    
def randstr(num_bytes):
    stream = open('/dev/random', 'rb')
    res = stream.read(num_bytes)
    stream.close()
    return res

def verify(pubkeyfile, sigfile, messagefile):
    decoded = decode(pubkeyfile, sigfile)
    print decoded
    
    m = open(messagefile, 'r')
    messagehash = sha(m.read()).hexdigest()
    m.close()
    
    if decoded == messagehash:
        print 'Good signature'
    else:
        print 'Bad signature'

if __name__ == "__main__":
    if '-g' in sys.argv and sys.argv[-2].isdigit() and sys.argv[-1].isdigit():
        generate_key(sys.argv[-2], sys.argv[-1])
    elif '-p' in sys.argv:
        priv_to_pubkey(sys.argv[-1])
    elif '-e' in sys.argv:
        encode(sys.argv[-2], sys.argv[-1])
    elif '-d' in sys.argv:
        print decode(sys.argv[-2], sys.argv[-1])
    elif '-v' in sys.argv:
        verify(sys.argv[-3], sys.argv[-2], sys.argv[-1])
    else:
        output_help()
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBAgAGBQJX89k8AAoJELTi4Nystj0llqwQAJpubTEEl4VysaO/IlPExNFl
mQ+md7cBEAmK3ithZcJSS5XsKXhSWs+w6b0IJRQB0r2XMHu4hZUiRicVubkiKtwc
jqZ8ots+Pr9mzcuw4dlVNH6Avr0WPpcObwCEWXzlLVP27kEeXCPSwPTp0Eh3YAgv
YGOkMvu4Yw2HmzwfNlHAdhdAPuNpW7dOHGwZAzBkeWegZDK/urDp7oEIw8D/DBBz
FbH/eXsRcHzmjk1cOi9lgQyaTZ3qSA+ULriSDM/LCjMNso+fKcxO0Pi7MpdNnxTj
l0KMHndWWaJkiROZ6M9zMyUt68/y4F1sJ0T/qy07msVYC8D7p+hEtOOJfAJuWiZL
VgLZzi5WiV93QwnKrJCrRR72SbPyAL9YGFbS5vBbilxv7dktoXUXnTeUP3Ddvn4B
4rW19wha3AZ5AT+ssuC8TggLzlDKlPLsGQmXEtyk7HAN+ynXnQ3ioHwwPOePzGHG
UfNIoXQnXDTLS4jLD09VXf3gYP27gb3ouT7dhOYQ0yignuE/5vvJ2UuneI52VV0i
pupS/vJ4h7qaKFJfhQmsczGkN0SnhyKjjE5Xi4A0NWHLKtaKU9Wxs0f/xA9b8sJg
hLjf2x1+3bHZeMsIPoxjd3z3xeHOgLj+BRSZTUxTmEZnlz6IaTzjNe5iSHL8ucef
tilzFtS1wA4DSSWPDbOg
=WGyj
-----END PGP SIGNATURE-----

No comments: