Module: encrypt_positions.py

"""
Main program: call with one argument: the identifier for the party doing the encryption.

Program to take the negotiation positions that party X wrote earlier and encrypt them. The
encrypted position files are written alongside of the earlier ones for subsequent secure
transmission to the opposite party in the negotiation.

There is a unique one-way encryption key for each pair of parties.

"""

import sys

basepath = "/Users/pbaker/Documents/Office Projects/Software Dev/demo1"

sys.path.append(basepath)
sys.path.append("%s/%s" % (basepath, "broker"))

import string
import broker_model as broker
import one_way_encrypt as OWE

def get_key(X, Y):
    """
Function to retrieve the session key from a file for players X and Y.
The key is returned to the caller.
"""
    fname = "%s/player%s/session_key_player%s.py" % (basepath, X, Y)
    f = open(fname)
    l = f.readline()
    one_way_key = None
    while l:
        if len(l) > 5:
            # we have a line with key to the right of '=' sign, get key next
            a = string.splitfields(l, "=")
            one_way_key = eval( a[1])
            break
        l = f.readline()

    f.close()
    return one_way_key

def encrypt_offer_statement(e, x, g, codebook):

    # first encrypt the string symbols that need encryption
    swap_stock = x["accept"]
    x_swap = e.encrypt_word(swap_stock)
    codebook[x_swap] = swap_stock
    x["accept"] = x_swap

    for_stock = x["for"]
    x_for = e.encrypt_word(for_stock)
    codebook[x_for] = for_stock
    x["for"] = x_for

    # encrypt any integers that need encryption
    interval = x["interval"]
    x_interval = e.encrypt_int(interval)
    codebook[x_interval] = interval
    x["interval"] = x_interval

    # conceal the real, continuous variables
    number_min = x["number"][0]
    x_number_min = e.encrypt_float("number", number_min)

    number_max = x["number"][1]
    x_number_max = e.encrypt_float("number", number_max)
    
    x["number"] = [ x_number_min, x_number_max ]
    
    cash_per_share = x["cash_per_share"]
    x_cash_min = e.encrypt_float("cash_per_share", cash_per_share[0])
    x_cash_max = e.encrypt_float("cash_per_share", cash_per_share[1])
    x["cash_per_share"] = [x_cash_min, x_cash_max]

    # write the encrypted ask statement
    g.write(str(x))
    g.write("\n")
    
def encrypt_ask_statement(e, x, g, codebook):

    # first encrypt the string symbols that need encryption
    swap_stock = x["swap_stock"]
    x_swap = e.encrypt_word(swap_stock)
    codebook[x_swap] = swap_stock
    x["swap_stock"] = x_swap

    for_stock = x["for_stock"]
    x_for = e.encrypt_word(for_stock)
    codebook[x_for] = for_stock
    x["for_stock"] = x_for

    # encrypt any integers that need encryption
    interval = x["interval"]
    x_interval = e.encrypt_int(interval)
    codebook[x_interval] = interval
    x["interval"] = x_interval

    # conceal the real, continuous variables
    number = x["number"]
    x_number = e.encrypt_float("number", number)
    x["number"] = x_number
    
    cash_per_share = x["cash_per_share"]
    x_cash_min = e.encrypt_float("cash_per_share", cash_per_share[0])
    x_cash_max = e.encrypt_float("cash_per_share", cash_per_share[1])
    x["cash_per_share"] = [x_cash_min, x_cash_max]

    # write the encrypted ask statement
    g.write(str(x))
    g.write("\n")
    

    

def encrypt_position(X, Y, key):
    """
Take the negotiation position that X has prepared for Y and encrypt it
using the agreed upon key. Write the encrypted position and a code book
of one-way encryption translations.
"""
    encrypt = OWE.OneWayEncrypt(key)
    
    fname = "%s/player%s/positions/player%s_position.py" % (basepath, X, Y)
    gname = "%s/player%s/positions/x_player%s_position.py" % (basepath, X, Y)
    hname = "%s/player%s/positions/player%s_codebook.py" % (basepath, X, Y)

    # fname is the unencrypted file and gname is the encrypted file writin from it.
    # as the one-way encryption progresses, we save information in a codebook that
    # is written on hname at the end.


    f = open(fname)
    g = open(gname, "w")
    h = open(hname, "w")

    codebook = {}

    # read each line of the negotiation position and evaluate it
    l = f.readline()
    #n = 0
    while l:
        if len(l) < 10 :
            # skip trivial lines, if any.
            l = f.readline()
            continue
        if l[0] == "#":
            # skip comment lines, if any.
            l = f.readline()
            continue
        x = eval(l)
        # BTW, we realize the preceding step is a security danger, however, we are using it
        # as a shortcut for the demo because we have complete control over the input to eval
        # for the demo. That would not be the case in a real application.
        action = x["action"]
        #print "found: ", action 
        if action == "offer":
            encrypt_offer_statement(encrypt, x, g, codebook)
        elif action == "ask":
            encrypt_ask_statement(encrypt, x, g, codebook)
        else:
            print "    *** unrecognize action field: %s " % action
            
##        n += 1
##        if n >= 3:
##            break
        l = f.readline()
        
            

    f.close()
    g.close()
    
    # write the codes
    h.write("#key\n")
    h.write("\"%s\"" % key)
    h.write("\n#codebook\n")
    h.write(str(codebook))
    h.write("\n#float_scale_factors\n")
    h.write(str( encrypt.scale_factors))
    h.write("\n")
    h.close()
    
    
if __name__ == '__main__':
    # first find out who we are from the command line:
    if len(sys.argv) < 2:
        s = "call encrypt_positions with one argument - the player doing the encrypting"
        raise s
    
    X = sys.argv[1]
    if X not in broker.players:
        print "encrypt_positions invoked for player %s who is not on brokers list: " % (X, broker.players)
        raise X
    else:
        print "\nencrypt_positions for player %s\n" % X
    #X = "A"

    # for each player, get the session key and encrypt the position
    for Y in broker.players:
##        if Y != "B":
##            continue
        if X == Y:
            continue
        print "    encrypt %s for %s" % (X, Y)
        key = get_key(X, Y)
        encrypt_position(X, Y, key)