~mcepl/m2crypto#204: 
RSA signature verification is failing in cryptography module signed by M2Crypto module

Migrated from: https://gitlab.com/m2crypto/m2crypto/-/issues/204
Created by: Sonu Kumar (@sonus21)
Created at: 2018-03-01T18:28:20.601Z

#Signing a Message

import M2Crypto
import hashlib
rsa = M2Crypto.RSA.load_key("privkey.pem")
msg = "This is a secret"
digest = hashlib.new('sha1', msg).digest()
signature = rsa.sign(digest, "sha1")

#Verification using M2Crypto

rsa = M2Crypto.RSA.load_pub_key( "pubkey.pem" )
rsa.verify(signature, digest)

#Verification using cryptography module

from cryptography.hazmat.backends import default_backend 
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.exceptions import InvalidSignature
with open( "pubkey.pem", "rb" ) as key_file:
     pub = serialization.load_pem_public_key(                
          key_file.read(), backend=default_backend() )                    
     pub.verify(signature, digest,padding.PKCS1v15(),hashes.SHA1() )

Unfortunately, verification always fails when called in crytography module, with following error _OpenSSLError(code=67702888L, lib=4, func=145, reason=104)

After digging further down the line, it looks different module make different API calls, for example, M2Crypto calls RSA_verify whereas cryptograph module calls EVP_PKEY_verify function.

Cryptography Version: 1.5.3
M2Crypto Version: 0.21.1

NOTE: I've raised a similar issue to cryptography at https://github.com/pyca/cryptography/issues/4125

Status
REPORTED
Submitter
~mcepl
Assigned to
No-one
Submitted
7 months ago
Updated
7 months ago
Labels
No labels applied.

~mcepl 7 months ago

Changed on 2018-04-17T20:27:04.993Z by Matěj Cepl:

changed milestone to 0.30

~mcepl 7 months ago

On 2018-04-17T20:28:33.946Z, Matěj Cepl wrote:

From other bug:

I suspect the m2crypto code in this example does raw (aka textbook) RSA. We don’t support that at this time as it is extremely insecure.

~mcepl 7 months ago

Changed on 2018-04-24T08:43:34.624Z by Matěj Cepl:

changed milestone to 0.31

~mcepl 7 months ago

On 2018-04-24T08:44:38.157Z, Matěj Cepl wrote:

@t8m Do we do something wrong here? Should we change? Would we break API? Should we?

~mcepl 7 months ago

On 2018-04-24T09:52:07.482Z, Tomáš Mráz wrote:

I think the best way would be to deprecate rsa.sign/rsa.verify completely. We cannot change the signature format as that would break the existing callers anyway.

If you would like to support proper RSA sign/verify there would have to be a way to specify the padding used - i.e. PKCS1v1.5 or PSS.

~mcepl 7 months ago

On 2018-04-25T08:33:09.842Z, Matěj Cepl wrote:

Well, but not-breaking-API and supporting ancient programs is raison d'être of M2Crypto.

~mcepl 7 months ago

On 2018-04-25T10:48:21.571Z, Hubert Kario (@mention me if you need reply) wrote:

raw RSA signing is how you can get RSA-PSS out of even OpenSSL 0.9.8, so yes, it should stay, but likely be documented that it is not something you should be doing

~mcepl 7 months ago

On 2018-05-02T15:28:50.771Z, Matěj Cepl wrote:

See https://stackoverflow.com/questions/2536307/how-do-i-deprecate-python-functions and https://github.com/vrcmarcos/python-deprecated/blob/master/deprecated/__init__.py for illustration, how to do it.

def deprecated(reason):
    # type: (Optional[str, Callable, Type]) -> Callable
    """
    :param reason: Reason message (or function/class/method to decorate).
    """

    if isinstance(reason, six.string_types):
        # The @deprecated is used with a 'reason'.
        #
        # .. code-block:: python
        #
        #    @deprecated("please, use another function")
        #    def old_function(x, y):
        #      pass

        def decorator(func1):

            if inspect.isclass(func1):
                fmt1 = "Call to deprecated class {name} ({reason})."
            else:
                fmt1 = "Call to deprecated function {name} ({reason})."

            @functools.wraps(func1)
            def new_func1(*args, **kwargs):
                warnings.simplefilter('always', DeprecationWarning)
                warnings.warn(
                    fmt1.format(name=func1.__name__, reason=reason),
                    category=DeprecationWarning,
                    stacklevel=2
                )
                warnings.simplefilter('default', DeprecationWarning)
                return func1(*args, **kwargs)

            return new_func1

        return decorator

    elif inspect.isclass(reason) or inspect.isfunction(reason):

        # The @deprecated is used without any 'reason'.
        #
        # .. code-block:: python
        #
        #    @deprecated
        #    def old_function(x, y):
        #      pass

        func2 = reason

        if inspect.isclass(func2):
            fmt2 = "Call to deprecated class {name}."
        else:
            fmt2 = "Call to deprecated function {name}."

        @functools.wraps(func2)
        def new_func2(*args, **kwargs):
            warnings.simplefilter('always', DeprecationWarning)
            warnings.warn(
                fmt2.format(name=func2.__name__),
                category=DeprecationWarning,
                stacklevel=2
            )
            warnings.simplefilter('default', DeprecationWarning)
            return func2(*args, **kwargs)

        return new_func2

    else:
        raise TypeError(repr(type(reason)))

(Last edited at 2018-05-02T15:29:10.510Z.)

~mcepl 7 months ago

On 2018-05-03T15:53:32.353Z, Matěj Cepl wrote:

raw RSA signing is how you can get RSA-PSS out of even OpenSSL 0.9.8, so yes, it should stay, but likely be documented that it is not something you should be doing

@tomato42 except we have OpenSSL 1.0.1e as the minimal supported version.

I guess we have to create RSA2 module (or something in that style), which would do the things properly and deprecate M2Crypto.RSA?

Which all methods of M2Crypto.RSA should be rewritten in your opinion?

~mcepl 7 months ago

Changed on 2018-05-28T05:13:42.846Z by Matěj Cepl:

mentioned in issue #217

~mcepl 7 months ago

On 2018-06-29T16:52:19.708Z, Hubert Kario (@mention me if you need reply) wrote:

OpenSSL 1.0.1e as the minimal supported version.

and rsa-pss was introduced in 1.0.2...

I guess we have to create RSA2 module (or something in that style), which would do the things properly and deprecate M2Crypto.RSA?

I'm not sure if it is worth the effort

~mcepl 7 months ago

On 2018-06-30T09:44:30.879Z, Matěj Cepl wrote:

raw RSA signing is how you can get RSA-PSS out of even OpenSSL 0.9.8, so yes, it should stay, but likely be documented that it is not something you should be doing

OK, I will plead stupidity here. Could somebody point me to some documentation what's RSA-PSS is, or (even better) provide pull request how would you like to see old ways deprecated and news introduced (at least some kind of draft, where I could fill in the gaps)?

(Last edited at 2018-06-30T09:44:56.882Z.)

~mcepl 7 months ago

On 2018-06-30T10:06:05.689Z, Matěj Cepl wrote:

Some more resources for me to study:

~mcepl 7 months ago

On 2018-07-09T11:58:49.066Z, Matěj Cepl wrote:

I'm not sure if it is worth the effort

Could you elaborate on this one, please?

~mcepl 7 months ago

Changed on 2018-10-02T11:53:27.513Z by Matěj Cepl:

changed milestone to 0.32

~mcepl 7 months ago

Changed on 2019-03-05T07:59:23.641Z by Matěj Cepl:

changed milestone to 0.33

~mcepl 7 months ago

Changed on 2019-04-26T14:30:13.984Z by Matěj Cepl:

changed milestone to 0.34

~mcepl 7 months ago

Changed on 2019-05-30T19:58:18.167Z by Matěj Cepl:

changed milestone to 0.35

(Last edited at 2019-05-30T19:58:18.171Z.)

~mcepl 7 months ago

Changed on 2019-06-08T06:32:44.520Z by Matěj Cepl:

changed milestone to 0.36

(Last edited at 2019-06-08T06:32:44.523Z.)

~mcepl referenced this from #217 7 months ago

Register here or Log in to comment, or comment via email.