Jinja Formatting of Inline Certificate - python

I'm attempting to use Jinja to automate the creation of a config file with inline certificates. For the most part, the config as a whole looks as expected with the exception of the certificates. While I can get them into the end file, the formatting is messed up and thus not working.
The expected goal is obviously
pki:
# The CAs that are accepted by this node. Must contain one or more certificates created by 'nebula-cert ca'
ca: |
-----BEGIN CERTIFICATE-----
<snip>
-----END CERTIFICATE-----
cert: |
-----BEGIN CERTIFICATE-----
<snip>
-----END CERTIFICATE-----
key: |
-----BEGIN X25519 PRIVATE KEY-----
<snip>
-----END X25519 PRIVATE KEY-----
But I'm ending up with
pki:
# The CAs that are accepted by this node. Must contain one or more certificates created by 'nebula-cert ca'
ca: |
-----BEGIN CERTIFICATE-----
<snip>
-----END CERTIFICATE-----
cert: |
-----BEGIN CERTIFICATE-----
<snip>
-----END CERTIFICATE-----
key: |
-----BEGIN X25519 PRIVATE KEY-----
<snip>
-----END X25519 PRIVATE KEY-----
The snippet from my Jinja template looks like this:
pki:
ca: |
{{ca}}
cert: |
{{hostCert}}
key: |
{{hostKey}}
The template is obviously lined up, but I'm obviously missing some form of formatting. I've attempted to use the |center(x) formatting but it's not working... or doing anything that I can see. Does anyone have advice on getting the certificates to align properly so that they're read correctly?

Jinja is doing exactly what you've told it to do: it places the value of the ca variable in your text where you've placed the {{ ca }} token. The content of the ca variable isn't indented, so it's not indented when you place it in your document.
If you want to indent a block of text, Jinja provides the indent filter. You would use it like this:
pki:
ca: |
{{ca|indent(4)}}
Having said that...this seems like a situation in which using Jinja is a sub-optimal solution: why not just render the YAML from a Python data structure using yaml.safe_dump?

Related

How to decode CSR string in python?

-----BEGIN CERTIFICATE REQUEST-----
MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxEjAQBgNVBAgTCVlvdXJTdGF0ZTER
MA8GA1UEBxMIWW91ckNpdHkxCzAJBgNVBAsTAklUMRowGAYDVQQKExFZb3VyQ29t
cGFueSwgSW5jLjEYMBYGA1UEAxMPd3d3LmV4YW1wbGUuY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA379BFFxfACdXsUk2wrQka/nAlKbo+I9DAW32
+/SRxj/KtXVddscKW1obHGpMKPw4meJqOpQwJkIChYjSUQSpPKzdGpccDMf/eoF0
J7EaQ2szLv9AqdRQw2Aaek8SmocVmd3LxEOX4VvALBOMLHVrB5/vhYfGECLJbc3l
RdEbdXyHDtHklRAoIVQCfjTwBWGNAD337vmHW7Q0R6FYUoa4fcJh7Rv6jHSywqwx
7pVfaDbZPuTgUhw7wksKNFxccG0xcTMr/+GrciHEuZ0chq86CBP9RIyLpp2+RMSf
m6rMEYm9o65j7vEYaKEJUOJtA5MIs/ZjaXfS1LjXurLU0nCOQQIDAQABoAAwDQYJ
KoZIhvcNAQEFBQADggEBAK159goyAYOpcnrQ2EvCGlizrK1kS3D8JjnAiP1NHrjB
/qdTYR+/8Dr/hMcwwU5ThGAVf68eMkk6tUNwAdpZ9C904Js2z+ENEbO8GA0Fc4rw
ix7vb15vSXe3shGijRGIzzHVGRoR3r7xQtIuMaDAr3xlV8jHbcvZTcpX0Kbq6H1G
NLA4CXsOI4KGwu4FXfSzJEGb3gEJD8HaMP8V8er5G0owv/g/9Z/1/b0g97kAcUwk
M2eDsvPhMx/pENGbnLPe4XMy7NPiEdzFnaYtUy2BDcXj3ZQEWxRWklERgg9/YcWI
obf5ziuNm1Df24NBt5tpCNzfGviKT6/RYfWg3dMaKxc=
-----END CERTIFICATE REQUEST-----
I need signature algorithm data from it but I don't know how i achieve it.
from cryptography.x509 import load_pem_x509_csr
req = load_pem_x509_csr(b'''
-----BEGIN CERTIFICATE REQUEST-----
MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCVVMxEjAQBgNVBAgTCVlvdXJTdGF0ZTER
...
obf5ziuNm1Df24NBt5tpCNzfGviKT6/RYfWg3dMaKxc=
-----END CERTIFICATE REQUEST-----
''');
print(req.signature_hash_algorithm.name)

How do I take the user input as it is given and not have it converted to the string data type?

I have a key
b'-----BEGIN RSA PRIVATE KEY-----\nMIIDCgIBAAKBpwYMzwEMAwLajdq74D0Q7NRXICJr/EZHI6z0NcmVbiAj139f7apO\nWG0KV9MJVjENFkh1Ld64B2GY8Ibq7/jCz/nPU67eQPmAKU59COzGK0+WSiDJ+twE\nLwH0eqzvC6DauDngw2biWIR6p/A9OHFXm2xANW1CPq64a/h9IFlXslOhHtwjfv8k\nN0mZ/PHK9vxWJlWwxEmI/sBXJlAa1fxxCl62H2N4YIvrAgMBAAECgacCOSrJY7Sn\nk9GVlH1vc4zU67+vZqeq2/HMWWJ61iNGRGWpNYONloUAbVChCUlXdUu/DPDybAaq\nYx3hNu1BKbZsQziphpuyFNsZMPHasWixMrXDHvTWUcEuOYKjk4EksDsCplo1BryY\n+O6kel711Xi6zVXEt/1aWc8s6KP1sIPunSbUh4m9BIPQzrQ6ImdgY0XtSqpIvw2I\n2zPFnRb2ZsMx7KgnXt1VlzX2g=\n-----END RSA PRIVATE KEY-----'
I need to take this as an input
key = input("enter your key")
When I do this, the key is converted to a string.
"b'-----BEGIN RSA PRIVATE KEY-----\nMIIDCgIBAAKBpwYMzwEMAwLajdq74D0Q7NRXICJr/EZHI6z0NcmVbiAj139f7apO\nWG0KV9MJVjENFkh1Ld64B2GY8Ibq7/jCz/nPU67eQPmAKU59COzGK0+WSiDJ+twE\nLwH0eqzvC6DauDngw2biWIR6p/A9OHFXm2xANW1CPq64a/h9IFlXslOhHtwjfv8k\nN0mZ/PHK9vxWJlWwxEmI/sBXJlAa1fxxCl62H2N4YIvrAgMBAAECgacCOSrJY7Sn\nk9GVlH1vc4zU67+vZqeq2/HMWWJ61iNGRGWpNYONloUAbVChCUlXdUu/DPDybAaq\nYx3hNu1BKbZsQziphpuyFNsZMPHasWixMrXDHvTWUcEuOYKjk4EksDsCplo1BryY\n+O6kel711Xi6zVXEt/1aWc8s6KP1sIPunSbUh4m9BIPQzrQ6ImdgY0XtSqpIvw2I\n2zPFnRb2ZsMx7KgnXt1VlzX2g=\n-----END RSA PRIVATE KEY-----'"
Because of this I cannot use it for the purpose the key was created.
If I encode this key, the result becomes:
b"b'-----BEGIN RSA PRIVATE KEY-----\nMIIDCgIBAAKBpwYMzwEMAwLajdq74D0Q7NRXICJr/EZHI6z0NcmVbiAj139f7apO\nWG0KV9MJVjENFkh1Ld64B2GY8Ibq7/jCz/nPU67eQPmAKU59COzGK0+WSiDJ+twE\nLwH0eqzvC6DauDngw2biWIR6p/A9OHFXm2xANW1CPq64a/h9IFlXslOhHtwjfv8k\nN0mZ/PHK9vxWJlWwxEmI/sBXJlAa1fxxCl62H2N4YIvrAgMBAAECgacCOSrJY7Sn\nk9GVlH1vc4zU67+vZqeq2/HMWWJ61iNGRGWpNYONloUAbVChCUlXdUu/DPDybAaq\nYx3hNu1BKbZsQziphpuyFNsZMPHasWixMrXDHvTWUcEuOYKjk4EksDsCplo1BryY\n+O6kel711Xi6zVXEt/1aWc8s6KP1sIPunSbUh4m9BIPQzrQ6ImdgY0XtSqpIvw2I\n2zPFnRb2ZsMx7KgnXt1VlzX2g=\n-----END RSA PRIVATE KEY-----'"
Therefore I still cannot use it.
How do I take the input as bytes??
This is not an elegant answer but reading an RSA key from stdin isn't either so... As someone suggested in the comments, you should probably read it from a file. It would be cleaner, but hey you asked for stdin, so here is a stdin-based answer :
#!/usr/bin/python3
from sys import stdin
private_key = ""
for line in stdin:
private_key += line
# We need a stopping condition otherwise it will read from stdin forever
if "END RSA PRIVATE KEY" in line:
break
# We must validate what has been entered is correct (a regex would be better)
if not private_key.startswith("-----BEGIN RSA PRIVATE KEY-----"):
raise Exception("Invalid private key !")
print("Here is your private key :")
print(private_key)
Enter the key as is, not on one line, and as said in other answers, don't include b'' in your input :
$ python3 test.py
-----BEGIN RSA PRIVATE KEY-----
MIIDCgIBAAKBpwYMzwEMAwLajdq74D0Q7NRXICJr/EZHI6z0NcmVbiAj139f7apO
WG0KV9MJVjENFkh1Ld64B2GY8Ibq7/jCz/nPU67eQPmAKU59COzGK0+WSiDJ+twE
LwH0eqzvC6DauDngw2biWIR6p/A9OHFXm2xANW1CPq64a/h9IFlXslOhHtwjfv8k
N0mZ/PHK9vxWJlWwxEmI/sBXJlAa1fxxCl62H2N4YIvrAgMBAAECgacCOSrJY7Sn
k9GVlH1vc4zU67+vZqeq2/HMWWJ61iNGRGWpNYONloUAbVChCUlXdUu/DPDybAaq
Yx3hNu1BKbZsQziphpuyFNsZMPHasWixMrXDHvTWUcEuOYKjk4EksDsCplo1BryY
+O6kel711Xi6zVXEt/1aWc8s6KP1sIPunSbUh4m9BIPQzrQ6ImdgY0XtSqpIvw2I
2zPFnRb2ZsMx7KgnXt1VlzX2g=
-----END RSA PRIVATE KEY-----
Here is your private key :
-----BEGIN RSA PRIVATE KEY-----
MIIDCgIBAAKBpwYMzwEMAwLajdq74D0Q7NRXICJr/EZHI6z0NcmVbiAj139f7apO
WG0KV9MJVjENFkh1Ld64B2GY8Ibq7/jCz/nPU67eQPmAKU59COzGK0+WSiDJ+twE
LwH0eqzvC6DauDngw2biWIR6p/A9OHFXm2xANW1CPq64a/h9IFlXslOhHtwjfv8k
N0mZ/PHK9vxWJlWwxEmI/sBXJlAa1fxxCl62H2N4YIvrAgMBAAECgacCOSrJY7Sn
k9GVlH1vc4zU67+vZqeq2/HMWWJ61iNGRGWpNYONloUAbVChCUlXdUu/DPDybAaq
Yx3hNu1BKbZsQziphpuyFNsZMPHasWixMrXDHvTWUcEuOYKjk4EksDsCplo1BryY
+O6kel711Xi6zVXEt/1aWc8s6KP1sIPunSbUh4m9BIPQzrQ6ImdgY0XtSqpIvw2I
2zPFnRb2ZsMx7KgnXt1VlzX2g=
-----END RSA PRIVATE KEY-----
Edit as ShellCode said since key stream already contain new line characters this will make input to return prematurely so you have to either keep reading until end of key stream which means at -----END RSA PRIVATE KEY----- or read this key directly from a file.
key = ""
print("Enter your key: ")
while True:
key += input()
if "-----END RSA PRIVATE KEY-----" in key:
break
key_bytes = bytes(key, encoding="ascii")
this way you can paste whole key without problems. Also when you enter your key dont enter as b'-----BEGIN RSA PRIVATE (rest of key) instead just enter key directly without b' at beginning and ' at end of key(only enter the key data) like -----BEGIN RSA PRIVATE (rest of key). So whole key will be
-----BEGIN RSA PRIVATE KEY-----\nMIIDCgIBAAKBpwYMzwEMAwLajdq74D0Q7NRXICJr/EZHI6z0NcmVbiAj139f7apO\nWG0KV9MJVjENFkh1Ld64B2GY8Ibq7/jCz/nPU67eQPmAKU59COzGK0+WSiDJ+twE\nLwH0eqzvC6DauDngw2biWIR6p/A9OHFXm2xANW1CPq64a/h9IFlXslOhHtwjfv8k\nN0mZ/PHK9vxWJlWwxEmI/sBXJlAa1fxxCl62H2N4YIvrAgMBAAECgacCOSrJY7Sn\nk9GVlH1vc4zU67+vZqeq2/HMWWJ61iNGRGWpNYONloUAbVChCUlXdUu/DPDybAaq\nYx3hNu1BKbZsQziphpuyFNsZMPHasWixMrXDHvTWUcEuOYKjk4EksDsCplo1BryY\n+O6kel711Xi6zVXEt/1aWc8s6KP1sIPunSbUh4m9BIPQzrQ6ImdgY0XtSqpIvw2I\n2zPFnRb2ZsMx7KgnXt1VlzX2g=\n-----END RSA PRIVATE KEY-----

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 \\.

Getting pub key and digital signature using M2Crypto

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!!

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