3

I have a .cer file containing public key. I need to use this file to verify signature signed by corresponding private key. I have the signature and public key. I need to verify the signature. I'm getting result as false. Below is the code:

def verify_sign(public_key_loc, signature, data):
    '''
    Verifies with a public key from whom the data came that it was indeed
    signed by their private key
    param: public_key_loc Path to public key
    param: signature String signature to be verified
    return: Boolean. True if the signature is valid; False otherwise.
    '''
    #pdb.set_trace()
    from Crypto.PublicKey import RSA
    from Crypto.Signature import PKCS1_v1_5
    from Crypto.Hash import SHA256
    from base64 import b64decode
    try:
        pub_key = open(public_key_loc, "r").read()
        rsakey = RSA.importKey(pub_key)
        signer = PKCS1_v1_5.new(rsakey)
        digest = SHA256.new()
        # Assumes the data is base64 encoded to begin with
        digest.update(b64decode(data))
        if signer.verify(digest, b64decode(signature)):
            return True
        return False 
    except Exception as e:
        print e

I tried to use method here to convert .cer file to .pem. How do I use a X509 certificate with PyCrypto?

Is the method used here is correct? or does python has better libraries. Because as far as i know, python does not support X.509Certificate. Bear my english. Appreciate any help.

Thanks.

Edit:

As of now, i'm trying to use Pycrypto. Do i need to use any other libraries or method in the same pycrypto?

Community
  • 1
  • 1
Uday
  • 151
  • 1
  • 3
  • 15
  • Do you maybe have test data, signature and public key? With the current information it's hard to debug. I don't see anything particularly wrong in the code you've posted (except possibly the name of your method :P) – Maarten Bodewes Dec 01 '14 at 18:00
  • @owlstead I can't disclose the test data, signature and public key. I think the main problem is conversion of .cer to .pem file as specified in the link. Is the method used in http://stackoverflow.com/questions/12911373/how-do-i-use-a-x509-certificate-with-pycrypto correct one? The verify_sign method is working because thats from https://launchkey.com/docs/api/encryption/python/pycrypto. I tried with set of generated public-private key. – Uday Dec 02 '14 at 03:56
  • 1
    If you cannot share your data you need new test data. Or are you going to store your code without any tests? – Maarten Bodewes Dec 02 '14 at 08:07
  • Hey @owlstead , I have test data correctly verified in C# code. I want to replicate the same method that in python. Basically in C#, from .cer file. its been converted from base64 to byte and then extracting the X509Certificate. Using this extracted X509cert, the verification is going to be done. But Python does not support the X509Certificate. So I tried converting the .cer file to asn1 format and then getting public key(I have placed a ref link in question). Its not giving any error but i'm not getting the answer as present in C# code. did you get my point? – Uday Dec 02 '14 at 08:35
  • @Uday were you able to solve it? – Akhil Dad Apr 23 '20 at 04:22

1 Answers1

5

You should be able to extract the public key component from the X509 certificate using the openssl x509 command. You say that your certificate file has a .cer extension which often means a binary DER format, so this command should extract the public key in a form that can be used by pycrypto:

openssl x509 -inform der -pubkey -noout -in certificate.cer >public_key.pem

Although, it's possible that your .cer file is already in PEM format (I suspect that it is because in C# you needed to base64 decode this certificate), in which case this command should get the public key:

openssl x509 -pubkey -noout -in certificate.cer >public_key.pem

Either way you should end up with a file public_key.pem that resembles this PEM format key:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq8ZtNvMVc3iDc850hdWu
7LLw4CQfE4O4IKy7mv6Iu6uhHQsfRQCqSbc1Nwxq70dMudG+41cSBI2Sx7bsAby2
2seBOCCtcoXmDvyBbAetaHY4xUTXzMZKxZc+ZPRR5vB+suxW9yWCTUmYyxaY3SPx
iZHRF5dAmSbW4qIrXt+9ifIbGlMtzFBBetA9KgxVcBQB6VhJEHoLk4KL4R7tOoAQ
gs6WijTwzNfTubRQh1VUCbidQihVAOWMNVS/3SWRRrcN5V2DqOWL+4TkPK522sRD
K1t0C/i+XWjxeFu1zn3xXZlA2sruOIFQvpihbLgkrfOvjA/XESgshBhMfbXZjzC1
GwIDAQAB
-----END PUBLIC KEY-----

Now you can load this using Crypto.PublicKey.RSA.importKey().

You also should double check the encoding of data and signature; make sure that these are base64 encoded as you assume, although this is probably correct since you have it working in C#.

Other options exist:

  1. Use good old pyOpenSSL - see module OpenSSL.crypto:

    import OpenSSL
    
    cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1,
                                           open('certificate.cer').read())
    try:
        OpenSSL.crypto.verify(cert, signature, data, 'sha256')
        print "Signature verified OK"
    except Exception as e:
        print "Signature verification failed: {}".format(e)
    
  2. Use M2Crypto (Python 3 not supported):

    import M2Crypto
    
    cert = M2Crypto.X509.load_cert('certificate.cer', M2Crypto.X509.FORMAT_DER)
    pubkey = cert.get_pubkey()
    pubkey.reset_context('sha256')
    pubkey.verify_init()
    pubkey.verify_update(content)
    verified = pubkey.verify_final(signature)
    
mhawke
  • 84,695
  • 9
  • 117
  • 138
  • This detailed answer filled me with energy and hope that i can solve this issue. So, let me try again and again. thanks @mhawke – Uday Dec 03 '14 at 09:49
  • I used openssl to convert the .cer file to .pem. incidentally, its giving me the same .pem file as i got from method giving in the http://stackoverflow.com/questions/12911373/how-do-i-use-a-x509-certificate-with-pycrypto. but the result is still the same. False :(. One small question. how verifier method of prcrypto will know the hashing is in SHA-256 or other?. Since we are not explicitly specifying the hashing type as SHA-256. – Uday Dec 03 '14 at 13:21
  • AFAIK it doesn't know. You must select the matching hash algorithm as used by the sender. How you communicate that between peers is another matter. So that's one thing for you to double check: make sure that both sender and receiver are using the same hash algorithm. – mhawke Dec 03 '14 at 13:32