[Erp5-report] r43825 kazuhiko - in /erp5/trunk/products/ERP5Security: ./ www/

nobody at svn.erp5.org nobody at svn.erp5.org
Mon Feb 28 17:35:28 CET 2011


Author: kazuhiko
Date: Mon Feb 28 17:35:27 2011
New Revision: 43825

URL: http://svn.erp5.org?rev=43825&view=rev
Log:
introduce AES cipher for much stronger encryption. the old implementation (Cesar cipher) is still kept for backward compatibility, but it is recommended to switch to AES cipher.

Modified:
    erp5/trunk/products/ERP5Security/ERP5KeyAuthPlugin.py
    erp5/trunk/products/ERP5Security/www/ERP5Security_addERP5KeyAuthPlugin.zpt
    erp5/trunk/products/ERP5Security/www/ERP5Security_editERP5KeyAuthPlugin.zpt

Modified: erp5/trunk/products/ERP5Security/ERP5KeyAuthPlugin.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Security/ERP5KeyAuthPlugin.py?rev=43825&r1=43824&r2=43825&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Security/ERP5KeyAuthPlugin.py [utf8] (original)
+++ erp5/trunk/products/ERP5Security/ERP5KeyAuthPlugin.py [utf8] Mon Feb 28 17:35:27 2011
@@ -55,6 +55,70 @@ from Products.ERP5Security.ERP5UserManag
                                                   SUPER_USER,\
                                                   _AuthenticationFailure
 
+from Crypto.Cipher import AES
+from base64 import b16decode, b16encode
+
+class AESCipher:
+  mode = AES.MODE_CFB
+
+  def __init__(self, encryption_key):
+    # AES key must be either 16, 24, or 32 bytes long
+    self.encryption_key = encryption_key.ljust(32)[:32]
+
+  def encrypt(self, login):
+    encryptor = AES.new(self.encryption_key, self.mode)
+    return b16encode(encryptor.encrypt(login.ljust(((len(login)-1)/16+1)*16)))
+
+  def decrypt(self, crypted_login):
+    decryptor = AES.new(self.encryption_key, self.mode)
+    return decryptor.decrypt(b16decode(crypted_login)).rstrip()
+
+# This cipher is weak. Do not use.
+class CesarCipher:
+  block_length = 3
+
+  def __init__(self, encryption_key):
+    self.encryption_key = encryption_key
+    self.encrypted_key = self.transformKey(self.encryption_key);
+
+  def transformKey(self,key):
+    """Transform the key to number for encryption"""
+    encrypt_key = []
+    for letter in key:
+      encrypt_key.append(ord(letter))
+    return encrypt_key
+
+  def encrypt(self, login):
+    crypted_login = ''
+    key_length = len(self.encrypted_key)
+    for i in range(0,len(login)):
+      delta = i % key_length
+      crypted_letter = str(ord(login[i]) + self.encrypted_key[delta])
+      #ord is the inverse of chr() for 8-bit (1111 1111 = 256)
+      #so crypted_letter max id 512
+      #we ajust lenght to be able to decrypt by block
+      crypted_letter = crypted_letter.rjust(self.block_length, '0')
+      crypted_login += crypted_letter
+    return crypted_login
+
+  def decrypt(self, crypted_login):
+    login = ''
+    #check lenght of the string
+    clogin_length = len(crypted_login)
+    if clogin_length % self.block_length != 0:
+      raise ValueError, "Lenght is not good"
+    #decrypt block per block
+    position = 0
+    key_length = len(self.encrypted_key)
+    for block in range(0, clogin_length, self.block_length):
+      delta = position % key_length
+      crypted_letter = crypted_login[block:block + self.block_length]
+      crypted_letter = int(crypted_letter) - self.encrypted_key[delta]
+      letter = chr(crypted_letter)
+      login += letter
+      position += 1
+    return login
+
 class ILoginEncryptionPlugin(Interface):
   """Contract for possible ERP5 Key Auth Plugin"""
 
@@ -70,12 +134,14 @@ manage_addERP5KeyAuthPluginForm = PageTe
     'www/ERP5Security_addERP5KeyAuthPlugin', globals(),
     __name__='manage_addERP5KeyAuthPluginForm')
 
-def addERP5KeyAuthPlugin(dispatcher, id,title=None,\
-                         encryption_key='',cookie_name='',\
+def addERP5KeyAuthPlugin(dispatcher, id, title=None,\
+                         encryption_key='', cipher='AES', cookie_name='',\
                          default_cookie_name='',REQUEST=None):
     """ Add a ERP5KeyAuthPlugin to a Pluggable Auth Service. """
 
-    plugin = ERP5KeyAuthPlugin( id, title,encryption_key,cookie_name,default_cookie_name)
+    plugin = ERP5KeyAuthPlugin(id=id, title=title, encryption_key=encryption_key,
+                               cipher=cipher, cookie_name=cookie_name,
+                               default_cookie_name=default_cookie_name)
     dispatcher._setObject(plugin.getId(), plugin)
 
     if REQUEST is not None:
@@ -103,11 +169,9 @@ class ERP5KeyAuthPlugin(ERP5UserManager,
   meta_type = "ERP5 Key Authentication"
   login_path = 'login_form'
   security = ClassSecurityInfo()
-  block_length = 3
   cookie_name = "__ac_key"
   default_cookie_name = "__ac"
   encryption_key = ''
-  encrypted_key = ''
 
   manage_options = ( ( { 'label': 'Edit',
                           'action': 'manage_editERP5KeyAuthPluginForm', }
@@ -127,7 +191,8 @@ class ERP5KeyAuthPlugin(ERP5UserManager,
                     + CookieAuthHelper._properties[:]
                   )
 
-  def __init__(self, id, title=None, encryption_key='', cookie_name='', default_cookie_name=''):
+  def __init__(self, id, title=None, encryption_key='', cipher='AES',
+               cookie_name='', default_cookie_name=''):
     #Check parameters
     if cookie_name is None or cookie_name == '':
       cookie_name = id
@@ -142,56 +207,27 @@ class ERP5KeyAuthPlugin(ERP5UserManager,
     self.cookie_name = cookie_name
     self.default_cookie_name = default_cookie_name
     self.encryption_key = encryption_key
-    self.encrypted_key = self.transformKey(self.encryption_key);
+    self.cipher = cipher
 
+  def _getCipher(self):
+    # If self.cipher does not exist, we use CesarCipher only for
+    # backward compatibility.
+    return getattr(self, 'cipher', 'Cesar')
 
   ################################
   #    ILoginEncryptionPlugin    #
   ################################
-  security.declarePrivate('transformKey')
-  def transformKey(self,key):
-    """Transform the key to number for encryption"""
-    encrypt_key = []
-    for letter in key:
-      encrypt_key.append(ord(letter))
-    return encrypt_key
-
   security.declarePublic('encrypt')
   def encrypt(self,login):
     """Encrypt the login"""
-    crypted_login = ''
-    key_length = len(self.encrypted_key)
-    for i in range(0,len(login)):
-      delta = i % key_length
-      crypted_letter = str(ord(login[i]) + self.encrypted_key[delta])
-      #ord is the inverse of chr() for 8-bit (1111 1111 = 256)
-      #so crypted_letter max id 512
-      #we ajust lenght to be able to decrypt by block
-      crypted_letter = crypted_letter.rjust(self.block_length, '0')
-      crypted_login += crypted_letter
-
-    return crypted_login
+    cipher = globals()['%sCipher' % self._getCipher()](self.encryption_key)
+    return cipher.encrypt(login)
 
   security.declarePrivate('decrypt')
   def decrypt(self, crypted_login):
     """Decrypt string and return the login"""
-    login = ''
-    #check lenght of the string
-    clogin_length = len(crypted_login)
-    if clogin_length % self.block_length != 0:
-      raise ValueError, "Lenght is not good"
-
-    #decrypt block per block
-    position = 0
-    key_length = len(self.encrypted_key)
-    for block in range(0, clogin_length, self.block_length):
-      delta = position % key_length
-      crypted_letter = crypted_login[block:block + self.block_length]
-      crypted_letter = int(crypted_letter) - self.encrypted_key[delta]
-      letter = chr(crypted_letter)
-      login += letter
-      position += 1
-    return login
+    cipher = globals()['%sCipher' % self._getCipher()](self.encryption_key)
+    return cipher.decrypt(crypted_login)
 
   ####################################
   #ILoginPasswordHostExtractionPlugin#
@@ -360,7 +396,8 @@ class ERP5KeyAuthPlugin(ERP5UserManager,
       __name__='manage_editERP5KeyAuthPluginForm' )
 
   security.declareProtected( ManageUsers, 'manage_editKeyAuthPlugin' )
-  def manage_editKeyAuthPlugin(self, encryption_key,cookie_name,default_cookie_name, RESPONSE=None):
+  def manage_editKeyAuthPlugin(self, encryption_key, cipher, cookie_name,
+                               default_cookie_name, RESPONSE=None):
     """Edit the object"""
     error_message = ''
 
@@ -373,7 +410,12 @@ class ERP5KeyAuthPlugin(ERP5UserManager,
       error_message += 'Invalid key value '
     else:
       self.encryption_key = encryption_key
-      self.encrypted_key = self.transformKey(self.encryption_key);
+
+    #Save cipher
+    if cipher == '' or cipher is None:
+      error_message += 'Invalid cipher value '
+    else:
+      self.cipher = cipher
 
     #Save cookie name
     if cookie_name == '' or cookie_name is None:

Modified: erp5/trunk/products/ERP5Security/www/ERP5Security_addERP5KeyAuthPlugin.zpt
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Security/www/ERP5Security_addERP5KeyAuthPlugin.zpt?rev=43825&r1=43824&r2=43825&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Security/www/ERP5Security_addERP5KeyAuthPlugin.zpt [utf8] (original)
+++ erp5/trunk/products/ERP5Security/www/ERP5Security_addERP5KeyAuthPlugin.zpt [utf8] Mon Feb 28 17:35:27 2011
@@ -39,6 +39,20 @@
   <tr>
     <td align="left" valign="top">
     <div class="form-label">
+    Cipher
+    </div>
+    </td>
+    <td align="left" valign="top">
+    <select name="cipher">
+    <tal:block tal:repeat="c python:[('AES', 'AES'), ('Cesar', 'Cesar (DO NOT USE)')]">
+      <option value="value" tal:attributes="value python:c[0]" tal:content="python:c[1]" />
+    </tal:block>
+    </select>
+    </td>
+  </tr>
+  <tr>
+    <td align="left" valign="top">
+    <div class="form-label">
     Cookie Name
     </div>
     </td>

Modified: erp5/trunk/products/ERP5Security/www/ERP5Security_editERP5KeyAuthPlugin.zpt
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Security/www/ERP5Security_editERP5KeyAuthPlugin.zpt?rev=43825&r1=43824&r2=43825&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Security/www/ERP5Security_editERP5KeyAuthPlugin.zpt [utf8] (original)
+++ erp5/trunk/products/ERP5Security/www/ERP5Security_editERP5KeyAuthPlugin.zpt [utf8] Mon Feb 28 17:35:27 2011
@@ -8,6 +8,7 @@
 <form action="manage_editKeyAuthPlugin" method="POST">
 
 <table tal:define="encryption_key request/encryption_key|context/encryption_key|string:;
+                   cipher request/cipher|context/cipher|string:Cesar;
                    default_cookie_name request/default_cookie_name|context/default_cookie_name|string:;
                    cookie_name request/cookie_name|context/cookie_name|string:;">
 
@@ -19,6 +20,20 @@
    </td>
 </tr>
 <tr>
+  <td align="left" valign="top">
+  <div class="form-label">
+  Cipher
+  </div>
+  </td>
+  <td align="left" valign="top">
+  <select name="cipher">
+  <tal:block tal:repeat="c python:[('AES', 'AES'), ('Cesar', 'Cesar (DO NOT USE)')]">
+    <option value="value" tal:attributes="value python:c[0]; selected python:c[0]==cipher" tal:content="python:c[1]" />
+  </tal:block>
+  </select>
+  </td>
+</tr>
+<tr>
    <td> Cookie Name </td>
    <td>
      <input type="text" name="cookie_name" value=""



More information about the Erp5-report mailing list