Re: Python 3.0 support

"C. Collis" <[email protected]> Wed, 24 Dec 2008 14:42:27 +0100
Newsgroups gmane.comp.python.cryptography
Message-ID <LISTSERV%[email protected]>
--part-u-1AEx-jqkGmW1FXj8cD2qa16iAe-apXDSZnXkM-SvthA
Content-Transfer-Encoding: 7bit
Content-Type: multipart/mixed; charset="windows-1252"; boundary="part-RFQ9TAUYFJKyzBZ-7XleK-rAN-J88gECEbd-ru4-3gfUp"

This is a multi-part message in MIME format.

--part-RFQ9TAUYFJKyzBZ-7XleK-rAN-J88gECEbd-ru4-3gfUp
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="windows-1252"

Hmm, attaching the patch didn't work (Google Chrome). Trying again with I=
E.

Chris



--part-RFQ9TAUYFJKyzBZ-7XleK-rAN-J88gECEbd-ru4-3gfUp--

--part-u-1AEx-jqkGmW1FXj8cD2qa16iAe-apXDSZnXkM-SvthA
Content-Transfer-Encoding: 7bit
Content-Type: APPLICATION/OCTET-STREAM;
 name="python30.patch"

Index: M2Crypto/EVP.py
===================================================================
--- M2Crypto/EVP.py	(revision 659)
+++ M2Crypto/EVP.py	(working copy)
@@ -102,7 +102,7 @@
 
     m2_cipher_ctx_free = m2.cipher_ctx_free
 
-    def __init__(self, alg, key, iv, op, key_as_bytes=0, d='md5', salt='12345678', i=1):
+    def __init__(self, alg, key, iv, op, key_as_bytes=0, d='md5', salt='12345678', i=1, padding=True):
         cipher = getattr(m2, alg, None)
         if cipher is None:
             raise ValueError, ('unknown cipher', alg)
@@ -114,6 +114,7 @@
             key = m2.bytes_to_key(self.cipher, kmd(), key, salt, iv, i)
         self.ctx=m2.cipher_ctx_new()
         m2.cipher_init(self.ctx, self.cipher, key, iv, op)
+        self.set_padding(padding)
         del key
         
     def __del__(self):
@@ -126,7 +127,13 @@
     def final(self):
         return m2.cipher_final(self.ctx)
 
+    def set_padding(self, enabled=True):
+        padding = 0
+        if enabled:
+            padding = 1
 
+        return m2.cipher_set_padding(self.ctx, padding) 
+
 class PKey:
     """
     Public Key
Index: M2Crypto/m2.py
===================================================================
--- M2Crypto/m2.py	(revision 659)
+++ M2Crypto/m2.py	(working copy)
@@ -25,7 +25,7 @@
 Copyright (C) 2004 OSAF. All Rights Reserved.
 """
 
-from __m2crypto import *
+from m2crypto import *
 lib_init()
 
 
Index: M2Crypto/RSA.py
===================================================================
--- M2Crypto/RSA.py	(revision 659)
+++ M2Crypto/RSA.py	(working copy)
@@ -160,6 +160,64 @@
     def check_key(self):
         return m2.rsa_check_key(self.rsa)
 
+    def sign_rsassa_pss(self, digest, hash_algo='sha1', salt_length=20):
+        """
+        Signs a digest with the private key using RSASSA-PSS
+
+        @type digest: str
+        @param digest: A digest created by using the digest method
+
+        @type salt_length: int
+        @param salt_length: The length of the salt to use
+        
+        @type hash_algo: str
+        @param hash_algo: The hash algorithm to use
+        Legal values are 'sha1','sha224', 'sha256', 'ripemd160', 
+        and 'md5'.
+
+        @return: a string which is the signature
+        """
+        hash = getattr(m2, hash_algo, None)
+
+        if hash is None:
+            raise RSAError, 'not such hash algorithm %s' % hash_algo 
+
+        signature = m2.rsa_padding_add_pkcs1_pss(self.rsa, digest, hash(), salt_length)
+        
+        return self.private_encrypt(signature, m2.no_padding) 
+
+
+    def verify_rsassa_pss(self, data, signature, hash_algo='sha1', salt_length=20):
+        """
+        Verifies the signature RSASSA-PSS
+
+        @type data: str
+        @param data: Data that has been signed
+
+        @type signature: str
+        @param signature: The signature signed with RSASSA-PSS
+        
+        @type salt_length: int
+        @param salt_length: The length of the salt that was used
+
+        @type hash_algo: str
+        @param hash_algo: The hash algorithm to use
+        Legal values are 'sha1','sha224', 'sha256', 'ripemd160', 
+        and 'md5'.
+
+        @return: True or False, depending on whether the signature was
+        verified.  
+        """
+        hash = getattr(m2, hash_algo, None)
+
+        if hash is None:
+            raise RSAError, 'not such hash algorithm %s' % hash_algo 
+
+        plain_signature = self.public_decrypt(signature, m2.no_padding)
+         
+        return m2.rsa_verify_pkcs1_pss(self.rsa, data, plain_signature, hash(), salt_length)
+
+
     def sign(self, digest, algo='sha1'):
         """
         Signs a digest with the private key
Index: setup.py
===================================================================
--- setup.py	(revision 659)
+++ setup.py	(working copy)
@@ -37,7 +37,7 @@
         # command line option
         if os.name == 'nt':
             self.libraries = ['ssleay32', 'libeay32']
-            self.openssl = 'c:\\pkg'
+            self.openssl = 'c:\\\openssl'
         else:
             self.libraries = ['ssl', 'crypto']
             self.openssl = '/usr'
Index: SWIG/_aes.i
===================================================================
--- SWIG/_aes.i	(revision 659)
+++ SWIG/_aes.i	(working copy)
@@ -76,7 +76,12 @@
         AES_encrypt((const unsigned char *)in, out, key);
     else
         AES_decrypt((const unsigned char *)in, out, key);
-    return PyString_FromStringAndSize(out, outlen);
+
+#if PY_MAJOR_VERSION >= 3
+    return PyBytes_FromStringAndSize(out, outlen);
+#else
+	return PyString_FromStringAndSize(out, outlen);
+#endif // PY_MAJOR_VERSION >= 3
 }
 
 int AES_type_check(AES_KEY *key) {
Index: SWIG/_asn1.i
===================================================================
--- SWIG/_asn1.i	(revision 659)
+++ SWIG/_asn1.i	(working copy)
@@ -38,17 +38,28 @@
 extern void ASN1_STRING_free( ASN1_STRING *);
 
 %typemap(in) (const void *, int) { 
+#if PY_MAJOR_VERSION >= 3
+    if (PyBytes_Check($input)) {
+        Py_ssize_t len;
+
+        $1 = PyBytes_AsString($input); 
+        len = PyBytes_Size($input);
+#else 
     if (PyString_Check($input)) {
         Py_ssize_t len;
 
         $1 = PyString_AsString($input); 
         len = PyString_Size($input);
+
+#endif // PY_MAJOR_VERSION >= 3
+
         if (len > INT_MAX) {
             PyErr_SetString(PyExc_ValueError, "object too large");
             return NULL;
         }
         $2 = len;
-    } else {
+    } 
+	else {
         PyErr_SetString(PyExc_TypeError, "expected string");
         return NULL;
     }
Index: SWIG/_bio.i
===================================================================
--- SWIG/_bio.i	(revision 659)
+++ SWIG/_bio.i	(working copy)
@@ -87,7 +87,13 @@
         Py_INCREF(Py_None);
         return Py_None;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    blob = PyBytes_FromStringAndSize(buf, r);
+#else
     blob = PyString_FromStringAndSize(buf, r);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(buf);
     return blob;
 }
@@ -113,7 +119,13 @@
         Py_INCREF(Py_None);
         return Py_None;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    blob = PyBytes_FromStringAndSize(buf, r);
+#else
     blob = PyString_FromStringAndSize(buf, r);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(buf);
     return blob;
 }
Index: SWIG/_bn.i
===================================================================
--- SWIG/_bn.i	(revision 659)
+++ SWIG/_bn.i	(working copy)
@@ -53,7 +53,12 @@
     char *randhex, *rangehex;
     
     /* Wow, it's a lot of work to convert into a hex string in C! */
-    format = PyString_FromString("%x");
+#if PY_MAJOR_VERSION >= 3
+    format = PyUnicode_FromString("%x");
+#else
+	format = PyString_FromString("%x");
+#endif // PY_MAJOR_VERSION >= 3
+
     if (!format) {
         return NULL;
     }
@@ -65,16 +70,27 @@
     }
     Py_INCREF(range);
     PyTuple_SET_ITEM(tuple, 0, range);
+
+#if PY_MAJOR_VERSION >= 3
+    rangePyString = PyUnicode_Format(format, tuple);
+#else
     rangePyString = PyString_Format(format, tuple);
+#endif // PY_MAJOR_VERSION >= 3
+
     if (!rangePyString) {
-        PyErr_SetString(PyExc_Exception, "PyString_Format failed");    
+        PyErr_SetString(PyExc_Exception, "String Format failed");    
         Py_DECREF(format);
         Py_DECREF(tuple);
         return NULL;    
     }
     Py_DECREF(format);
     Py_DECREF(tuple);
+
+#if PY_MAJOR_VERSION >= 3
+    rangehex = PyUnicode_AsUTF8String(rangePyString);
+#else
     rangehex = PyString_AsString(rangePyString);
+#endif // PY_MAJOR_VERSION >= 3
     
     if (!BN_hex2bn(&rng, rangehex)) {
         /*Custom errors?*/
Index: SWIG/_dh.i
===================================================================
--- SWIG/_dh.i	(revision 659)
+++ SWIG/_dh.i	(working copy)
@@ -103,7 +103,13 @@
         PyErr_SetString(_dh_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
-    ret = PyString_FromStringAndSize((const char *)key, klen);
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize((const char *)key, klen);
+#else
+	ret = PyString_FromStringAndSize((const char *)key, klen);
+#endif // PY_MAJOR_VERSION >= 3
+
     BN_free(pk);
     PyMem_Free(key);
     return ret;
Index: SWIG/_dsa.i
===================================================================
--- SWIG/_dsa.i	(revision 659)
+++ SWIG/_dsa.i	(working copy)
@@ -284,7 +284,13 @@
         PyMem_Free(sigbuf);
         return NULL;
     }
-    ret = PyString_FromStringAndSize(sigbuf, siglen);
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(sigbuf, siglen);
+#else
+	ret = PyString_FromStringAndSize(sigbuf, siglen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(sigbuf);
     return ret;
 }
Index: SWIG/_ec.i
===================================================================
--- SWIG/_ec.i	(revision 659)
+++ SWIG/_ec.i	(working copy)
@@ -174,6 +174,9 @@
     /* Create a PyBuffer containing a copy of the binary,
      * to simplify memory deallocation
      */
+#if PY_MAJOR_VERSION >= 3
+    pyo = PyBytes_FromStringAndSize( src, src_len );
+#else
     pyo = PyBuffer_New( src_len );
     ret = PyObject_AsWriteBuffer( pyo, &dst, &dst_len );
     assert( src_len == dst_len );
@@ -185,6 +188,9 @@
         return NULL;
     }
     memcpy( dst, src, src_len );
+
+#endif // PY_MAJOR_VERSION >= 3
+
     OPENSSL_free(src);
 
     return pyo;
@@ -312,7 +318,12 @@
         PyMem_Free(sigbuf);
         return NULL;
     }
-    ret = PyString_FromStringAndSize(sigbuf, siglen);
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(sigbuf, siglen);
+#else
+	ret = PyString_FromStringAndSize(sigbuf, siglen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(sigbuf);
     return ret;
 }
@@ -359,7 +370,12 @@
         return NULL;
     }
 
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize((const char *)sharedkey, sharedkeylen);
+#else
     ret = PyString_FromStringAndSize((const char *)sharedkey, sharedkeylen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(sharedkey);
     
     return ret;
Index: SWIG/_evp.i
===================================================================
--- SWIG/_evp.i	(revision 659)
+++ SWIG/_evp.i	(working copy)
@@ -127,6 +127,8 @@
 %rename(aes_256_ofb) EVP_aes_256_ofb;
 extern const EVP_CIPHER *EVP_aes_256_ofb(void);
 
+%rename(cipher_set_padding) EVP_CIPHER_CTX_set_padding;
+extern int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);
 %rename(pkey_new) EVP_PKEY_new;
 extern EVP_PKEY *EVP_PKEY_new(void);
 %rename(pkey_free) EVP_PKEY_free;
@@ -177,7 +179,11 @@
 
     PKCS5_PBKDF2_HMAC_SHA1(passbuf, passlen, saltbuf, saltlen, iter,
                            keylen, key);
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(key, keylen);
+#else
     ret = PyString_FromStringAndSize(key, keylen);
+#endif // PY_MAJOR_VERSION >= 3 
     OPENSSL_cleanse(key, keylen);
     return ret;
 }
@@ -219,7 +225,13 @@
         PyErr_SetString(_evp_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(blob, blen);
+#else
     ret = PyString_FromStringAndSize(blob, blen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(blob);
     return ret;
 }
@@ -274,7 +286,13 @@
         return NULL;
     }
     HMAC_Final(ctx, blob, (unsigned int *)&blen);
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(blob, blen);
+#else
     ret = PyString_FromStringAndSize(blob, blen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(blob);
     return ret;
 }
@@ -297,7 +315,13 @@
     }
     HMAC(md, kbuf, klen, dbuf, dlen, blob, &blen);
     blob = PyMem_Realloc(blob, blen);
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(blob, blen);
+#else
     ret = PyString_FromStringAndSize(blob, blen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(blob);
     return ret;
 }
@@ -336,7 +360,13 @@
     klen = EVP_BytesToKey(cipher, md, (unsigned char *)sbuf, 
         (unsigned char *)dbuf, dlen, iter, 
         key, NULL); /* Since we are not returning IV no need to derive it */
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(key, klen);
+#else
     ret = PyString_FromStringAndSize(key, klen);
+#endif // PY_MAJOR_VERSION >= 3
+
     return ret;
 }
 
@@ -376,7 +406,13 @@
         PyErr_SetString(_evp_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(obuf, olen);
+#else
     ret = PyString_FromStringAndSize(obuf, olen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(obuf);
     return ret;
 }
@@ -395,7 +431,13 @@
         PyErr_SetString(_evp_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(obuf, olen);
+#else
     ret = PyString_FromStringAndSize(obuf, olen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(obuf);
     return ret;
 }
@@ -432,7 +474,13 @@
         PyErr_SetString(_evp_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(sigbuf, siglen);
+#else
     ret = PyString_FromStringAndSize(sigbuf, siglen);
+#endif // PY_MAJOR_VERSION >= 3
+
     OPENSSL_cleanse(sigbuf, siglen);
     OPENSSL_free(sigbuf);
     return ret;
@@ -501,7 +549,13 @@
         PyErr_SetString(PyExc_ValueError, "EVP_PKEY as DER failed");
         return NULL; 
     }
+
+#if PY_MAJOR_VERSION >= 3
+    der = PyBytes_FromStringAndSize(pp, len);
+#else
     der = PyString_FromStringAndSize(pp, len);
+#endif // PY_MAJOR_VERSION >= 3
+
     OPENSSL_free(pp);
     return der;
 }
@@ -533,7 +587,13 @@
                 return NULL;
             }
             BIO_get_mem_ptr(bio, &bptr);
+
+#if PY_MAJOR_VERSION >= 3
+            ret = PyBytes_FromStringAndSize(bptr->data, bptr->length);
+#else
             ret = PyString_FromStringAndSize(bptr->data, bptr->length);
+#endif // PY_MAJOR_VERSION >= 3
+
             BIO_set_close(bio, BIO_CLOSE);
             BIO_free(bio);
             RSA_free(rsa);
@@ -558,7 +618,13 @@
                 return NULL;
             }
             BIO_get_mem_ptr(bio, &bptr);
+
+#if PY_MAJOR_VERSION >= 3
+            ret = PyBytes_FromStringAndSize(bptr->data, bptr->length);
+#else
             ret = PyString_FromStringAndSize(bptr->data, bptr->length);
+#endif // PY_MAJOR_VERSION >= 3
+
             BIO_set_close(bio, BIO_CLOSE);
             BIO_free(bio);
             DSA_free(dsa);
Index: SWIG/_lib.i
===================================================================
--- SWIG/_lib.i	(revision 659)
+++ SWIG/_lib.i	(working copy)
@@ -74,7 +74,12 @@
     int ret;
     Py_ssize_t len2;
 
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_AsStringAndSize(obj, s, &len2);
+#else
     ret = PyString_AsStringAndSize(obj, s, &len2);
+#endif // PY_MAJOR_VERSION >= 3
+
     if (ret)
        return ret;
     if (len2 > INT_MAX) {
@@ -132,7 +137,13 @@
     
         _x509_store_ctx_swigptr = SWIG_NewPointerObj((void *)ctx, SWIGTYPE_p_X509_STORE_CTX, 0);
         _x509_store_ctx_obj = Py_BuildValue("(Oi)", _x509_store_ctx_swigptr, 0);
+
+#if PY_MAJOR_VERSION >= 3
+        _x509_store_ctx_inst = PyType_GenericNew(_klass, _x509_store_ctx_obj, NULL);
+#else
         _x509_store_ctx_inst = PyInstance_New(_klass, _x509_store_ctx_obj, NULL);
+#endif // PY_MAJOR_VERSION >= 3
+
         argv = Py_BuildValue("(iO)", ok, _x509_store_ctx_inst);
     } else {
         if (PyErr_Warn(PyExc_DeprecationWarning, "Old style callback, use cb_func(ok, store) instead")) {
@@ -279,6 +290,16 @@
     if (ret == NULL) {
         return -1;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    if (!PyBytes_Check(ret)) {
+        Py_DECREF(ret);
+        return -1;
+    }
+    if ((len = PyBytes_Size(ret)) > num)
+        len = num;
+    str = PyBytes_AsString(ret); 
+#else
     if (!PyString_Check(ret)) {
         Py_DECREF(ret);
         return -1;
@@ -286,6 +307,8 @@
     if ((len = PyString_Size(ret)) > num)
         len = num;
     str = PyString_AsString(ret); 
+#endif // PY_MAJOR_VERSION >= 3
+
     for (i = 0; i < len; i++)
         buf[i] = str[i];
     Py_DECREF(ret);
@@ -314,7 +337,13 @@
         return NULL;
     }
     len=BN_bn2mpi(bn, mpi);
+
+#if PY_MAJOR_VERSION >= 3
+    pyo=PyBytes_FromStringAndSize((const char *)mpi, len);
+#else
     pyo=PyString_FromStringAndSize((const char *)mpi, len);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(mpi);
     return pyo;
 }
@@ -340,7 +369,13 @@
       return NULL;
     }
     BN_bn2bin(bn, bin);
+
+#if PY_MAJOR_VERSION >= 3
+    pyo=PyBytes_FromStringAndSize((const char *)bin, len);
+#else
     pyo=PyString_FromStringAndSize((const char *)bin, len);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(bin);
     return pyo;
 }
@@ -368,7 +403,13 @@
         return NULL;    
     }
     len = strlen(hex);
+
+#if PY_MAJOR_VERSION >= 3
+    pyo=PyBytes_FromStringAndSize(hex, len);
+#else
     pyo=PyString_FromStringAndSize(hex, len);
+#endif // PY_MAJOR_VERSION >= 3
+
     OPENSSL_free(hex);
     return pyo;
 }
@@ -422,11 +463,20 @@
 %typemap(in) Blob * {
     Py_ssize_t len;
 
+#if PY_MAJOR_VERSION >= 3
+    if (!PyBytes_Check($input)) {
+        PyErr_SetString(PyExc_TypeError, "expected PyString");
+        return NULL;
+    }
+    len=PyBytes_Size($input);
+#else
     if (!PyString_Check($input)) {
         PyErr_SetString(PyExc_TypeError, "expected PyString");
         return NULL;
     }
     len=PyString_Size($input);
+#endif // PY_MAJOR_VERSION >= 3
+
     if (len > INT_MAX) {
         PyErr_SetString(PyExc_ValueError, "object too large");
         return -1;
@@ -436,7 +486,13 @@
         PyErr_SetString(PyExc_MemoryError, "malloc Blob");
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    $1->data=(unsigned char *)PyBytes_AsString($input);
+#else
     $1->data=(unsigned char *)PyString_AsString($input);
+#endif // PY_MAJOR_VERSION >= 3
+
     $1->len=len;
 }
 
@@ -445,18 +501,28 @@
         Py_INCREF(Py_None);
         $result=Py_None;
     } else {
+
+#if PY_MAJOR_VERSION >= 3
+        $result=PyBytes_FromStringAndSize((const char *)$1->data, $1->len);
+#else
         $result=PyString_FromStringAndSize((const char *)$1->data, $1->len);
+#endif // PY_MAJOR_VERSION >= 3
+
         PyMem_Free($1->data);
         PyMem_Free($1);
     }
 }
 
 %typemap(in) FILE * {
+#if PY_MAJOR_VERSION >= 3
+    $1=PyObject_AsFileDescriptor($input);
+#else
     if (!PyFile_Check($input)) {
         PyErr_SetString(PyExc_TypeError, "expected PyFile");
         return NULL;
     }
     $1=PyFile_AsFile($input);
+#endif // PY_MAJOR_VERSION >= 3
 }
 
 %typemap(in) PyObject *pyfunc {
@@ -468,7 +534,12 @@
 }
 
 %typemap(in) PyObject *pyblob {
+#if PY_MAJOR_VERSION >= 3
+    if (!PyBytes_Check($input)) {
+#else
     if (!PyString_Check($input)) {
+#endif // PY_MAJOR_VERSION >= 3
+
         PyErr_SetString(PyExc_TypeError, "expected PyString");
         return NULL;
     }
Index: SWIG/_objects.i
===================================================================
--- SWIG/_objects.i	(revision 659)
+++ SWIG/_objects.i	(working copy)
@@ -93,7 +93,13 @@
 
     buf = PyMem_Malloc(len + 1);
     len = OBJ_obj2txt(buf, len + 1, obj, no_name);
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(buf, len);
+#else
     ret = PyString_FromStringAndSize(buf, len);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(buf);
 
     return ret;
Index: SWIG/_pkcs7.i
===================================================================
--- SWIG/_pkcs7.i	(revision 659)
+++ SWIG/_pkcs7.i	(working copy)
@@ -75,7 +75,13 @@
         return NULL;
     }
     BIO_read(bio, outbuf, outlen);
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(outbuf, outlen);
+#else
     ret = PyString_FromStringAndSize(outbuf, outlen);
+#endif // PY_MAJOR_VERSION >= 3
+
     BIO_free(bio);
     PyMem_Free(outbuf);
     return ret;
@@ -111,7 +117,13 @@
         return NULL;
     }
     BIO_read(bio, outbuf, outlen);
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(outbuf, outlen);
+#else
     ret = PyString_FromStringAndSize(outbuf, outlen);
+#endif // PY_MAJOR_VERSION >= 3
+
     BIO_free(bio);
     PyMem_Free(outbuf);
     return ret;
Index: SWIG/_rand.i
===================================================================
--- SWIG/_rand.i	(revision 659)
+++ SWIG/_rand.i	(working copy)
@@ -56,7 +56,11 @@
         return NULL;
     }
     if (RAND_bytes(blob, n)) {
+#if PY_MAJOR_VERSION >= 3
+        obj = PyBytes_FromStringAndSize(blob, n);
+#else
         obj = PyString_FromStringAndSize(blob, n);
+#endif // PY_MAJOR_VERSION >= 3
         PyMem_Free(blob);
         return obj;
     } else {
@@ -87,7 +91,13 @@
         Py_INCREF(Py_None);
         return Py_None;
     } else {
+
+#if PY_MAJOR_VERSION >= 3
+        PyTuple_SET_ITEM(tuple, 0, PyBytes_FromStringAndSize(blob, n));
+#else
         PyTuple_SET_ITEM(tuple, 0, PyString_FromStringAndSize(blob, n));
+#endif // PY_MAJOR_VERSION >= 3
+
         PyMem_Free(blob);
         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((long)ret));
         return tuple;
Index: SWIG/_rc4.i
===================================================================
--- SWIG/_rc4.i	(revision 659)
+++ SWIG/_rc4.i	(working copy)
@@ -47,7 +47,13 @@
         return NULL;
     }
     RC4(key, len, buf, out);
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize(out, len);
+#else
     ret = PyString_FromStringAndSize(out, len);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(out);
     return ret;
 }
Index: SWIG/_rsa.i
===================================================================
--- SWIG/_rsa.i	(revision 659)
+++ SWIG/_rsa.i	(working copy)
@@ -196,7 +196,13 @@
         PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+#else
     ret = PyString_FromStringAndSize((const char *)tbuf, tlen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(tbuf);
     return ret;
 }
@@ -221,7 +227,13 @@
         PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+#else
     ret = PyString_FromStringAndSize((const char *)tbuf, tlen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(tbuf);
     return ret;
 }
@@ -246,7 +258,13 @@
         PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+#else
     ret = PyString_FromStringAndSize((const char *)tbuf, tlen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(tbuf);
     return ret;
 }
@@ -271,11 +289,77 @@
         PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+#else
     ret = PyString_FromStringAndSize((const char *)tbuf, tlen);
+#endif // PY_MAJOR_VERSION >= 3
+
     PyMem_Free(tbuf);
     return ret;
 }
 
+PyObject *rsa_padding_add_pkcs1_pss(RSA *rsa, PyObject *digest, EVP_MD *hash, int salt_lenth) {
+    const void *dbuf;
+    void *tbuf;
+
+    int dlen, result;
+    PyObject *ret;
+
+    int tlen = BN_num_bytes(rsa->n);
+
+    if (m2_PyObject_AsReadBufferInt(digest, &dbuf, &dlen) == -1)
+        return NULL;
+
+    if (!(tbuf = PyMem_Malloc(tlen))) {
+        PyErr_SetString(PyExc_MemoryError, "rsa_padding_add_pkcs1_pss");
+        return NULL;
+    }
+    result = RSA_padding_add_PKCS1_PSS(
+        rsa,
+        (unsigned char *)tbuf,
+        (unsigned char *)dbuf,
+        hash,
+        salt_lenth);
+
+    if (result == -1) {
+        PyMem_Free(tbuf);
+        PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error()));
+        return NULL;
+    }
+
+#if PY_MAJOR_VERSION >= 3
+    ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+#else
+    ret = PyString_FromStringAndSize((const char *)tbuf, tlen);
+#endif // PY_MAJOR_VERSION >= 3
+
+    PyMem_Free(tbuf);
+    return ret;
+}
+
+int rsa_verify_pkcs1_pss(RSA *rsa, PyObject *digest, PyObject *signature, EVP_MD *hash, int salt_lenth) {
+    const void *dbuf;
+    const void *sbuf;
+
+    int dlen, slen, ret;
+
+    if (m2_PyObject_AsReadBufferInt(digest, &dbuf, &dlen) == -1)
+        return 0;
+
+    if (m2_PyObject_AsReadBufferInt(signature, &sbuf, &slen) == -1)
+        return 0;
+
+    ret = RSA_verify_PKCS1_PSS(
+        rsa,
+        (unsigned char *)dbuf,
+        hash,
+        (unsigned char *)sbuf,
+        salt_lenth);
+
+    return ret;
+}
+
 PyObject *rsa_sign(RSA *rsa, PyObject *py_digest_string, int method_type) {
     int digest_len = 0;
     int buf_len = 0;
@@ -302,7 +386,13 @@
         PyErr_SetString(_rsa_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    signature =  PyBytes_FromStringAndSize((const char*) sign_buf, buf_len);
+#else
     signature =  PyString_FromStringAndSize((const char*) sign_buf, buf_len);
+#endif
+
     PyMem_Free(sign_buf);
     return signature;
 }     
Index: SWIG/_ssl.i
===================================================================
--- SWIG/_ssl.i	(revision 659)
+++ SWIG/_ssl.i	(working copy)
@@ -491,7 +491,13 @@
         case SSL_ERROR_NONE:
         case SSL_ERROR_ZERO_RETURN:
             buf = PyMem_Realloc(buf, r);
+
+#if PY_MAJOR_VERSION >= 3
+            obj = PyBytes_FromStringAndSize(buf, r);
+#else
             obj = PyString_FromStringAndSize(buf, r);
+#endif //PY_MAJOR_VERSION >= 3
+
             break;
         case SSL_ERROR_WANT_WRITE:
         case SSL_ERROR_WANT_READ:
@@ -541,7 +547,13 @@
         case SSL_ERROR_NONE:
         case SSL_ERROR_ZERO_RETURN:
             buf = PyMem_Realloc(buf, r);
+
+#if PY_MAJOR_VERSION >= 3
+            obj = PyBytes_FromStringAndSize(buf, r);
+#else
             obj = PyString_FromStringAndSize(buf, r);
+#endif // PY_MAJOR_VERSION >= 3
+
             break;
         case SSL_ERROR_WANT_WRITE:
         case SSL_ERROR_WANT_READ:
Index: SWIG/_util.i
===================================================================
--- SWIG/_util.i	(revision 659)
+++ SWIG/_util.i	(working copy)
@@ -27,7 +27,13 @@
         PyErr_SetString(_util_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    obj = PyBytes_FromString(ret);
+#else
     obj = PyString_FromString(ret);
+#endif // PY_MAJOR_VERSION >= 3
+
     OPENSSL_free(ret);
     return obj;
 }
@@ -48,7 +54,13 @@
         PyErr_SetString(_util_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3
+    obj = PyBytes_FromStringAndSize(ret, len);
+#else
     obj = PyString_FromStringAndSize(ret, len);
+#endif // PY_MAJOR_VERSION >= 3
+
     OPENSSL_free(ret);
     return obj;
 }
Index: SWIG/_x509.i
===================================================================
--- SWIG/_x509.i	(revision 659)
+++ SWIG/_x509.i	(working copy)
@@ -159,12 +159,21 @@
 %rename(x509_name_entry_get_data) X509_NAME_ENTRY_get_data;
 extern ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *);
 
-%typemap(in) (CONST unsigned char *, int) { 
+%typemap(in) (CONST unsigned char *, int) {
+#if PY_MAJOR_VERSION >= 3 
+    if (PyBytes_Check($input)) {
+        Py_ssize_t len;
+
+        $1 = PyBytes_AsString($input); 
+        len = PyBytes_Size($input);
+#else
     if (PyString_Check($input)) {
         Py_ssize_t len;
 
         $1 = PyString_AsString($input); 
         len = PyString_Size($input);
+#endif // PY_MAJOR_VERSION >= 3
+
         if (len > INT_MAX) {
             PyErr_SetString(PyExc_ValueError, "object too large");
             return NULL;
@@ -328,7 +337,13 @@
         PyErr_SetString(_x509_err, ERR_reason_error_string(ERR_get_error()));
     }
     else {     
+
+#if PY_MAJOR_VERSION >= 3 
+        ret = PyBytes_FromStringAndSize(buf, len);
+#else
         ret = PyString_FromStringAndSize(buf, len);
+#endif // PY_MAJOR_VERSION >= 3 
+
         OPENSSL_free(buf);
     }
     return ret;
@@ -400,13 +415,23 @@
         return NULL;
     }
     xlen = X509_NAME_get_text_by_NID(name, nid, buf, len);
+
+#if PY_MAJOR_VERSION >= 3 
+    ret = PyBytes_FromStringAndSize(buf, xlen);
+#else
     ret = PyString_FromStringAndSize(buf, xlen);
+#endif // PY_MAJOR_VERSION >= 3 
+
     PyMem_Free(buf);
     return ret;
 }
 
 int x509_name_set_by_nid(X509_NAME *name, int nid, PyObject *obj) {
+#if PY_MAJOR_VERSION >= 3 
+    return X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC, PyBytes_AsString(obj), -1, -1, 0);
+#else
     return X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC, PyString_AsString(obj), -1, -1, 0);
+#endif // PY_MAJOR_VERSION >= 3 
 }
 
 /* x509_name_add_entry_by_txt */
@@ -417,7 +442,11 @@
 PyObject *x509_name_get_der(X509_NAME *name)
 {
     i2d_X509_NAME(name, 0);
+#if PY_MAJOR_VERSION >= 3 
+    return PyBytes_FromStringAndSize(name->bytes->data, name->bytes->length);
+#else
     return PyString_FromStringAndSize(name->bytes->data, name->bytes->length);
+#endif // PY_MAJOR_VERSION >= 3 
 }
 
 /* sk_X509_new_null() is a macro returning "STACK_OF(X509) *". */
@@ -509,7 +538,11 @@
         PyErr_SetString(_x509_err, ERR_reason_error_string(ERR_get_error()));
         return NULL;
     }
+#if PY_MAJOR_VERSION >= 3 
+    ext_name = PyBytes_FromStringAndSize(ext_name_str, strlen(ext_name_str));
+#else
     ext_name = PyString_FromStringAndSize(ext_name_str, strlen(ext_name_str));
+#endif // PY_MAJOR_VERSION >= 3 
     return ext_name;
 }
 
@@ -567,12 +600,23 @@
     Py_ssize_t encoded_string_len;
     char *encoded_string;
 
+#if PY_MAJOR_VERSION >= 3 
+    encoded_string_len = PyBytes_Size(pyEncodedString);
+#else
     encoded_string_len = PyString_Size(pyEncodedString);
+#endif
+
     if (encoded_string_len > INT_MAX) {
         PyErr_SetString(PyExc_ValueError, "object too large");
         return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3 
+    encoded_string = PyBytes_AsString(pyEncodedString);
+#else
     encoded_string = PyString_AsString(pyEncodedString);
+#endif 
+
     if (!encoded_string) {
         return NULL;
     }
@@ -598,7 +642,13 @@
        PyErr_SetString(_x509_err, ERR_reason_error_string(ERR_get_error()));
        return NULL;
     }
+
+#if PY_MAJOR_VERSION >= 3 
+    encodedString = PyBytes_FromStringAndSize((const char *)encoding, len);
+#else
     encodedString = PyString_FromStringAndSize((const char *)encoding, len);
+#endif // PY_MAJOR_VERSION >= 3 
+
     OPENSSL_free(encoding);
     return encodedString; 
 }
Index: tests/test_evp.py
===================================================================
--- tests/test_evp.py	(revision 659)
+++ tests/test_evp.py	(working copy)
@@ -209,7 +209,7 @@
             self.try_algo(i)
 
         self.assertRaises(ValueError, self.try_algo, 'nosuchalgo4567')
-        
+       
     def test_AES(self):
         enc = 1
         dec = 0
@@ -239,7 +239,8 @@
             'CT':  'd0a02b3836451753d493665d33f0e8862dea54cdb293abc7506939276772f8d5021c19216bad525c8579695d83ba2684',
             },
         ]
-        
+       
+        # Test with padding
         for test in tests:
             # encrypt
             k=EVP.Cipher(alg='aes_128_cbc', key=unhexlify(test['KEY']), iv=unhexlify(test['IV']), op=enc)
@@ -261,7 +262,27 @@
             cbuf.close()
             self.assertEqual(plaintext, test['PT'])
 
+        # Test without padding
+        for test in tests:
+            # encrypt
+            k=EVP.Cipher(alg='aes_128_cbc', key=unhexlify(test['KEY']), iv=unhexlify(test['IV']), op=enc, padding=False)
+            pbuf=cStringIO.StringIO(test['PT'])
+            cbuf=cStringIO.StringIO()
+            ciphertext = hexlify(self.cipher_filter(k, pbuf, cbuf))
+            pbuf.close()
+            cbuf.close()
+            self.assertEqual(ciphertext, test['CT'])
 
+            # decrypt
+            j=EVP.Cipher(alg='aes_128_cbc', key=unhexlify(test['KEY']), iv=unhexlify(test['IV']), op=dec, padding=False)
+            pbuf=cStringIO.StringIO()
+            cbuf=cStringIO.StringIO(unhexlify(test['CT']))
+            plaintext=self.cipher_filter(j, cbuf, pbuf)
+            pbuf.close()
+            cbuf.close()
+            self.assertEqual(plaintext, test['PT'])
+
+
     def test_raises(self):
         def _cipherFilter(cipher, inf, outf):
             while 1:
Index: tests/test_rsa.py
===================================================================
--- tests/test_rsa.py	(revision 659)
+++ tests/test_rsa.py	(working copy)
@@ -166,6 +166,34 @@
             verify = rsa2.verify(digest, signature, algo) 
             assert verify == 1, 'verification failed with algorithm %s' % algo
     
+    def test_sign_and_verify_rsassa_pss(self):
+        """
+        Testing signing and verifying using rsassa_pss
+
+        The maximum size of the salt has to decrease as the
+        size of the digest increases because of the size of 
+        our test key limits it.
+        """
+        algos = {'sha1':43, 
+                 'ripemd160':43,
+                 'md5':47}
+
+        if m2.OPENSSL_VERSION_NUMBER >= 0x90800F:
+            algos['sha224'] = 35
+            algos['sha256'] = 31
+            algos['sha384'] = 15
+            algos['sha512'] = 0 
+    
+        message = "This is the message string"
+        digest = sha.sha(message).digest()
+        rsa = RSA.load_key(self.privkey)
+        rsa2 = RSA.load_pub_key(self.pubkey)
+        for algo, salt_max in algos.iteritems():
+            for salt_length in range(0, salt_max):
+                signature = rsa.sign_rsassa_pss(digest, algo, salt_length)
+                verify = rsa2.verify_rsassa_pss(digest, signature, algo, salt_length) 
+                assert verify == 1, 'verification failed with algorithm %s salt length %d' % (algo, salt_length)
+
     def test_sign_bad_method(self):
         """
         Testing calling sign with an unsupported message digest algorithm



--part-u-1AEx-jqkGmW1FXj8cD2qa16iAe-apXDSZnXkM-SvthA--