cossacklabs / themis

Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.
https://www.cossacklabs.com/themis
Apache License 2.0
1.87k stars 143 forks source link

Convert Soter format RSA keys to PEM or DER? #992

Closed yen936 closed 1 year ago

yen936 commented 1 year ago

Thank you for reading this.

I am unable to use JSON web tokens in python because the jwt library uses the cryptography library under the hood and jwt expects the PEM format. The ability to convert the Soter format into PEM or DER (which could be converted into PEM) provides interoperability into other cryptosystems.

Am I missing some other solution? Or perhaps my thought process is off?

`

with open('keys/priv_themis_1.pem', 'rb') as f:
    private_key: bytes = f.read()

# Create JWT
payload = {
    'sub': 'user',
    'iat': datetime.datetime.utcnow(),
    'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
}
jwt_token = jwt.encode(payload, private_key, algorithm='RS256')`

ValueError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported 
algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', 
[_OpenSSLErrorWithText(code=75497580, lib=9, reason=108, reason_text=b'error:0480006C:PEM routines::no start line')])

I tried to manually make the keys--it failed Write the private key bytes to a file in PEM format

with open('private_key.pem', 'wb') as f:
    f.write(b'-----BEGIN PRIVATE KEY-----\n')
    f.write(base64.b64encode(private_key_bytes))
    f.write(b'\n-----END PRIVATE KEY-----\n')
ilammy commented 1 year ago

Themis format of RSA keys is not compatible with PKCS#8 encoded as BEGIN PRIVATE KEY in PEM.

You cannot easily convert it without knowing Themis key layout details.


Meanwhile, you should probably use cryptography directly to generate RSA key pairs.

from cryptography.hazmat.primitives.asymmetric import rsa
import datetime
import jwt

private_key = rsa.generate_private_key(public_exponent=65537, key_size=4096)

payload = {
    'sub': 'user',
    'iat': datetime.datetime.utcnow(),
    'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
}
jwt_token = jwt.encode(payload, private_key, algorithm='RS256')

print(jwt_token)

You might want to use PyThemis to encrypt the private key for storage, using Secure Cell with passphrase. But at this point might be better off using cryptography too, since it can encrypt its own private keys as well.


Having a way to "export" Themis keys into a common format could be nice, but it has its own downsides.

For example, Themis keys will always work with Themis cryptosystems. However, we cannot promise they would be usable, appropriate, or even secure to use with any other cryptosystems. Thus it's not necessarily something we'd want to encourage by providing such API.

Lagovas commented 1 year ago

Additionally, I want to remind that @ilammy wrote a great page in our documentation about soter layout for RSA keys. There enough information to understand how to extract manually private keys from the soter's container if you really need it.

yen936 commented 1 year ago

Thank you