#!/usr/bin/env python #-*- coding: iso8859-15 -*- ########################################################## # CRYPT v0.1 # ########################################################## # Author: Juan Miguel Taboada Godoy # # Date: Szczecin, 02th of march of 2006 # # Description: CRYPTOGAFY library for encrypt/decryption # # # # Codigo fuente bajo licencia GNU/GPL # # Centrologic (Computational Logistic Center) # # http://www.centrologic.com - info@centrologic.com # ########################################################## # Libaries {{{1 import pyDes import GnuPGInterface import types # }}}1 # Cryptography library ## Cryptography library class CRYPTOGRAFY: # Constructor {{{1 def __init__(self): self.methods=[] # }}}1 # Destructor {{{1 def __del__(self): self.methods=[] # }}}1 # Function to encrypt data {{{1 ## Function to encrypt data ## \param self - ## \param string String to encript def encrypt(self,string): # For each method for method in self.methods: # Descomposition of the method (kind,arguments)=method if (kind=="3des"): # Encrypt the string try: string=self.__tripleDes(string,arguments,True) except KeyboardInterrupt: raise except Exception,e: raise MethodError,"TripleDES method encryption error: " % (e) elif (kind=="gnupg"): # Take every field out (origin,destiny,passphrase)=arguments # Encrypt the string string=self.__gnupg(string,origin,destiny,passphrase,True) else: # Unknow method raise MethodError,"Unknow given encryption method" return string # }}}1 # Function to decrypt data {{{1 ## Function to decrypt data ## \param self - ## \param string String to decrypt def decrypt(self,string): # Inversion of the list of methods inverted=[] for method in self.methods: # Insert in the beginning inverted.insert(0,method) # For each method for method in inverted: # Descomposition of the method (kind,arguments)=method if (kind=="3des"): # Decrypt the string try: string=self.__tripleDes(string,arguments,False) except KeyboardInterrupt: raise except Exception,e: raise MethodError,"TripleDES method decryption error: %s" % e elif (kind=="gnupg"): # Take every field out (origin,destiny,passphrase)=arguments # Decrypt the string string=self.__gnupg(string,origin,destiny,passphrase,False) else: # Unknow method raise MethodError,"Unknow given decryption method" return string # }}}1 # Function to load a new method of encryption {{{1 ## Function to load a new method of encryption ## \param self - ## \param method Method name ## \param arguments Arguments needed for the selected method \n ## - 3des: Expect a string of 16 or 24 characters that will be the encription password \n ## - gnupg: Expect a tuple of 3 values (our_pgp_key_id,destination_pgp_key_id,passphrase) ## \warning Using gnupg you must to download the public keys from destination to be sure s catched. This library will not download pgp keys from external servers and it will not ask to do it. def load(self,method,arguments): # Build the method {{{2 if (method=="3des"): # TripleDES, check the type of arguments if (not isinstance(arguments,types.StringType)): # Is not an string raise MethodError,"The given argument is not an string" # Check if the size of the password it is good elif ((len(arguments)!=16)and((len(arguments)!=24))): # If the password is not of the right size raise MethodError,"The given argument is expected to be 16 or 24 characters string" elif (method=="gnupg"): # GnuPG, check the length of arguments if (len(arguments)!=3): # The list is wrong raise MethodError,"The given arguments must to have 3 elements (origin,destiny,passphrase)" # Take data out (origin,destiny,passphrase)=arguments # Check origin if (not self.__is_gpgkey(origin)): # The origin is not a gpgkey ID raise MethodError,"The origin key is not a gpgkey id" # Check destiny if (not self.__is_gpgkey(destiny)): # The destiny is not a gpgkey ID raise MethodError,"The destiny key is not a gpgkey id" # Check passphrase if (not isinstance(passphrase,types.StringType)): # The passphrase is not an string raise MethodError,"The passphrase is not an string" else: # Error: Unknow method raise MethodError,"The given method \"%s\" is unknow by this library" % (method) # }}}2 # Add the new method to the list {{{2 self.methods.append((method,arguments)) # }}}2 # }}}1 # Function to unload the last method from the list {{{1 ## Function to unload the last method from the list ## \param self - def unload(self): self.methods=self.methods[:-1] # }}}1 # Internal function to check if the key is a GPG ID {{{1 ## \internal ## This function check f the pgp key given in string is a valid pgp key id ## \param self - ## \param string PGP key id to check def __is_gpgkey(self,string): # Check that there is a 0 in the beginning if (not (string[0]=='0')): return False # Check that the second character is 'x' if (not (string[1]=='x')): return False # Check that the rest is exactly 8 characters if (not (len(string[2:])==8)): return False # In other case return True # }}}1 # Cryptografy functions {{{1 # TripleDES {{{2 def __tripleDes(self,string,password,encrypt=True): if ((len(password)!=16) and (len(password)!=24)): raise MethodError,"Password must be 16 or 24 characters, now is %d characters" % (len(password)) else: if (encrypt): # Encrypt the string, create key k=pyDes.triple_des(password) # Encrypt the string with the created key neostring=k.encrypt(string,"*") else: # Decrypt the string, create key k=pyDes.triple_des(password) # Decrypt the string with the created key neostring=k.decrypt(string,"*") # Return the new string return neostring # }}}2 # GnuPG {{{2 def __gnupg(self,string,origin,destiny,passphrase,encrypt=True): if (encrypt): # Encrypt the string, create GnuPG object gnupg=GnuPGInterface.GnuPG() # Select default key gnupg.options.default_key=origin # Configure the object gnupg.options.armor=1 gnupg.options.quiet=1 gnupg.options.no_greeting=1 gnupg.options.no_verbose=1 gnupg.options.meta_interactive=0 gnupg.options.extra_args.append('--no-secmem-warning') # Set the destiny gnupg.options.recipients=[destiny] # Set the passphrase gnupg.passphrase=passphrase # Launch GnuPG proc=gnupg.run(['--sign','--encrypt'],create_fhs=['stdin','stdout','stderr']) # Open stdin and introduce the string proc.handles['stdin'].write(string) proc.handles['stdin'].close() # Open stdout and take the result of encryption ciphertext=proc.handles['stdout'].read() proc.handles['stdout'].close() # Open stderr and take the errors on the process errors=proc.handles['stderr'].read() proc.handles['stderr'].close() # Wait for process to finish try: proc.wait() except KeyboardInterrupt: raise except Exception,e: # Relaunch the exception raise MethodError,"GnuPG encryption error: %s (%s)" % (e,errors) # Set the type of the object if (not isinstance(ciphertext,types.StringType)): raise MethodError,"What GnuPG gave back is not a string!" # Return the result return ciphertext else: # Decrypt the string, create GnuPG object gnupg=GnuPGInterface.GnuPG() # Select default key gnupg.options.default_key=destiny # Configure the object gnupg.options.armor=1 gnupg.options.quiet=1 gnupg.options.batch=0 gnupg.options.no_greeting=1 gnupg.options.no_verbose=1 gnupg.options.meta_interactive=0 gnupg.options.extra_args.append('--no-secmem-warning') # Set the destiny #gnupg.options.recipients=['juanmi@centrologic.com'] # Set the passphrase gnupg.passphrase=passphrase # Launch GnuPG proc=gnupg.run(['--decrypt'],create_fhs=['stdin','stdout','stderr']) # Open stdin and introduce the string proc.handles['stdin'].write(string) proc.handles['stdin'].close() # Open stdout and take the result of decryption decrypted=proc.handles['stdout'].read() proc.handles['stdout'].close() # Open stderr and take the errors on the process errors=proc.handles['stderr'].read() proc.handles['stderr'].close() # Wait for process to finish try: proc.wait() except KeyboardInterrupt: raise except Exception,e: # Relaunch the exception raise MethodError,"GnuPG decryption error: %s (%s)" % (e,errors) # Return the result return decrypted # }}}2 # }}}1 # EXCEPTION CLASSES {{{1 # Except (General Exception) {{{2 class Except(Exception): def __init__(self,string): self.string=string def __str__(self): return self.string #}}}2 # IOError (Input/Output Error) {{{2 class IOError(Exception): def __init__(self,string): self.string=string def __str__(self): return self.string # }}}2 # MethodError (The encryp/decryption method produced an error) {{{2 class MethodError(Exception): def __init__(self,string): self.string=string def __str__(self): return self.string # }}}2 # }}}1