Przeglądaj źródła

update demo_dynamic.py

Larry Bugbee 8 lat temu
rodzic
commit
9f548c9928
1 zmienionych plików z 93 dodań i 39 usunięć
  1. 93 39
      demos/demo_dynamic.py

+ 93 - 39
demos/demo_dynamic.py

@@ -1,7 +1,7 @@
 
 
 
 
 """
 """
-    demo_dynamic.py                                     v1
+    demo_dynamic.py                                     v2
 
 
     This program demonstrates Python's use of the dynamic
     This program demonstrates Python's use of the dynamic
     language support additions to LTC, namely access to LTC
     language support additions to LTC, namely access to LTC
@@ -19,26 +19,21 @@
     load multiple .dylibs, but it does not support this level
     load multiple .dylibs, but it does not support this level
     of tight coupling between otherwise independent libraries.)
     of tight coupling between otherwise independent libraries.)
 
 
-    My .dylib was created on OSX with the following steps:
-
-      1- compile LTC to a .a static lib:
-           CFLAGS="-DLTM_DESC -DUSE_LTM" make
-
-      2- link LTC and LTM into a single .dylib:
-           ar2dylib_with  tomcrypt  tommath
-         where ar2dylib_with is a shell script that combines
-         the LTC .a with the LTM .dylib
+    My .dylib was created on OSX/macOS with the following:
+        sudo make -j5 -f makefile.shared                        \
+            CFLAGS="-DUSE_TFM -DTFM_DESC -I/usr/local/include"  \
+            EXTRALIBS=/usr/local/lib/libtfm.a  install
 
 
     Reminder: you don't need to bind in a math library unless
     Reminder: you don't need to bind in a math library unless
-              you are going to use LTC functions that depend
-              on a mathlib.  For example, public key crypto
-              needs a mathlib; hashing and symmetric encryption
-              do not.
+              you are going to use LTC functions that need a
+              mathlib.  For example, public key crypto requires
+              a mathlib; hashing and symmetric encryption do not.
 
 
     This code was written for Python 2.7.
     This code was written for Python 2.7.
 
 
     Larry Bugbee
     Larry Bugbee
-    March 2014
+    March 2014      v1
+    August 2017     v2
 
 
 """
 """
 
 
@@ -46,15 +41,23 @@
 from ctypes import *
 from ctypes import *
 from ctypes.util import find_library
 from ctypes.util import find_library
 
 
+# switches to enable/disable selected output
+SHOW_ALL_CONSTANTS      = True
+SHOW_ALL_SIZES          = True
+SHOW_SELECTED_CONSTANTS = True
+SHOW_SELECTED_SIZES     = True
+SHOW_BUILD_OPTIONS_ALGS = True
+SHOW_SHA256_EXAMPLE     = True
+SHOW_CHACHA_EXAMPLE     = True
+
+print
+print('  demo_dynamic.py')
 
 
 #---------------------------------------------------------------
 #---------------------------------------------------------------
 # load the .dylib
 # load the .dylib
 
 
 libname = 'tomcrypt'
 libname = 'tomcrypt'
 libpath = find_library(libname)
 libpath = find_library(libname)
-
-print
-print('  demo_dynamic.py')
 print
 print
 print('  path to library %s: %s' % (libname, libpath))
 print('  path to library %s: %s' % (libname, libpath))
 
 
@@ -69,7 +72,8 @@ print
 # supported sizes.  One alternative: these lists may be parsed
 # supported sizes.  One alternative: these lists may be parsed
 # and used as needed.
 # and used as needed.
 
 
-if 1:
+if SHOW_ALL_CONSTANTS:
+    print '-'*60
     print '  all supported constants and their values:'
     print '  all supported constants and their values:'
 
 
     # get size to allocate for constants output list
     # get size to allocate for constants output list
@@ -85,7 +89,8 @@ if 1:
     print
     print
 
 
 
 
-if 1:
+if SHOW_ALL_SIZES:
+    print '-'*60
     print '  all supported sizes:'
     print '  all supported sizes:'
 
 
     # get size to allocate for sizes output list
     # get size to allocate for sizes output list
@@ -105,7 +110,8 @@ if 1:
 # get individually named constants and sizes
 # get individually named constants and sizes
 
 
 # print selected constants
 # print selected constants
-if 1:
+if SHOW_SELECTED_CONSTANTS:
+    print '-'*60
     print '\n  selected constants:'
     print '\n  selected constants:'
 
 
     names = [
     names = [
@@ -122,7 +128,8 @@ if 1:
         print '    %-25s  %d' % (name, value)
         print '    %-25s  %d' % (name, value)
 
 
 # print selected sizes
 # print selected sizes
-if 1:
+if SHOW_SELECTED_SIZES:
+    print '-'*60
     print '\n  selected sizes:'
     print '\n  selected sizes:'
 
 
     names = [
     names = [
@@ -143,14 +150,18 @@ if 1:
 
 
 #---------------------------------------------------------------
 #---------------------------------------------------------------
 #---------------------------------------------------------------
 #---------------------------------------------------------------
-# ctypes getting a list of this build's supported algorithms
-# and compiler switches
+# LibTomCrypt exposes one interesting string that can be accessed
+# via Python's ctypes module, "crypt_build_settings", which
+# provides a list of this build's compiler switches and supported
+# algorithms.  If someday LTC exposes other interesting strings,
+# they can be found with:
+#   nm /usr/local/lib/libtomcrypt.dylib | grep " D "
 
 
 def get_named_string(lib, name):
 def get_named_string(lib, name):
     return c_char_p.in_dll(lib, name).value
     return c_char_p.in_dll(lib, name).value
 
 
-if 0:
-    print '\n%s' % ('-'*60)
+if SHOW_BUILD_OPTIONS_ALGS:
+    print '-'*60
     print 'This is a string compiled into LTC showing compile '
     print 'This is a string compiled into LTC showing compile '
     print 'options and algorithms supported by this build \n'
     print 'options and algorithms supported by this build \n'
     print get_named_string(LTC, 'crypt_build_settings')
     print get_named_string(LTC, 'crypt_build_settings')
@@ -160,23 +171,31 @@ if 0:
 
 
 #---------------------------------------------------------------
 #---------------------------------------------------------------
 #---------------------------------------------------------------
 #---------------------------------------------------------------
-# here is an example of how a wrapper can make Python access
-# more Pythonic
+# here is an example of how Python code can be written to access
+# LTC's implementation of SHA256 and ChaCha,
 
 
 # - - - - - - - - - - - - -
 # - - - - - - - - - - - - -
-# a wrapper fragment...
+# definitions
 
 
 def _get_size(name):
 def _get_size(name):
     size = c_int(0)
     size = c_int(0)
     rc = LTC.crypt_get_size(name, byref(size))
     rc = LTC.crypt_get_size(name, byref(size))
+    if rc != 0:
+        raise Exception('LTC.crypt_get_size(%s) rc = %d' % (name, rc))
     return size.value
     return size.value
 
 
-sha256_state_struct_size = _get_size('sha256_state')
-sha512_state_struct_size = _get_size('sha512_state')
+def _get_constant(name):
+    constant = c_int(0)
+    rc = LTC.crypt_get_constant(name, byref(constant))
+    if rc != 0:
+        raise Exception('LTC.crypt_get_constant(%s) rc = %d' % (name, rc))
+    return constant.value
+
+CRYPT_OK = _get_constant('CRYPT_OK')
 
 
 class SHA256(object):
 class SHA256(object):
     def __init__(self):
     def __init__(self):
-        self.state = c_buffer(sha256_state_struct_size)
+        self.state = c_buffer(_get_size('sha256_state'))
         LTC.sha256_init(byref(self.state))
         LTC.sha256_init(byref(self.state))
     def update(self, data):
     def update(self, data):
         LTC.sha256_process(byref(self.state), data, len(data))
         LTC.sha256_process(byref(self.state), data, len(data))
@@ -185,19 +204,54 @@ class SHA256(object):
         LTC.sha256_done(byref(self.state), byref(md))
         LTC.sha256_done(byref(self.state), byref(md))
         return md.raw
         return md.raw
 
 
+class ChaCha(object):
+    def __init__(self, key, rounds):
+        self.state   = c_buffer(_get_size('chacha_state'))
+        self.counter = c_int(1)
+        err = LTC.chacha_setup(byref(self.state), key, len(key), rounds)
+    def set_iv32(self, iv):
+        err = LTC.chacha_ivctr32(byref(self.state), iv, len(iv), byref(self.counter))
+        if err != CRYPT_OK:
+            raise Exception('LTC.chacha_ivctr32() err = %d' % err)
+    def crypt(self, datain):
+        dataout = c_buffer(len(datain))
+        err = LTC.chacha_crypt(byref(self.state), datain, len(datain), byref(dataout))
+        if err != CRYPT_OK:
+            raise Exception('LTC.chacha_crypt() err = %d' % err)
+        return dataout.raw
+
 # - - - - - - - - - - - - -
 # - - - - - - - - - - - - -
-# an app fragment...
+# a SHA256 app fragment...
 
 
 # from wrapper import *         # uncomment in real life
 # from wrapper import *         # uncomment in real life
 
 
-data = 'hello world'
+if SHOW_SHA256_EXAMPLE:
+    print '-'*60
+    data = 'hello world'
+
+    sha256 = SHA256()
+    sha256.update(data)
+    md = sha256.digest()
+
+    template = '\n  the SHA256 digest for "%s" is %s \n'
+    print template % (data, md.encode('hex'))
+
+# - - - - - - - - - - - - -
+# a ChaCha app fragment...
+
+if SHOW_CHACHA_EXAMPLE:
+    print '-'*60
+    key     = 'hownowbrowncow\x00\x00'  # exactly 16 or 32 bytes
+    rounds  = 12                        # common values: 8, 12, 20
+    iv      = '123456789012'            # exactly 12 bytes
+    plain   = 'Kilroy was here, there, and everywhere!'
 
 
-sha256 = SHA256()
-sha256.update(data)
-md = sha256.digest()
+    cha = ChaCha(key, rounds)
+    cha.set_iv32(iv)
+    cipher = cha.crypt(plain)
 
 
-template = '\n\n  the SHA256 digest for "%s" is %s \n'
-print template % (data, md.encode('hex'))
+    template = '\n  ChaCha%d ciphertext for "%s" is "%s" \n'
+    print template % (rounds, plain, cipher.encode('hex'))