11
22
33"""
4- demo_dynamic.py v1
4+ demo_dynamic.py v2
55
66 This program demonstrates Python's use of the dynamic
77 language support additions to LTC, namely access to LTC
1919 load multiple .dylibs, but it does not support this level
2020 of tight coupling between otherwise independent libraries.)
2121
22- My .dylib was created on OSX with the following steps:
23-
24- 1- compile LTC to a .a static lib:
25- CFLAGS="-DLTM_DESC -DUSE_LTM" make
26-
27- 2- link LTC and LTM into a single .dylib:
28- ar2dylib_with tomcrypt tommath
29- where ar2dylib_with is a shell script that combines
30- the LTC .a with the LTM .dylib
22+ My .dylib was created on OSX/macOS with the following:
23+ sudo make -j5 -f makefile.shared \
24+ CFLAGS="-DUSE_TFM -DTFM_DESC -I/usr/local/include" \
25+ EXTRALIBS=/usr/local/lib/libtfm.a install
3126
3227 Reminder: you don't need to bind in a math library unless
33- you are going to use LTC functions that depend
34- on a mathlib. For example, public key crypto
35- needs a mathlib; hashing and symmetric encryption
36- do not.
28+ you are going to use LTC functions that need a
29+ mathlib. For example, public key crypto requires
30+ a mathlib; hashing and symmetric encryption do not.
3731
3832 This code was written for Python 2.7.
3933
4034 Larry Bugbee
41- March 2014
35+ March 2014 v1
36+ August 2017 v2
4237
4338"""
4439
4540
4641from ctypes import *
4742from ctypes .util import find_library
4843
44+ # switches to enable/disable selected output
45+ SHOW_ALL_CONSTANTS = True
46+ SHOW_ALL_SIZES = True
47+ SHOW_SELECTED_CONSTANTS = True
48+ SHOW_SELECTED_SIZES = True
49+ SHOW_BUILD_OPTIONS_ALGS = True
50+ SHOW_SHA256_EXAMPLE = True
51+ SHOW_CHACHA_EXAMPLE = True
52+
53+ print
54+ print (' demo_dynamic.py' )
4955
5056#---------------------------------------------------------------
5157# load the .dylib
5258
5359libname = 'tomcrypt'
5460libpath = find_library (libname )
55-
56- print
57- print (' demo_dynamic.py' )
5861print
5962print (' path to library %s: %s' % (libname , libpath ))
6063
6972# supported sizes. One alternative: these lists may be parsed
7073# and used as needed.
7174
72- if 1 :
75+ if SHOW_ALL_CONSTANTS :
76+ print '-' * 60
7377 print ' all supported constants and their values:'
7478
7579 # get size to allocate for constants output list
8589 print
8690
8791
88- if 1 :
92+ if SHOW_ALL_SIZES :
93+ print '-' * 60
8994 print ' all supported sizes:'
9095
9196 # get size to allocate for sizes output list
105110# get individually named constants and sizes
106111
107112# print selected constants
108- if 1 :
113+ if SHOW_SELECTED_CONSTANTS :
114+ print '-' * 60
109115 print '\n selected constants:'
110116
111117 names = [
122128 print ' %-25s %d' % (name , value )
123129
124130# print selected sizes
125- if 1 :
131+ if SHOW_SELECTED_SIZES :
132+ print '-' * 60
126133 print '\n selected sizes:'
127134
128135 names = [
143150
144151#---------------------------------------------------------------
145152#---------------------------------------------------------------
146- # ctypes getting a list of this build's supported algorithms
147- # and compiler switches
153+ # LibTomCrypt exposes one interesting string that can be accessed
154+ # via Python's ctypes module, "crypt_build_settings", which
155+ # provides a list of this build's compiler switches and supported
156+ # algorithms. If someday LTC exposes other interesting strings,
157+ # they can be found with:
158+ # nm /usr/local/lib/libtomcrypt.dylib | grep " D "
148159
149160def get_named_string (lib , name ):
150161 return c_char_p .in_dll (lib , name ).value
151162
152- if 0 :
153- print '\n %s' % ( ' -'* 60 )
163+ if SHOW_BUILD_OPTIONS_ALGS :
164+ print '-' * 60
154165 print 'This is a string compiled into LTC showing compile '
155166 print 'options and algorithms supported by this build \n '
156167 print get_named_string (LTC , 'crypt_build_settings' )
@@ -160,23 +171,31 @@ def get_named_string(lib, name):
160171
161172#---------------------------------------------------------------
162173#---------------------------------------------------------------
163- # here is an example of how a wrapper can make Python access
164- # more Pythonic
174+ # here is an example of how Python code can be written to access
175+ # LTC's implementation of SHA256 and ChaCha,
165176
166177# - - - - - - - - - - - - -
167- # a wrapper fragment...
178+ # definitions
168179
169180def _get_size (name ):
170181 size = c_int (0 )
171182 rc = LTC .crypt_get_size (name , byref (size ))
183+ if rc != 0 :
184+ raise Exception ('LTC.crypt_get_size(%s) rc = %d' % (name , rc ))
172185 return size .value
173186
174- sha256_state_struct_size = _get_size ('sha256_state' )
175- sha512_state_struct_size = _get_size ('sha512_state' )
187+ def _get_constant (name ):
188+ constant = c_int (0 )
189+ rc = LTC .crypt_get_constant (name , byref (constant ))
190+ if rc != 0 :
191+ raise Exception ('LTC.crypt_get_constant(%s) rc = %d' % (name , rc ))
192+ return constant .value
193+
194+ CRYPT_OK = _get_constant ('CRYPT_OK' )
176195
177196class SHA256 (object ):
178197 def __init__ (self ):
179- self .state = c_buffer (sha256_state_struct_size )
198+ self .state = c_buffer (_get_size ( 'sha256_state' ) )
180199 LTC .sha256_init (byref (self .state ))
181200 def update (self , data ):
182201 LTC .sha256_process (byref (self .state ), data , len (data ))
@@ -185,19 +204,54 @@ def digest(self):
185204 LTC .sha256_done (byref (self .state ), byref (md ))
186205 return md .raw
187206
207+ class ChaCha (object ):
208+ def __init__ (self , key , rounds ):
209+ self .state = c_buffer (_get_size ('chacha_state' ))
210+ self .counter = c_int (1 )
211+ err = LTC .chacha_setup (byref (self .state ), key , len (key ), rounds )
212+ def set_iv32 (self , iv ):
213+ err = LTC .chacha_ivctr32 (byref (self .state ), iv , len (iv ), byref (self .counter ))
214+ if err != CRYPT_OK :
215+ raise Exception ('LTC.chacha_ivctr32() err = %d' % err )
216+ def crypt (self , datain ):
217+ dataout = c_buffer (len (datain ))
218+ err = LTC .chacha_crypt (byref (self .state ), datain , len (datain ), byref (dataout ))
219+ if err != CRYPT_OK :
220+ raise Exception ('LTC.chacha_crypt() err = %d' % err )
221+ return dataout .raw
222+
188223# - - - - - - - - - - - - -
189- # an app fragment...
224+ # a SHA256 app fragment...
190225
191226# from wrapper import * # uncomment in real life
192227
193- data = 'hello world'
228+ if SHOW_SHA256_EXAMPLE :
229+ print '-' * 60
230+ data = 'hello world'
231+
232+ sha256 = SHA256 ()
233+ sha256 .update (data )
234+ md = sha256 .digest ()
235+
236+ template = '\n the SHA256 digest for "%s" is %s \n '
237+ print template % (data , md .encode ('hex' ))
238+
239+ # - - - - - - - - - - - - -
240+ # a ChaCha app fragment...
241+
242+ if SHOW_CHACHA_EXAMPLE :
243+ print '-' * 60
244+ key = 'hownowbrowncow\x00 \x00 ' # exactly 16 or 32 bytes
245+ rounds = 12 # common values: 8, 12, 20
246+ iv = '123456789012' # exactly 12 bytes
247+ plain = 'Kilroy was here, there, and everywhere!'
194248
195- sha256 = SHA256 ( )
196- sha256 . update ( data )
197- md = sha256 . digest ( )
249+ cha = ChaCha ( key , rounds )
250+ cha . set_iv32 ( iv )
251+ cipher = cha . crypt ( plain )
198252
199- template = '\n \n the SHA256 digest for "%s" is %s \n '
200- print template % (data , md .encode ('hex' ))
253+ template = '\n ChaCha%d ciphertext for "%s" is "%s" \n '
254+ print template % (rounds , plain , cipher .encode ('hex' ))
201255
202256
203257
0 commit comments