Ver Fonte

added a Python demo

Larry Bugbee há 11 anos atrás
pai
commit
d99b970a8b
1 ficheiros alterados com 237 adições e 0 exclusões
  1. 237 0
      demos/demo_dynamic.py

+ 237 - 0
demos/demo_dynamic.py

@@ -0,0 +1,237 @@
+
+
+""" 
+    demo_dynamic.py                                     v1
+    
+    This program demonstrates Python's use of the dynamic 
+    language support additions to LTC, namely access to LTC 
+    constants, struct and union sizes, and the binding of a 
+    math package to LTC.  Also provided are simple code 
+    fragments to illustrate how one might write a Python 
+    wrapper for LTC and how an app might call the wrapper. 
+    This or a similar model should work for Ruby and other 
+    dynamic languages.
+    
+    This instance uses Python's ctypes and requires a single 
+    .dylib linking together LTC and one or more math libraries.  
+    Building a single .dylib is needed because LTC wants a 
+    fairly tight relationship between itself and the mathlib. 
+    (ctypes can load multiple .dylibs, but it does not support 
+    this level of coupling between those 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 -DTFM_DESC -DUSE_TFM \
+                   -I/usr/local/include" make
+      
+      2- link LTC, LTM and TFM into a single .dylib:
+           ar2dylib_with_and  tomcrypt  tommath  tfm
+         where ar2dylib_with_and is a shell script that combines 
+         the .a with .dylibs for LTM and TFM
+    
+    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 
+              does not.
+    
+    Larry Bugbee
+    March 2014
+
+"""
+
+
+from ctypes import *
+from ctypes.util import find_library
+
+
+#---------------------------------------------------------------
+# load the .dylib
+
+libname = 'tomcrypt'
+libpath = find_library(libname)
+
+print
+print('  demo_dynamic.py')
+print
+print('  path to library %s: %s' % (libname, libpath))
+
+LTC = cdll.LoadLibrary(libpath)
+print('  loaded: %s' % LTC)
+print
+
+
+
+#---------------------------------------------------------------
+# get list of all supported constants followed by a list of all 
+# supported sizes.  One alternative: these lists may be parsed 
+# and used as needed.
+
+if 1:
+    print '  all supported constants and their values:'
+    
+    # get size to allocate for constants output list
+    str_len = c_int(0)
+    ret = LTC.crypt_list_all_constants(None, byref(str_len))
+    print '    need to allocate %d bytes \n' % str_len.value
+    
+    # allocate that size and get (name, size) pairs, each pair
+    # separated by a newline char.
+    names_sizes = c_buffer(str_len.value)
+    ret = LTC.crypt_list_all_constants(names_sizes, byref(str_len))
+    print names_sizes.value
+    print
+    
+    
+if 1:
+    print '  all supported sizes:'
+    
+    # get size to allocate for sizes output list
+    str_len = c_int(0)
+    ret = LTC.crypt_list_all_sizes(None, byref(str_len))
+    print '    need to allocate %d bytes \n' % str_len.value
+    
+    # allocate that size and get (name, size) pairs, each pair
+    # separated by a newline char.
+    names_sizes = c_buffer(str_len.value)
+    ret = LTC.crypt_list_all_sizes(names_sizes, byref(str_len))
+    print names_sizes.value
+    print
+
+
+#---------------------------------------------------------------
+# get individually named constants and sizes
+
+# print selected constants
+if 1:
+    print '\n  selected constants:'
+    
+    names = [
+        'PK_PUBLIC',
+        'MAX_RSA_SIZE',
+        'CTR_COUNTER_BIG_ENDIAN',
+    ]
+    for name in names:
+        const_value = c_int(0)
+        rc = LTC.crypt_get_constant(name, byref(const_value))
+        value = const_value.value
+        print '    %-25s  %d' % (name, value)
+
+# print selected sizes
+if 1:
+    print '\n  selected sizes:'
+    
+    names = [
+        'rijndael_key_struct_size',
+        'rsa_key_struct_size',
+        'symmetric_CTR_struct_size',
+        'twofish_key_struct_size',
+        'ecc_point_struct_size',
+        'gcm_state_struct_size',
+        'sha512_state_struct_size',
+    ]
+    for name in names:
+        size_value = c_int(0)
+        rc = LTC.crypt_get_size(name, byref(size_value))
+        value = size_value.value
+        print '    %-25s  %d' % (name, value)
+
+
+#---------------------------------------------------------------
+# init the selected math package, change to another mathlib, 
+# and change back to the first mathlib
+
+if 1:
+    print '\n  init the selected math package, change, and change again'
+    
+    # show ltm_desc
+    ptr = c_int.in_dll(LTC, 'ltm_desc')
+    print '    ltm_desc:   ', hex(ptr.value)
+    # show tfm_desc
+    ptr = c_int.in_dll(LTC, 'tfm_desc')
+    print '    tfm_desc:   ', hex(ptr.value)
+    # let's see the initial value of ltc_mp
+    ptr = c_int.in_dll(LTC, 'ltc_mp')
+    print '    initial ptr:', hex(ptr.value)
+    
+    # init LTM and show ltc_mp
+    LTC.init_LTM()
+    ptr = c_int.in_dll(LTC, 'ltc_mp')
+    print '    ptr to LTM: ', hex(ptr.value)
+    
+    # init TFM and show ltc_mp
+    LTC.init_TFM()
+    ptr = c_int.in_dll(LTC, 'ltc_mp')
+    print '    ptr to TFM: ', hex(ptr.value)
+    
+    # now change back to LTM
+    LTC.init_LTM()
+    ptr = c_int.in_dll(LTC, 'ltc_mp')
+    print '    ptr to LTM: ', hex(ptr.value)
+
+
+
+#---------------------------------------------------------------
+#---------------------------------------------------------------
+# ctypes getting a list of this build's supported algorithms 
+# and compiler switches
+
+def get_named_string(lib, name):
+    return c_char_p.in_dll(lib, name).value
+
+if 0:
+    print '\n%s' % ('-'*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')
+    print
+
+
+
+#---------------------------------------------------------------
+#---------------------------------------------------------------
+# here is an example of how a wrapper can make Python access 
+# more Pythonic
+
+# - - - - - - - - - - - - -
+# a wrapper fragment...
+
+def _get_size(name):
+    size = c_int(0)
+    rc = LTC.crypt_get_size(name, byref(size))
+    return size.value
+
+sha256_state_struct_size = _get_size('sha256_state_struct_size')
+sha512_state_struct_size = _get_size('sha512_state_struct_size')
+
+class SHA256(object):
+    def __init__(self):
+        self.state = c_buffer(sha256_state_struct_size)
+        LTC.sha256_init(byref(self.state))
+    def update(self, data):
+        LTC.sha256_process(byref(self.state), data, len(data))
+    def digest(self):
+        md = c_buffer(32)
+        LTC.sha256_done(byref(self.state), byref(md))
+        return md.raw
+
+# - - - - - - - - - - - - -
+# an app fragment...
+
+# from wrapper import *         # uncomment in real life
+
+data = 'hello world'
+
+sha256 = SHA256()
+sha256.update(data)
+md = sha256.digest()
+
+template = '\n\n  the SHA256 digest for "%s" is %s \n'
+print template % (data, md.encode('hex'))
+
+
+
+#---------------------------------------------------------------
+#---------------------------------------------------------------
+#---------------------------------------------------------------