I'm trying to port an M2Crypto function to pyCrypto or any other solution, 'cause the last version of M2Crypto doesn't work with pypy.
So, i'm trying to port an existing code from pysimplesoap:
https://github.com/pysimplesoap/pysimplesoap/blob/master/pysimplesoap/xmlsec.py
This is the only function that i don't know how to port:
def x509_extract_rsa_public_key(cert, binary=False):
"Return the public key (PEM format) from a X509 certificate"
x509 = x509_parse_cert(cert, binary)
return x509.get_pubkey().get_rsa().as_pem()
The original public certificate is:
-----BEGIN CERTIFICATE-----
MIIFhTCCA20CBFOF3SIwDQYJKoZIhvcNAQEFBQAwgYYxIDAeBgkqhkiG9w0BCQEW
EWpjZXJkYUBleHBlcnRpLmNsMQswCQYDVQQGEwJDTDERMA8GA1UECAwIU2FudGlh
Z28xETAPBgNVBAcMCFNhbnRpYWdvMRAwDgYDVQQKDAdFeHBlclRJMRAwDgYDVQQL
DAdFeHBlclRJMQswCQYDVQQDDAIxMDAeFw0xNDA1MjgxMjU3MDZaFw0xNjA1Mjcx
MjU3MDZaMIGGMSAwHgYJKoZIhvcNAQkBFhFqY2VyZGFAZXhwZXJ0aS5jbDELMAkG
A1UEBhMCQ0wxETAPBgNVBAgMCFNhbnRpYWdvMREwDwYDVQQHDAhTYW50aWFnbzEQ
MA4GA1UECgwHRXhwZXJUSTEQMA4GA1UECwwHRXhwZXJUSTELMAkGA1UEAwwCMTAw
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCX1t11QZSgfodg+NPwKdof
lakbpxsFmCvjbY3Vpp6/bTv56XIZe/Z3gBlU4zeGslEaqzs1k4cGAcdZPHxSMydC
oLxmyXpdS2hVFUZTYAeanXHhQzUKmNlgYj3uObprPEEQzD/vEuqpwz2/ZGyaHsWs
exu9aeuLAUUSNne0yqobrzRfEp2FqCp4sJB80cXgGfPA4Cr5jROHqUi8sVWpWRy5
ai5ZaiXRPo3YKF1336twuw9lRS3cRtJh9/AoJElGT7G7BMDpxyTTa08y1iRliDGu
mwWivQMHoKqEs0lCtF9Uz8cFdmiIoRPTt6McpmLoapL9v19xjNnim4lke6DPvtcg
uato7T+frDqA5Cj5GRP/8jbe90Y+YjHuJTkw+fkV6gDTRmJ3wCWDIw/07aY6nZ+H
24Imu6N2YBsMEsa8j9OW04mNgtppRC4dFBh0FIKXC35kJgN38y+6T7MsQThX1XZS
SlK0FygJJADVGelmxtsrRRfnp4yLYRjwdkRGExRjVs/+fkOyKI+fX0o68z6MEDyA
5epVHpgwJ/Yz3Lo7cgXy0hO5a/MfZc0Y0ofb29g8sJMJ8j/SSR85i4pFxudn+HH0
SmkkzE/P10adF/X+pqjscOE+aXwnX09lUUQ9TIlpYaR3hUhONsuefYJ2sHz2z+vt
K5btQwN7u9+QeXLgb20PMwIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQAqCepOSFi7
8d6lKTfWpMuj5ygpplBa3Bj81AKkNfSGDN7zkNX2sCbqn9aEjniIPtldG6I2fgCs
FYTZE9oEPNiuEuH7PNtAjTExIUi9Jzm7bqjCdSs7Ioek1cPePgst017zJ6NSTkaM
r7pUDaS3855xO92uaJskppAeegwz9Dv3d5wY+wVViqUki4pZyxa95IvBJz4NR1Xr
cO6XtUUT9M0wbd0jAkRp7DPQfkihZj8vLSvlUYTRdlF2swIBE/ME2T3NCa0/kt1c
IA1Aq/zn7t0yKvyaJ/O//LrHA1Lfa/uC61O/9P3t+eXDsYl73CeGQdSYZp2DAZmA
Ek3tzwhFa6HR+POIo8MptWMT3DQ0ISHH+EW1Xp8GHIGsk2ELsXuA6XTNwpfz9yvl
9d7IGsq4cdX88cNUCbXm4tj7F3s6i8pNWeCImaYcXKGCBdsLM+lbmqbuV7o3d1Ei
efbR1TQkCxRBNCMUI0pF7NW8PvY3QER9/jEnN52SX+tuQRVdpgl+PyTdSASr4FhV
+HHmgeOgeOewXDnZ7aA1F6f8+CY8Niv4FGZIAptdxTqdynY4nUy/wFowBouO3LEF
6nIcQ3Jx1pDXoEmcLa03JaL7qQNSHyqSe/YEl8E5fdDr7vApzw9pvpAjj1aslidL
bNd4l1YGlL2vbGsIXZlbdBLiblXRi78AyQ==
And when i execute that function, the result is:
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAl9bddUGUoH6HYPjT8Cna
H5WpG6cbBZgr422N1aaev207+elyGXv2d4AZVOM3hrJRGqs7NZOHBgHHWTx8UjMn
QqC8Zsl6XUtoVRVGU2AHmp1x4UM1CpjZYGI97jm6azxBEMw/7xLqqcM9v2Rsmh7F
rHsbvWnriwFFEjZ3tMqqG680XxKdhagqeLCQfNHF4BnzwOAq+Y0Th6lIvLFVqVkc
uWouWWol0T6N2Chdd9+rcLsPZUUt3EbSYffwKCRJRk+xuwTA6cck02tPMtYkZYgx
rpsFor0DB6CqhLNJQrRfVM/HBXZoiKET07ejHKZi6GqS/b9fcYzZ4puJZHugz77X
ILmraO0/n6w6gOQo+RkT//I23vdGPmIx7iU5MPn5FeoA00Zid8AlgyMP9O2mOp2f
h9uCJrujdmAbDBLGvI/TltOJjYLaaUQuHRQYdBSClwt+ZCYDd/Mvuk+zLEE4V9V2
UkpStBcoCSQA1RnpZsbbK0UX56eMi2EY8HZERhMUY1bP/n5DsiiPn19KOvM+jBA8
gOXqVR6YMCf2M9y6O3IF8tITuWvzH2XNGNKH29vYPLCTCfI/0kkfOYuKRcbnZ/hx
9EppJMxPz9dGnRf1/qao7HDhPml8J19PZVFEPUyJaWGkd4VITjbLnn2CdrB89s/r
7SuW7UMDe7vfkHly4G9tDzMCAwEAAQ==
-----END PUBLIC KEY-----
I was trying to do something like this, but it doesn't work:
pub = open("certificate_server.crt", "r").read()
a2 = crypto.load_certificate(FILETYPE_PEM, pub)
b2 = a2.get_pubkey()
But then i don't know how to proceed, can someone help me?
Using pyOpenSSL, after you call get_pubkey() you can call OpenSSL.crypto.dump_publickey(OpenSSL.crypto.FILETYPE_PEM, b2) to get the PEM output.
Related
How do I read BouncingCastle PGP key and decrypt message using Python.?
This private key is generated using GoAnywhere OpenPGP Studio, password is Test#123
Below is the key blob and the error I'm getting. I'm getting same error when I read from file(.asc) as well
test_key_pvt = """-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: BCPG v1.48
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
/+ldLYPLUjczvK+qk1dbU89Grv7h/w==
=Uo6i
-----END PGP PRIVATE KEY BLOCK-----
"""
pvt_key, _ = pgpy.PGPKey.from_blob(test_key_pvt)
Error: pgpy.errors.PGPError: 6 is not a valid SymmetricKeyAlgorithm
Another error for different key: pgpy.errors.PGPError: 112 is not a valid CompressionAlgorithm
Not able to arrive at any solution, I'm trying to automate a very small transfer and its really annoying that I'm not able to find anything for this in python. PGPY library doesn't have a lot of documentation.
TIA
I want to generate a private , public key pair and put them into private.key and public.key files respectively.
I have the following code.
from OpenSSL import crypto, SSL
def gen_rsa_key_pair():
k = crypto.PKey()
k.generate_key(crypto.TYPE_RSA, 1024)
open("Priv.key", "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k))
crypto.dump_publickey() is not available.
How do I dump public key to a file?
The OpenSSL functions to print the public RSA key do not seem to be exported by the Python OpenSSL wrapper. By accessing the internals of the crypto module, you could still do it yourself (assuming that you have this package installed locally), as this code snippet shows:
>>> bio = crypto._new_mem_buf()
>>> rsa = crypto._lib.EVP_PKEY_get1_RSA(k._pkey)
>>> crypto._lib.PEM_write_bio_RSAPublicKey(bio, rsa)
1
>>> s = crypto._bio_to_string(bio)
>>> print(s)
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBANF1gYh10F8HTQdM6+bkwAwJ0Md6bMciKbP3qS6KTki3v3m+cM17Szqq
Mp4xxWbvnS2oeotYfn8eaZg0QUTOVDd1F7tuOxVEdvQ9ZEp1aeOCRU3b9QZSmVfg
wJrqDG3f149mNdexI12plwaxyt6odonv6+fEQJrbhrV/nIA8N/EFAgMBAAE=
-----END RSA PUBLIC KEY-----
This is just for illustration purposes. A proper solution should be added to the crypto module itself, via a new method dump_publickey() or the like.
Supposing that I have an X509 Certificate as follows:
-----BEGIN CERTIFICATE-----
MIIE5zCCA8+gAwIBAgIEAOJk2zANBgkqhkiG9w0BAQUFADCByjELMAkGA1UEBhMC
VVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNV
BAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlmaWNh
dGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5IFNl
Y3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5NjkyODcw
HhcNMDkwMTE4MjEyMjMxWhcNMTEwMTE4MjEyMjMxWjBbMRowGAYDVQQKExFtYWls
Lm5peGNyYWZ0Lm5ldDEaMBgGA1UEAxMRbWFpbC5uaXhjcmFmdC5uZXQxITAfBgNV
BAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDCBnzANBgkqhkiG9w0BAQEFAAOB
jQAwgYkCgYEA0LhCDXvNXhTHov9Szh474Cv3Nz7QspVOI4p5M+zZt18VTVCHJz0Z
TleJum8RblpU4NPHJgOauIb1CAE3vLSKySV2DjHMt2L2/NUatJiKjDQKAEloKwQK
t75BP0mAGFPZmHlMNUQ32Sr/0byxxM4ElL2SSBasJE3PPVkSBOtLfssCAwEAAaOC
AcUwggHBMA8GA1UdEwEB/wQFMAMBAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
AQUFBwMCMA4GA1UdDwEB/wQEAwIFoDAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8v
Y3JsLmdvZGFkZHkuY29tL2dkczEtMS5jcmwwUwYDVR0gBEwwSjBIBgtghkgBhv1t
AQcXATA5MDcGCCsGAQUFBwIBFitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHku
Y29tL3JlcG9zaXRvcnkvMIGABggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGGGGh0
dHA6Ly9vY3NwLmdvZGFkZHkuY29tLzBKBggrBgEFBQcwAoY+aHR0cDovL2NlcnRp
ZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5L2dkX2ludGVybWVkaWF0ZS5j
cnQwHwYDVR0jBBgwFoAU/axhMpNsRdbi7oVfmrrndplozOcwMwYDVR0RBCwwKoIR
bWFpbC5uaXhjcmFmdC5uZXSCFXd3dy5tYWlsLm5peGNyYWZ0Lm5ldDAdBgNVHQ4E
FgQUAYML0uoVH8Sn8JZ3xbR9NLzE0tYwDQYJKoZIhvcNAQEFBQADggEBAJ/1/mGM
tF/UPwOvmiNE0i46qXCJDs6Ui7kCxWWQzC+CbT6x3fe8VwZ2/9OVeScw5aGkG7sU
kfid0XmfXxYrqkVsubrhQt/1MKKowB35M5a/wRd7E0h2ucYhBF3dnTQ29yJ9ppHC
HOvsUDGOan+e7japMyTYn9PU9Y8QtnzovRXk55iYfL4p57YvPwk4yMnBtc/krQcd
m6ZdvmY+zbbjWaDyarfIp3fQCL2HD/lC5rJaGUn633GIT0OrrQ4Gfy6hQ98UC+Pt
I8LFuzs02dJlCpDhGquvQ0W6o4uuvjSP28HfGBcmKholG0GT9wyZZCBvUlFyV6kq
/KNTisOW4so6I+Q=
-----END CERTIFICATE-----
Is there a way to check which algorithm was used in order to generate the key starting from the value (string) above in Python?
You can use the pyOpenSSL library (https://github.com/pyca/pyopenssl).
from OpenSSL import crypto
cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert_string)
cert.get_signature_algorithm()
For more documentation on X509 objects see https://pyopenssl.readthedocs.org/en/latest/api/crypto.html#OpenSSL.crypto.X509
I'm trying to validate Windows 8 receipt XML signature using pyxmlsec.
My receipt (receipt.xml) looks like this:
<?xml version="1.0"?><Receipt Version="1.0" ReceiptDate="2012-08-30T23:10:05Z" CertificateId="b809e47cd0110a4db043b3f73e83acd917fe1336" ReceiptDeviceId="4e362949-acc3-fe3a-e71b-89893eb4f528"><AppReceipt Id="8ffa256d-eca8-712a-7cf8-cbf5522df24b" AppId="55428GreenlakeApps.CurrentAppSimulatorEventTest_z7q3q7z11crfr" PurchaseDate="2012-06-04T23:07:24Z" LicenseType="Full" /><ProductReceipt Id="6bbf4366-6fb2-8be8-7947-92fd5f683530" ProductId="Product1" PurchaseDate="2012-08-30T23:08:52Z" ExpirationDate="2012-09-02T23:08:49Z" ProductType="Durable" AppId="55428GreenlakeApps.CurrentAppSimulatorEventTest_z7q3q7z11crfr" /><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>cdiU06eD8X/w1aGCHeaGCG9w/kWZ8I099rw4mmPpvdU=</DigestValue></Reference></SignedInfo><SignatureValue>SjRIxS/2r2P6ZdgaR9bwUSa6ZItYYFpKLJZrnAa3zkMylbiWjh9oZGGng2p6/gtBHC2dSTZlLbqnysJjl7mQp/A3wKaIkzjyRXv3kxoVaSV0pkqiPt04cIfFTP0JZkE5QD/vYxiWjeyGp1dThEM2RV811sRWvmEs/hHhVxb32e8xCLtpALYx3a9lW51zRJJN0eNdPAvNoiCJlnogAoTToUQLHs72I1dECnSbeNPXiG7klpy5boKKMCZfnVXXkneWvVFtAA1h2sB7ll40LEHO4oYN6VzD+uKd76QOgGmsu9iGVyRvvmMtahvtL1/pxoxsTRedhKq6zrzCfT8qfh3C1w==</SignatureValue></Signature></Receipt>
And here's my certificate (cert):
-----BEGIN CERTIFICATE-----
MIIDyTCCArGgAwIBAgIQNP+YKvSo8IVArhlhpgc/xjANBgkqhkiG9w0BAQsFADCB
jjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1Jl
ZG1vbmQxHjAcBgNVBAoMFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEWMBQGA1UECwwN
V2luZG93cyBTdG9yZTEgMB4GA1UEAwwXV2luZG93cyBTdG9yZSBMaWNlbnNpbmcw
HhcNMTExMTE3MjMwNTAyWhcNMzYxMTEwMjMxMzQ0WjCBjjELMAkGA1UEBhMCVVMx
EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1JlZG1vbmQxHjAcBgNVBAoM
FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEWMBQGA1UECwwNV2luZG93cyBTdG9yZTEg
MB4GA1UEAwwXV2luZG93cyBTdG9yZSBMaWNlbnNpbmcwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQCcr4/vgqZFtzMqy3jO0XHjBUNx6j7ZTXEnNpLl2VSe
zVQA9KK2RlvroXKhYMUUdJpw+txm1mqi/W7D9QOYTq1e83GLhWC9IRh/OSmSYt0e
kgVLB+icyRH3dtpYcJ5sspU2huPf4I/Nc06OuXlMsD9MU4Ug9IBD2HSDBEquhGRo
xV64YuEH4645oB14LlEay0+JZlkKZ/mVhx/sdzSBfrda1X/Ckc7SOgnTSM3d/DnO
5DKwV2WYn+7i/rBqe4/op6IqQMrPpHyem9Sny+i0xiUMA+1IwkX0hs0gvHM6zDww
TMDiTapbCy9LnmMx65oMq56hhsQydLEmquq8lVYUDEzLAgMBAAGjITAfMB0GA1Ud
DgQWBBREzrOBz7zw+HWskxonOXAPMa6+NzANBgkqhkiG9w0BAQsFAAOCAQEAeVtN
4c6muxO6yfht9SaxEfleUBIjGfe0ewLBp00Ix7b7ldJ/lUQcA6y+Drrl7vjmkHQK
OU3uZiFbCxTvgTcoz9o+1rzR/WPXmqH5bqu6ua/UrobGKavAScqqI/G6o56Xmx/y
oErWN0VapN370crKJvNWxh3yw8DCl+W0EcVRiWX5lFsMBNBbVpK4Whp+VhkSJilu
iRpe1B35Q8EqOz/4RQkOpVI0dREnuSYkBy/h2ggCtiQ5yfvH5zCdcfhFednYDevS
axmt3W5WuHz8zglkg+OQ3qpXaXySRlrmLdxEmWu2MOiZbQkU2ZjBSQmvFAOy0dd6
P1YLS4+Eyh5drQJc0Q==
-----END CERTIFICATE-----
And it does validates when I'm using xmlsec1 console program (thanks to my previous question):
$ xmlsec1 --verify --pubkey-cert-pem cert receipt.xml
OK
SignedInfo References (ok/all): 1/1
Manifests References (ok/all): 0/0
Now I'm trying to do the same using pyxmlsec package (and its docs):
In [1]: import xmlsec; xmlsec.init(); xmlsec.cryptoInit(); xmlsec.cryptoAppInit(None)
Out[1]: 0
In [2]: mngr = xmlsec.KeysMngr(); xmlsec.cryptoAppDefaultKeysMngrInit(mngr)
Out[2]: 0
In [3]: mngr.certLoad('cert', xmlsec.KeyDataFormatCertPem , xmlsec.KeyDataTypePublic)
Out[3]: 0
In [4]: dsig_ctx = xmlsec.DSigCtx(mngr)
In [5]: import libxml2; f = libxml2.parseFile('receipt.xml'); node = xmlsec.findNode(f.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs)
In [6]: dsig_ctx.verify(node)
func=xmlSecKeysMngrGetKey:file=keys.c:line=1370:obj=unknown:subj=xmlSecKeysMngrFindKey:error=1:xmlsec library function failed:
func=xmlSecDSigCtxProcessKeyInfoNode:file=xmldsig.c:line=871:obj=unknown:subj=unknown:error=45:key is not found:
func=xmlSecDSigCtxProcessSignatureNode:file=xmldsig.c:line=565:obj=unknown:subj=xmlSecDSigCtxProcessKeyInfoNode:error=1:xmlsec library function failed:
func=xmlSecDSigCtxVerify:file=xmldsig.c:line=366:obj=unknown:subj=xmlSecDSigCtxSigantureProcessNode:error=1:xmlsec library function failed:
Out[6]: -1
What am I doing wrong here? How can it be fixed? Or is there any better python package for this task?
This is how the receipt can be validated without external files:
import xmlsec
from lxml import etree
from M2Crypto import X509
import StringIO
def validate_win_signature(receipt, cert):
xml = etree.fromstring(receipt)
xmlsec.tree.add_ids(xml, ["ID"])
signature_node = xmlsec.tree.find_node(xml, xmlsec.Node.SIGNATURE)
assert signature_node is not None
assert signature_node.tag.endswith(xmlsec.Node.SIGNATURE)
ctx = xmlsec.SignatureContext()
certx509 = X509.load_cert_string(cert)
pubkey = certx509.get_pubkey().get_rsa().as_pem(cipher=None)
keystream = StringIO.StringIO(pubkey)
key = xmlsec.Key.from_memory(keystream, xmlsec.KeyFormat.PEM)
ctx.key = key
ctx.verify(signature_node)
The problem seems to be that using mngr.certLoad on a certificate file returns 0, ie. success, when in fact the key manager does not hold any valid keys (bug?). I got the idea from these two lines, which imply that there is no key:
func=xmlSecKeysMngrGetKey:file=keys.c:line=1370:obj=unknown:subj=xmlSecKeysMngrFindKey:error=1:xmlsec library function failed:
func=xmlSecDSigCtxProcessKeyInfoNode:file=xmldsig.c:line=871:obj=unknown:subj=unknown:error=45:key is not found:
The solution is to convert the certificate file into a public key file using openssl:
openssl x509 -inform pem -in cert -pubkey -noout > pubkey
Then, you can use this key to verify the signature with the python library:
>>> key = xmlsec.cryptoAppKeyLoad('pubkey', xmlsec.KeyDataFormatPem, None, None, None)
>>> dsig_ctx = xmlsec.DSigCtx()
>>> dsig_ctx.signKey = key
>>> dsig_ctx.verify(node)
0
>>> dsig_ctx.status == xmlsec.DSigStatusSucceeded
True
Or, same thing with a key manager:
>>> key = xmlsec.cryptoAppKeyLoad('pubkey', xmlsec.KeyDataFormatPem, None, None, None)
>>> mngr = xmlsec.KeysMngr(); xmlsec.cryptoAppDefaultKeysMngrInit(mngr)
0
>>> xmlsec.cryptoAppDefaultKeysMngrAdoptKey(mngr, key)
0
>>> dsig_ctx = xmlsec.DSigCtx(mngr)
>>> dsig_ctx.verify(node)
0
>>> dsig_ctx.status == xmlsec.DSigStatusSucceeded
True
I stumbled upon an old email thread in which a user of the xmlsec c library describes his trouble with using the certificate file directly, and gives the aforementioned command to convert it to a public key.
He is also able to get the library to perform the conversion a few emails later by making a call to xmlSecOpenSSLAppKeyFromCertLoadBIO. Presumably the xmlsec command line utility does this when given the --pubkey-cert-pem flag. However, I was not able to find a corresponding method in the python library after greping around for a bit. So it looks like at the moment it's not possible.
Edit
It is possible to convert the certificate to a public key using M2Crypto (documentation), a Python wrapper for OpenSSL. I adapted answers from Extracting public key from certificate... and a blog post from Sheogora to work with this particular case.
>>> from M2Crypto import X509
>>> cert = X509.load_cert('cert', X509.FORMAT_PEM)
>>> pubkey = cert.get_pubkey().get_rsa()
>>> pubkey.save_key('pubkey', cipher=None)
1 # Success
The public key will be saved in PEM format with no encryption to file pubkey and can now be loaded using xmlsec.cryptoAppKeyLoad('pubkey', xmlsec.KeyDataFormatPem, None, None, None).
I have a RSA public key in PEM format + PKCS#1(I guess):
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAJNrHWRFgWLqgzSmLBq2G89exgi/Jk1NWhbFB9gHc9MLORmP3BOCJS9k
onzT/+Dk1hdZf00JGgZeuJGoXK9PX3CIKQKRQRHpi5e1vmOCrmHN5VMOxGO4d+zn
JDEbNHODZR4HzsSdpQ9SGMSx7raJJedEIbr0IP6DgnWgiA7R1mUdAgMBAAE=
-----END RSA PUBLIC KEY-----
I want to get the SHA1 digest of its ASN1 encoded version in Python. The first step should be to read this key, but I failed to do it in PyCrypto:
>> from Crypto.PublicKey import RSA
>> RSA.importKey(my_key)
ValueError: RSA key format is not supported
The documentation of PyCrypto says PEM + PKCS#1 is supported, so I'm confused.
I've also tried M2Crypto, but it turns out that M2Crypto does not support PKCS#1 but only X.509.
PyCrypto supports PKCS#1 in the sense that it can read in X.509 SubjectPublicKeyInfo objects that contain an RSA public key encoded in PKCS#1.
Instead, the data encoded in your key is a pure RSAPublicKey object (that is, an ASN.1 SEQUENCE with two INTEGERs, modulus and public exponent).
You can still read it in though. Try something like:
from Crypto.PublicKey import RSA
from Crypto.Util import asn1
from base64 import b64decode
key64 = 'MIGJAoGBAJNrHWRFgWLqgzSmLBq2G89exgi/Jk1NWhbFB9gHc9MLORmP3BOCJS9k\
onzT/+Dk1hdZf00JGgZeuJGoXK9PX3CIKQKRQRHpi5e1vmOCrmHN5VMOxGO4d+znJDEbNHOD\
ZR4HzsSdpQ9SGMSx7raJJedEIbr0IP6DgnWgiA7R1mUdAgMBAAE='
keyDER = b64decode(key64)
seq = asn1.DerSequence()
seq.decode(keyDER)
keyPub = RSA.construct( (seq[0], seq[1]) )
Starting from version 2.6, PyCrypto can import also RsaPublicKey ASN.1 objects.
The code is then much simpler:
from Crypto.PublicKey import RSA
from base64 import b64decode
key64 = b'MIGJAoGBAJNrHWRFgWLqgzSmLBq2G89exgi/Jk1NWhbFB9gHc9MLORmP3BOCJS9k\
onzT/+Dk1hdZf00JGgZeuJGoXK9PX3CIKQKRQRHpi5e1vmOCrmHN5VMOxGO4d+znJDEbNHOD\
ZR4HzsSdpQ9SGMSx7raJJedEIbr0IP6DgnWgiA7R1mUdAgMBAAE='
keyDER = b64decode(key64)
keyPub = RSA.importKey(keyDER)