1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
#-*- coding: utf-8 -*-
from aespython import key_expander, aes_cipher, ocb_mode
import json
import base64
class sjcl(ocb_mode.OCBMode):
"""convenience class to wrap the sjcl objects encryption and decryption"""
def __init__(self, key, keylen):
KE = key_expander.KeyExpander(keylen)
expended_key = KE.expand(key)
cipher = aes_cipher.AESCipher(expanded_key)
ocb_mode.OCBMode.__init__(self, cipher, len(key))
@staticmethod
def hex2byte(hexstring):
"""convert a hexstring to a list of bytes"""
return map(ord, hexstring.decode("hex"))
@staticmethod
def byte2hex(byteslist):
"""convert a list of bytes to a hexstring"""
return str(bytearray(byteslist)).encode("hex")
@staticmethod
def pad(b64string):
"""pad a base64 string with = so that its lengh is divisible by 4"""
return b64string + ''.join(['='] * (len(b64string) % 4))
def encrypt_sjclobject(self, plaintext, header):
"""encrypt a message and return in in the sjcl object format"""
tag, ciphertext = ocb_mode.OCBMode.encrypt_block(self, plaintext, header)
sjcl_object = {"iv": base64.b64encode(bytearray(self._iv)).rstrip("="),
"mode": "ocb2",
"ts": 128,
"ct": base64.b64encode(bytearray(ciphertext) +
bytearray(tag)).rstrip("="),
"adata": base64.b64encode(header).rstrip("=")
}
return json.dumps(sjcl_object)
def decrypt_sjclobject(self, objectstring):
"""takes a sjcl object and return a list of bytes."""
sjcl_object = json.loads(objectstring)
iv = map(ord, base64.b64decode(pad(sjcl_object['iv'])))
self.set_iv(iv)
ct = map(ord, base64.b64decode(pad(sjcl_object['ct'])))
try:
header = map(ord, base64.b64decode(pad(sjcl_object['adata'])))
except KeyError:
header = []
#sjcl appends the tag at the end of the cipher text (it's 16 bytes long)
tag = ct[-16:]
ciphertext = ct[:-16]
isValid, plaintext = ocb_mode.OCBMode.decrypt_block(self, header, ciphertext, tag)
if not isValid:
raise Exception("can't authenticate the data")
else:
return plaintext
if __name__=="__main__":
key = sjcl.hex2byte('12538243c49f1c58e6f7b0687bbd65b2')
iv = sjcl.hex2byte('250c3041c00a605a4100e264abbc588b')
sjclmode = sjcl(key, 128)
sjclmode.set_iv(iv)
plaintext = map(ord, "La chaire est triste, hélas ! et j'ai lu \
tous les livres.")
header = bytearray("Mallarmé")
test = sjclmode.encrypt_sjclobject(plaintext, header)
print test
print str(bytearray(sjclmode.decrypt_sjclobject(test)))
|