Skip to content

Commit 725532c

Browse files
authored
Merge pull request #272 from libtom/update-demos-demo_dynamic.py
Update demos demo dynamic.py - everything is green
2 parents d502c24 + de6ac74 commit 725532c

File tree

2 files changed

+94
-378
lines changed

2 files changed

+94
-378
lines changed

demos/demo_dynamic.py

Lines changed: 94 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22

33
"""
4-
demo_dynamic.py v2b
4+
demo_dynamic.py v2b
55
66
This program demonstrates Python's use of the dynamic
77
language support additions to LTC, namely access to LTC
@@ -33,8 +33,31 @@
3333
mathlib. For example, public key crypto requires
3434
a mathlib; hashing and symmetric encryption do not.
3535
36-
This code was written for Python 2.7 with the ctypes standard
37-
library.
36+
------
37+
38+
This code was originally written for Python 2.7 with the
39+
ctypes standard library. This version is modified to run
40+
under both Python 2.7 and 3.6.
41+
42+
Arguably the biggest change for Python3 has to do with
43+
strings. Under Python2, native strings are ASCII bytes and
44+
passing them to LTC is natural and requires no conversion.
45+
Under Python3 all native strings are Unicode which requires
46+
they be converted to bytes before use by LTC.
47+
48+
Note the following for Python3.
49+
- ASCII keys, IVs and other string arguments must be
50+
'bytes'. Define them with a 'b' prefix or convert
51+
via the 'bytes()' function.
52+
- "strings" returned from LTC are bytes and conversion
53+
to Unicode might be necessary for proper printing.
54+
If so, use <string>.decode('utf-8').
55+
- The Python2 'print' statement becomes a function in
56+
Python3 which requires parenthesis, eg. 'print()'.
57+
58+
NB: Unicode is achieved under Python2 by either defining
59+
a Unicode string with a 'u' prefix or passing ASCII
60+
strings thru the 'unicode()' function.
3861
3962
Larry Bugbee
4063
March 2014 v1
@@ -43,6 +66,7 @@
4366
"""
4467

4568

69+
import sys
4670
from ctypes import *
4771
from ctypes.util import find_library
4872

@@ -55,21 +79,25 @@
5579
SHOW_SHA256_EXAMPLE = True
5680
SHOW_CHACHA_EXAMPLE = True
5781

58-
print
82+
print(' ')
5983
print(' demo_dynamic.py')
6084

85+
def inprint(s, indent=0):
86+
"prints strings indented, including multline strings"
87+
for line in s.split('\n'):
88+
print(' '*indent + line)
6189

6290
#-------------------------------------------------------------------------------
6391
# load the .dylib
6492

6593
libname = 'tomcrypt'
6694
libpath = find_library(libname)
67-
print
95+
print(' ')
6896
print(' path to library %s: %s' % (libname, libpath))
6997

7098
LTC = cdll.LoadLibrary(libpath)
7199
print(' loaded: %s' % LTC)
72-
print
100+
print(' ')
73101

74102

75103
#-------------------------------------------------------------------------------
@@ -78,79 +106,79 @@
78106
# and used as needed.
79107

80108
if SHOW_ALL_CONSTANTS:
81-
print '-'*60
82-
print ' all supported constants and their values:'
109+
print('-'*60)
110+
print(' all supported constants and their values:')
83111

84112
# get size to allocate for constants output list
85113
str_len = c_int(0)
86114
ret = LTC.crypt_list_all_constants(None, byref(str_len))
87-
print ' need to allocate %d bytes to build list \n' % str_len.value
115+
print(' need to allocate %d bytes to build list \n' % str_len.value)
88116

89117
# allocate that size and get (name, size) pairs, each pair
90118
# separated by a newline char.
91119
names_sizes = c_buffer(str_len.value)
92120
ret = LTC.crypt_list_all_constants(names_sizes, byref(str_len))
93-
print names_sizes.value
94-
print
121+
print(names_sizes.value.decode("utf-8"))
122+
print(' ')
95123

96124

97125
if SHOW_ALL_SIZES:
98-
print '-'*60
99-
print ' all supported sizes:'
126+
print('-'*60)
127+
print(' all supported sizes:')
100128

101129
# get size to allocate for sizes output list
102130
str_len = c_int(0)
103131
ret = LTC.crypt_list_all_sizes(None, byref(str_len))
104-
print ' need to allocate %d bytes to build list \n' % str_len.value
132+
print(' need to allocate %d bytes to build list \n' % str_len.value)
105133

106134
# allocate that size and get (name, size) pairs, each pair
107135
# separated by a newline char.
108136
names_sizes = c_buffer(str_len.value)
109137
ret = LTC.crypt_list_all_sizes(names_sizes, byref(str_len))
110-
print names_sizes.value
111-
print
138+
print(names_sizes.value.decode("utf-8"))
139+
print(' ')
112140

113141

114142
#-------------------------------------------------------------------------------
115143
# get individually named constants and sizes
116144

117145
if SHOW_SELECTED_CONSTANTS:
118-
print '-'*60
119-
print '\n selected constants:'
146+
print('-'*60)
147+
print('\n selected constants:')
120148

121149
names = [
122-
'ENDIAN_LITTLE',
123-
'ENDIAN_64BITWORD',
124-
'PK_PUBLIC',
125-
'MAX_RSA_SIZE',
126-
'CTR_COUNTER_BIG_ENDIAN',
150+
b'ENDIAN_LITTLE',
151+
b'ENDIAN_64BITWORD',
152+
b'PK_PUBLIC',
153+
b'MAX_RSA_SIZE',
154+
b'CTR_COUNTER_BIG_ENDIAN',
127155
]
128156
for name in names:
129157
const_value = c_int(0)
130158
rc = LTC.crypt_get_constant(name, byref(const_value))
131159
value = const_value.value
132-
print ' %-25s %d' % (name, value)
133-
print
160+
print(' %-25s %d' % (name.decode("utf-8"), value))
161+
print(' ')
134162

135163
if SHOW_SELECTED_SIZES:
136-
print '-'*60
137-
print '\n selected sizes:'
164+
print('-'*60)
165+
print('\n selected sizes:')
138166

139167
names = [
140-
'rijndael_key',
141-
'rsa_key',
142-
'symmetric_CTR',
143-
'twofish_key',
144-
'ecc_point',
145-
'gcm_state',
146-
'sha512_state',
168+
b'rijndael_key',
169+
b'rsa_key',
170+
b'symmetric_CTR',
171+
b'twofish_key',
172+
b'ecc_point',
173+
b'gcm_state',
174+
b'sha512_state',
147175
]
148176
for name in names:
149177
size_value = c_int(0)
150178
rc = LTC.crypt_get_size(name, byref(size_value))
151179
value = size_value.value
152-
print ' %-25s %d' % (name, value)
153-
print
180+
print(' %-25s %d' % (name.decode("utf-8"), value))
181+
print(' ')
154182

155183

156184
#-------------------------------------------------------------------------------
@@ -163,13 +191,14 @@
163191
# nm /usr/local/lib/libtomcrypt.dylib | grep " D "
164192

165193
def get_named_string(lib, name):
166-
return c_char_p.in_dll(lib, name).value
194+
return c_char_p.in_dll(lib, name).value.decode("utf-8")
167195

168196
if SHOW_BUILD_OPTIONS_ALGS:
169-
print '-'*60
170-
print 'This is a string compiled into LTC showing compile '
171-
print 'options and algorithms supported by this build \n'
172-
print get_named_string(LTC, 'crypt_build_settings')
197+
print('-'*60)
198+
print('This is a string compiled into LTC showing compile')
199+
print('options and algorithms supported by this build \n')
200+
# print(get_named_string(LTC, 'crypt_build_settings'))
201+
inprint(get_named_string(LTC, 'crypt_build_settings'), 4)
173202

174203

175204
#-------------------------------------------------------------------------------
@@ -180,32 +209,34 @@ def get_named_string(lib, name):
180209
# - - - - - - - - - - - - -
181210
# definitions
182211

212+
from binascii import hexlify, unhexlify
213+
214+
def _err2str(err):
215+
# define return type
216+
errstr = LTC.error_to_string
217+
errstr.restype = c_char_p
218+
# get and return err string
219+
return errstr(err)
220+
183221
def _get_size(name):
184222
size = c_int(0)
185-
rc = LTC.crypt_get_size(name, byref(size))
223+
rc = LTC.crypt_get_size(bytes(name), byref(size))
186224
if rc != 0:
187225
raise Exception('LTC.crypt_get_size(%s) rc = %d' % (name, rc))
188226
return size.value
189227

190228
def _get_constant(name):
191229
constant = c_int(0)
192-
rc = LTC.crypt_get_constant(name, byref(constant))
230+
rc = LTC.crypt_get_constant(bytes(name), byref(constant))
193231
if rc != 0:
194232
raise Exception('LTC.crypt_get_constant(%s) rc = %d' % (name, rc))
195233
return constant.value
196234

197-
def _err2str(err):
198-
# define return type
199-
errstr = LTC.error_to_string
200-
errstr.restype = c_char_p
201-
# get and return err string
202-
return errstr(err)
203-
204-
CRYPT_OK = _get_constant('CRYPT_OK')
235+
CRYPT_OK = _get_constant(b'CRYPT_OK')
205236

206237
class SHA256(object):
207238
def __init__(self):
208-
self.state = c_buffer(_get_size('sha256_state'))
239+
self.state = c_buffer(_get_size(b'sha256_state'))
209240
LTC.sha256_init(byref(self.state))
210241
def update(self, data):
211242
LTC.sha256_process(byref(self.state), data, len(data))
@@ -216,7 +247,7 @@ def digest(self):
216247

217248
class ChaCha(object):
218249
def __init__(self, key, rounds):
219-
self.state = c_buffer(_get_size('chacha_state'))
250+
self.state = c_buffer(_get_size(b'chacha_state'))
220251
self.counter = c_int(1)
221252
err = LTC.chacha_setup(byref(self.state), key, len(key), rounds)
222253
if err != CRYPT_OK:
@@ -235,42 +266,39 @@ def crypt(self, datain):
235266
# - - - - - - - - - - - - -
236267
# a SHA256 app fragment
237268

238-
# from wrapper import * # uncomment in real life
239-
240269
if SHOW_SHA256_EXAMPLE:
241-
print '-'*60
242-
data = 'hello world'
270+
print('-'*60)
271+
data = b'hello world' # we want bytes, not Unicode
243272

244273
sha256 = SHA256()
245274
sha256.update(data)
246275
md = sha256.digest()
247276

248277
template = '\n the SHA256 digest for "%s" is %s \n'
249-
print template % (data, md.encode('hex'))
278+
print(template % (data, hexlify(md)))
250279

251280
# - - - - - - - - - - - - -
252281
# a ChaCha app fragment
253282

254283
if SHOW_CHACHA_EXAMPLE:
255-
print '-'*60
256-
key = 'hownowbrowncow\x00\x00' # exactly 16 or 32 bytes
284+
print('-'*60)
285+
key = b'hownowbrowncow\x00\x00' # exactly 16 or 32 bytes
257286
rounds = 12 # common values: 8, 12, 20
258-
iv = '123456789012' # exactly 12 bytes
259-
plain = 'Kilroy was here, there, and everywhere!'
287+
iv = b'123456789012' # exactly 12 bytes
288+
plain = b'Kilroy was here, there, and everywhere!'
260289

261290
cha = ChaCha(key, rounds)
262291
cha.set_iv32(iv)
263292
cipher = cha.crypt(plain)
264293

265294
template = '\n ChaCha%d ciphertext for "%s" is "%s"'
266-
print template % (rounds, plain, cipher.encode('hex'))
295+
print(template % (rounds, plain, hexlify(cipher)))
267296

268-
# reset to decrypt
269-
cha.set_iv32(iv)
297+
cha.set_iv32(iv) # reset to decrypt
270298
decrypted = cha.crypt(cipher)
271299

272300
template = ' ChaCha%d decoded text for "%s" is "%s" \n'
273-
print template % (rounds, plain, decrypted)
301+
print(template % (rounds, plain, decrypted.decode("utf-8")))
274302

275303
# Footnote: Keys should be erased fm memory as soon as possible after use,
276304
# and that includes Python. For a tip on how to do that in Python, see

0 commit comments

Comments
 (0)