فهرست منبع

update demo_dynamic.py

Larry Bugbee 8 سال پیش
والد
کامیت
9f548c9928
1فایلهای تغییر یافته به همراه93 افزوده شده و 39 حذف شده
  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
     language support additions to LTC, namely access to LTC
@@ -19,26 +19,21 @@
     load multiple .dylibs, but it does not support this level
     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
-              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.
 
     Larry Bugbee
-    March 2014
+    March 2014      v1
+    August 2017     v2
 
 """
 
@@ -46,15 +41,23 @@
 from ctypes import *
 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
 
 libname = 'tomcrypt'
 libpath = find_library(libname)
-
-print
-print('  demo_dynamic.py')
 print
 print('  path to library %s: %s' % (libname, libpath))
 
@@ -69,7 +72,8 @@ print
 # supported sizes.  One alternative: these lists may be parsed
 # and used as needed.
 
-if 1:
+if SHOW_ALL_CONSTANTS:
+    print '-'*60
     print '  all supported constants and their values:'
 
     # get size to allocate for constants output list
@@ -85,7 +89,8 @@ if 1:
     print
 
 
-if 1:
+if SHOW_ALL_SIZES:
+    print '-'*60
     print '  all supported sizes:'
 
     # get size to allocate for sizes output list
@@ -105,7 +110,8 @@ if 1:
 # get individually named constants and sizes
 
 # print selected constants
-if 1:
+if SHOW_SELECTED_CONSTANTS:
+    print '-'*60
     print '\n  selected constants:'
 
     names = [
@@ -122,7 +128,8 @@ if 1:
         print '    %-25s  %d' % (name, value)
 
 # print selected sizes
-if 1:
+if SHOW_SELECTED_SIZES:
+    print '-'*60
     print '\n  selected sizes:'
 
     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):
     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 'options and algorithms supported by this build \n'
     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):
     size = c_int(0)
     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
 
-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):
     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))
     def update(self, 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))
         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
 
-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'))