Getting pub key and digital signature using M2Crypto - python

I used a GUI tool to make a X509 certificate and tried to use M2Crypto of Python to extract useful information from that cert, but came across issues. Code as below:
ca=X509.load_cert("MyCA.crt", X509.FORMAT_PEM)
print ca_pub.as_pem(cipher=None)
-----BEGIN PRIVATE KEY-----
MIIBJwIBADANBgkqhkiG9w0BAQEFAASCAREwggENAgEAAoIBAQDol4gW9mDc8IRW
Ack4Y0/Nk+OnikJPMj65YDIexVuW/ptCEnRAX+EZmB3lM4labS0Ou5gydKj3vpoR
dUM6Un1d8YYyw8Q2gJGXDHbTFjn/eU98VxIa7nHYlZGLvG5g0Eo4fCTUw3CBhI3Y
B8U3C89Ez1IL6sqly9Fhc5BICFtxVtCngWhapR3tIcR85h3vlUCmavhRyBmtdiku
As6ceH9GxfaFmONph/GzKVHy7iA6MSAIf/EDyz5jRKfWwhLQh4Uq9BWfioaFlQPF
iZlxs45iE3pAxrAAejkguUrjeAmIojQvQq9T0YNtdf3LQCUVn2Vfd9KkqncqADew
tujidoEZAgMBAAE=
-----END PRIVATE KEY-----
My questions:
Why get_pubkey() displays "Private Key" information? Should it begin with ---Begin Public Key ----- ?
The certificate is self-signed, and how to get the digital signature from the certificate?
Many thanks!!

Related

pyOpenSSL RSA private keys encrypted with AES 256

In pyOpenSSL i haven't been able to find a way to encrypt a RSA private key with AES 256 just yet, been looking all over the place for this but cant seem to find a way.
Before i used OpenSSL to get the key and ca/cl certificates but now im opting to make an application where i need to handle the pfx-file in certain ways.
In OpenSSL i used to do the following:
openssl pkcs12 -in file.pfx -nocerts -out key.key
after that i did:
openssl rsa -aes256 -key.key -out encrypted.key
is there anything similar in pyOpenSSL using crypto?
I believe I solved this. But for anyone wondering, this is what I did:
import os
import shutil
from Crypto.PublicKey import RSA
def encrypt(old_key, new_key, passphrase):
key = RSA.importKey(open(old_key, 'rb').read())
with open(new_key, 'wb') as f:
pem_key = key.export_key(format='PEM', passphrase=passphrase, pkcs=8, protection='PBKDF2WithHMAC-SHA1AndAES256-CBC')
f.write(pem_key)
f.close()
if os.path.exists(old_key):
os.remove(old_key)
encryptAES('path_to_old_key', 'path_to_new:key.key', 'supersecretpassword')
One question still remaining is if there's anyway to output the encryption info done in python similar to OpenSSL?
If you run openssl rsa -aes256 -in old.key -out new.key
The key will return attributes in the beginning like such:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC
Key here...
-----END RSA PRIVATE KEY-----
However when I export the private key in Python I just get:
-----BEGIN ENCRYPTED PRIVATE KEY-----
Key here...
-----END ENCRYPTED PRIVATE KEY-----
Is there anyway to display these attributes with pycryptodome?

Website authentication using smart cards' certificate and public key

So I have a credit card looking like smart card with a chip. This card logins on a website after the card is inserted into the card reader.
Now I have to write a program in python which can read the card and login on that website. After research on internet I found out that I need to extract :
Certificate and
Public key (since private key cannot be extracted)
from the card and then use these 2 things to create a HTTPs connection (example here) . So far I am able to extract certificate in pem format. But i cant find a way to extract key in pem format till now. I used PyKCS11 to read the card. Below is my code:
from asn1crypto import pem, x509
from PyKCS11 import *
import binascii
pkcs11 = PyKCS11Lib()
pkcs11.load(r'C:\Windows\System32\XXXX.dll')
print(pkcs11.getSlotList(tokenPresent=False))
slot = pkcs11.getSlotList(tokenPresent=False)[0]
print(pkcs11.getTokenInfo(slot))
session = pkcs11.openSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION)
session.login('123456')
result = []
result_pem = []
# find public key and print modulus
pubKey = session.findObjects([(CKA_CLASS, CKO_PUBLIC_KEY)])[0]
modulus = session.getAttributeValue(pubKey, [CKA_MODULUS])[0]
print("\nmodulus: {}".format(binascii.hexlify(bytearray(modulus))))
#find certificates
certs = session.findObjects([(CKA_CLASS, CKO_CERTIFICATE)])
for cert in certs:
cka_value, cka_id = session.getAttributeValue(cert, [CKA_VALUE, CKA_ID])
cert_der = bytes(cka_value)
cert = x509.Certificate.load(cert_der)
# Write out a PEM encoded value
cert_pem = pem.armor('CERTIFICATE', cert_der)
result.append(cert)
result_pem.append(cert_pem)
with open('cert.pem','wb') as f:
f.write(cert_pem)
print(result)
So here are my questions:
1. Is my approach right?
If yes, then how to extract public key in pem format?
How this smart card authentication actually works on client side and server side?
Public key extraxction
If you already have exported the certificate, it is probably easier to extract the public key from there, instead of from the smartcard. You can use openssl for that:
openssl x509 -in cert.pem -pubkey -out pubkey.pem -noout
Authentication
What you are trying to achieve is to open a TLS connection with mutual authentication using a client certificate. If you do this, the private key of your client certificate signs parts of the handshake to authenticate itself towards the server.
Extracting the certificate and the public key from the smartcard won't help you here. You need to find a library, which allows you to use your private key straight from your PKCS#11 token.

Separating SSL Certificate with Python RegEx

I have a SSL certificate file that contains the Certificate Body, Certificate Chain and Encrypted Private Key, e.g.
-----BEGIN CERTIFICATE-----
...
...
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
...
...
-----END CERTIFICATE-----
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
...
...
-----END ENCRYPTED PRIVATE KEY-----
I'm looking to separate it into it's three different parts using Python's RegEx library, re.
I tried many different things, e.g re.split(r'(-----BEGIN .+?-----(?s).+?-----END .+?-----)', exportCertificateOutput)
Any advice on how to do this? Thanks.
Based on the comment by #FailSafe I ended up going with:
re.findall("(-----[BEGIN \S\ ]+?-----[\S\s]+?-----[END \S\ ]+?-----)")
Please note you may have to escape the \ by doubling them \\.

Python JWT and RSA

I would like to learn about creating JWT using RSA public and private key. I am a beginner to learn securing my services. I am using pyjwt right now. I got something error with my testing, here it is:
SAMPLEKEY:
privatekey = """-----BEGIN RSA PRIVATE KEY-----MIICXQIBAAKBgQCkC2AfenNMfrU4oMfMZt9aZGBbFjzBTjV9Yttp0GHeVjIKboTwLkiKNqSKrm2Jralbteii2J9h6BeUBpv3B/Os7M0eNeM8B+5Rzm44vcmkzdtufTuX2utjoz8BFjelXw5og2i67NtxgiSHv2x1KCHbGZG+jpDOgjorxFusKbeGjQIDAQABAoGADbMJfvd543x9Y9JBfTdmFaVmSpUL09TVMLhtvGNzmN635RkfrvMeibRQf2hbq3C+QPNrDxZqEQIR3gHDSpj2Z2tGrE95a5o8+I3NBARkKOz41lMFm2AnXZLsM0ma+8S61j8AtELgFuKZWyi2t9A3Otf1+vayZVS/F8pyof0wD10CQQDXDloBpki887jVXtnIauV3Z1744P/uvVkWZOMTMiNF5Xh8SRPn2mNR80vUAAN5SL7zjGyDQeoYKZMRJaLFGsaPAkEAw0bCyz2aA+aWaTM1iyK4XK9/dNPoztE0lmeaHXvI7d1Zp0ipbLwewt4gRbSL7UpxdRQy0ELep4HoSTLt2dQPIwJBANCtS2c4XHKFKIBa5oaUO4+OjdiAM7gMoeqaAMG6sAF99ljbbGZZQnDd3WGclcJVdXzMcOs4xZeml99WnsgWAD8CQAWIfsKFh1Su9voaIl1D6ZduvZzQ2Frr4KKWYu6M8F+VExJDY9GZ7wE0jBONjx11K4vWu63dBzQV4UAZulWexaMCQQCmfoq0l1JtnYhV3LhEN3E8gwUK/0456An5YKunwO8nPrBsrdt/TQ6ZAUzh7JkmabV3h2KXQ+H0/cvfWBOhYaov-----END RSA PRIVATE KEY-----"""
publickey = """-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkC2AfenNMfrU4oMfMZt9aZGBbFjzBTjV9Yttp0GHeVjIKboTwLkiKNqSKrm2Jralbteii2J9h6BeUBpv3B/Os7M0eNeM8B+5Rzm44vcmkzdtufTuX2utjoz8BFjelXw5og2i67NtxgiSHv2x1KCHbGZG+jpDOgjorxFusKbeGjQIDAQAB-----END PUBLIC KEY-----"""
Here is my sample code:
#app.route('/token')
def token():
encodedToken = jwt.encode({'userid':'1'}, publickey, algorithm = 'RS256')
print(jwt.decode(encodedToken, privatekey, verify=True, algorithms='RS256'))
return "OKE"
And, I am getting this error when running it:
Is there any solution into this ?
Thanks
Basically you'll want to switch the keys, use the private key for "encoding" (signing) and public for "decoding" (verification).
This issue is reported on GitHub here: https://github.com/jpadilla/pyjwt/issues/81
And marked as "closed".

How to load an RSA key from a PEM file and use it in python-crypto

I have not found a way to load an RSA private key from a PEM file to use it in python-crypto (signature).
python-openssl can load a PEM file but the PKey object can't be used to retrieved key information (p, q, ...) to use with Crypto.PublicKey.construct().
I recommend M2Crypto instead of python-crypto. You will need M2Crypto to parse PEM anyway and its EVP api frees your code from depending on a particular algorithm.
private = """
-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBANQNY7RD9BarYRsmMazM1hd7a+u3QeMPFZQ7Ic+BmmeWHvvVP4Yj
yu1t6vAut7mKkaDeKbT3yiGVUgAEUaWMXqECAwEAAQJAIHCz8h37N4ScZHThYJgt
oIYHKpZsg/oIyRaKw54GKxZq5f7YivcWoZ8j7IQ65lHVH3gmaqKOvqdAVVt5imKZ
KQIhAPPsr9i3FxU+Mac0pvQKhFVJUzAFfKiG3ulVUdHgAaw/AiEA3ozHKzfZWKxH
gs8v8ZQ/FnfI7DwYYhJC0YsXb6NSvR8CIHymwLo73mTxsogjBQqDcVrwLL3GoAyz
V6jf+/8HvXMbAiEAj1b3FVQEboOQD6WoyJ1mQO9n/xf50HjYhqRitOnp6ZsCIQDS
AvkvYKc6LG8IANmVv93g1dyKZvU/OQkAZepqHZB2MQ==
-----END RSA PRIVATE KEY-----
"""
message = "python-crypto sucks"
# Grab RSA parameters e, n
from M2Crypto import RSA, BIO
bio = BIO.MemoryBuffer(private)
rsa = RSA.load_key_bio(bio)
n, e = rsa.n, rsa.e
# In Python-crypto:
import Crypto.PublicKey.RSA
pycrypto_key = Crypto.PublicKey.RSA.construct((n, e))
# Use EVP api to sign message
from M2Crypto import EVP
key = EVP.load_key_string(private)
# if you need a different digest than the default 'sha1':
key.reset_context(md='sha256')
key.sign_init()
key.sign_update(message)
signature = key.sign_final()
# Use EVP api to verify signature
public = """
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANQNY7RD9BarYRsmMazM1hd7a+u3QeMP
FZQ7Ic+BmmeWHvvVP4Yjyu1t6vAut7mKkaDeKbT3yiGVUgAEUaWMXqECAwEAAQ==
-----END PUBLIC KEY-----
"""
from M2Crypto import BIO, RSA, EVP
bio = BIO.MemoryBuffer(public)
rsa = RSA.load_pub_key_bio(bio)
pubkey = EVP.PKey()
pubkey.assign_rsa(rsa)
pubkey.reset_context(md="sha256")
pubkey.verify_init()
pubkey.verify_update(message)
assert pubkey.verify_final(signature) == 1
See http://svn.osafoundation.org/m2crypto/trunk/tests/test_rsa.py, but I prefer using the algorithm-independent EVP API http://svn.osafoundation.org/m2crypto/trunk/tests/test_evp.py.
How do you verify an RSA SHA1 signature in Python? addresses a similar issue.
is this (close to) what you tried doing?
public_key_filename = 'public_key.pem'
rsa = M2Crypto.RSA.load_pub_key(pk)
That should work. The issue might be with openssl too, does it work when you just use openssl (not in Python)?
Link to Me Too Crypto

Categories