views:

249

answers:

3

I'm trying to translate the follow Java into its Python equivalent.

 // certificate is contents of https://fps.sandbox.amazonaws.com/certs/090909/PKICert.pem
 // signature is a string that I need to verify.
 CertificateFactory factory = CertificateFactory.getInstance("X.509");
 X509Certificate x509Certificate = 
            (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certificate.getBytes()));
 Signature signatureInstance = Signature.getInstance(signatureAlgorithm);
 signatureInstance.initVerify(x509Certificate.getPublicKey());
 signatureInstance.update(stringToSign.getBytes(UTF_8_Encoding));
 return signatureInstance.verify(Base64.decodeBase64(signature.getBytes()));

This is for the PKI signature verification used by AWS FPS. http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAccountManagementGuide/VerifyingSignature.html

Thanks for your help!

A: 

I've written lots of Python code dealing with X509 stuff. I've always fallen back to calling openssl via the subprocess module. Google's keyczar library is getting some buzz although I've never used it.

Ryan Nowakowski
+2  A: 

I looked into doing this with pyCrypto and keyczar but the problem is neither have the ability to parse X509 certificates (keyczar has keyczar.util.ParseX509() but it is limited and doesn't work for the AWS cert or I'm guessing any real world cert).

I believe M2Crypto works though. See the following code snippet, which needs a real signature and plaintext filled in to really test.

from M2Crypto import X509

cert = X509.load_cert("PKICert.pem")
pub_key = cert.get_pubkey()

plaintext = "YYY"  # Put plaintext message here
signature = "XXX"  # Put signature of plaintext here

pub_key.verify_init()
pub_key.verify_update(plaintext)
if not pub_key.verify_final(signature):
    print "Signature failed"
Von
One thought that occurred to me is that the RSA key in the AWS cert is unlikely to change often if ever, if you were willing to use, e.g., openssl to extract the RSA key and save to a file you could probably use pyCrypto or keyczar with the raw RSA key.
Von
A: 

After all was said and done, I decided not to use a native library to verify the signature (because M2Crypto doesn't port easily to 64-bit Windows). I found that later versions of the Amazon FPS API includes a REST/SOAP call to verify the signature, so if a round trip to their server isn't too expensive, you can just call VerifySignature. I've added support for this in the next version of boto as boto.fps.connection.verify_signature.

Jason R. Coombs