added a Python demo
This commit is contained in:
		
							parent
							
								
									1b29ce896f
								
							
						
					
					
						commit
						d99b970a8b
					
				
							
								
								
									
										237
									
								
								demos/demo_dynamic.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								demos/demo_dynamic.py
									
									
									
									
									
										Normal file
									
								
							@ -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'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#---------------------------------------------------------------
 | 
			
		||||
#---------------------------------------------------------------
 | 
			
		||||
#---------------------------------------------------------------
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user