#!/usr/bin/env python

"""
    This is a very short demo of Helix.

    Helix: Fast Encryption and Authentication
           by Niels Ferguson and Bruce Schneier
           See DDJ, Nov 2003, p28

    Helix is fast compared to other algorithms.  Besides
    being quick, Helix also provides both ciphertext and an
    authentication digest with a single pass of the data.
    Typically, two passes are required.

    Larry Bugbee
    March 2005
"""

try:
    from xhelix import Helix
    print 'using xhelix'
except:
    from helix import Helix

from time import time
from md5 import md5
from base64 import encodestring, decodestring

def bytestr2hex(bs):
    "returns the hex characters of a given string"
    h = ''
    for c in bs:
        h = h + ('0'+hex(ord(c))[2:])[-2:]
    return h   # .upper()

def md5TimeRandom16():
    "returns a time-based random number stretched by MD5"
    m = md5()
    m.update(str(time()))
    return m.digest()

# need some plaintext (can be binary)
p = 'Hello World!'      # plaintext

# define a secret encryption key, of any length
k = 'aSecretKey'        # encryption key

# generate a unique, one-time only random number (must be
# 16 bytes never before used)
n = md5TimeRandom16()   # nounce 

# define a context and encrypt
h = Helix(k)
c,d = h.encrypt(n,p)    # c = ciphertext, d = digest

# show the values used
print
print '  p:', p
print '  k:', k
print '  n:', bytestr2hex(n)
print '  c:', bytestr2hex(c)
print '  d:', bytestr2hex(d)

# send nounce, ciphertext and digest.  receiver must have the key.
mask = """
<root>
  <message>
    <algorithm name="helix"/>
    <nounce transform="base64">
      %s
    </nounce>
    <ciphertext transform="base64">
      %s
    </ciphertext>
    <digest transform="base64">
      %s
    </digest>
  </message>
</root>
"""
b64n = encodestring(n).strip()
b64c = encodestring(c).strip()
b64d = encodestring(d).strip()
xml = mask % (b64n, b64c, b64d)
print xml


# now let's verify and decrypt
n = decodestring(b64n)     # undo the base64
c = decodestring(b64c)
d = decodestring(b64d)

# d = 'asd'+d[3:]  # to demo a corruption

# define a context and decrypt
h2 = Helix(k)
p2 = h2.decrypt(n,c,d)

# test and print results
if p == p2:
    print '[[[', p2, ']]]  <--<< it worked\n'
else:
    print "\n  *** it didn't work ***\n"