207 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
 | 
						|
 | 
						|
""" 
 | 
						|
    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 a math library.  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 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
 | 
						|
    
 | 
						|
    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.
 | 
						|
    
 | 
						|
    This code was written for Python 2.7.
 | 
						|
    
 | 
						|
    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 = [
 | 
						|
        'ENDIAN_LITTLE',
 | 
						|
        'ENDIAN_64BITWORD',
 | 
						|
        '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',
 | 
						|
        'rsa_key',
 | 
						|
        'symmetric_CTR',
 | 
						|
        'twofish_key',
 | 
						|
        'ecc_point',
 | 
						|
        'gcm_state',
 | 
						|
        'sha512_state',
 | 
						|
    ]
 | 
						|
    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)
 | 
						|
 | 
						|
 | 
						|
#---------------------------------------------------------------
 | 
						|
#---------------------------------------------------------------
 | 
						|
# 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')
 | 
						|
sha512_state_struct_size = _get_size('sha512_state')
 | 
						|
 | 
						|
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'))
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#---------------------------------------------------------------
 | 
						|
#---------------------------------------------------------------
 | 
						|
#---------------------------------------------------------------
 |