Can I decrypt openssl encrypted data using any dependancy? - python

I have used openssl to encrypt data using below command:
openssl cms -encrypt -in test.data -inform PEM -recip certificate.pem -outform PEM -out test_encrypted_data.txt
Now I want to decrypt above encrypted data using python. I have tried below code, but it is not working and is throwing:
ValueError: Ciphertext with incorrect length.
Code:
from Crypto.Cipher import PKCS1_OAEP, AES
from Crypto.PublicKey import RSA
from OpenSSL import crypto
import base64
data = open("test_encrypted_data.txt").read()
data = data.replace("-----BEGIN CMS-----", "").replace("-----END CMS-----", "")
data = base64.b64decode(data)
private_key = RSA.import_key(open("private_key_no_pass.pem").read())
decryptor = PKCS1_OAEP.new(private_key)
decryptedtext = decryptor.decrypt(data)
print(f"Decrypted Text : {decryptedtext.decode()}")

Check if openssl des 'base64' encode.
Probably -base64 parameter is missing in openssl.
So the text is encrypted but not base64 coded by openssl, and then your code does base64 decode and decrypts it.

Thanks all I have used openssl commands to decrypt file in python
decrypted_data = subprocess.check_output(
f'echo "{encryptedtext}" | openssl cms -decrypt -inkey services/private_key_no_pass.pem -inform PEM ',
shell=True)

Related

How to generate RSA private key using Fernet

This should be simple (famous last words)
In the terminal, i can run this command:
winpty openssl genrsa -des3 -out my_rsa_key_pair 2048
How can I do the exact same thing using pyca/cryptography ?
The Fernet method is not used as a method for generating RSA keys. Therefore, Fernet-based RSA key generation is not supported by pyca/cryptography. However, you can generate RSA keys in the pyca/cryptography package like this:
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend
private_key = rsa.generate_private_key(
public_exponent=65537, # Commonly used public exponent
key_size=2048, # Key size in bits
backend=default_backend()
)
public_key = private_key.public_key()
Hope this helps.

Asymmetric Encryption with node js and Decryption with Python

I have trouble with encryption and description using node js and python.
First create public/private keys,
openssl genrsa -out private_key.pem 4096
openssl rsa -pubout -in private_key.pem -out public_key.pem
then in nodejs
const crypto = require("crypto")
const fs = require("fs")
var encrypted = crypto.publicEncrypt({
key: fs.readFileSync('./public_key.pem', 'utf8'),
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: 'sha256'},
Buffer.from("123456"))
encrypted = encrypted.toString('base64')
Now I try to decrypt encrypted in python
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
with open("./private_key.pem", "rb") as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
original_message = private_key.decrypt(
encrypted,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
the decryption method raises an error
ValueError: Ciphertext length must be equal to key size.
I think the problem is different padding but I do not know how to use proper paddings.
These are my sources
Link1
Link2

Signing S/MIME content from Python [duplicate]

I'm trying to create a non-detached signature on python3. I currently have code that does this on python2 with m2crypto, but m2crypto isn't available for python3.
I've been trying rsa, pycrypto and openssl, but haven't seen to find how.
Here's the equivalent OpenSSL command:
openssl smime -sign -signer $CRTFILE -inkey $KEYFILE -outformDER -nodetach
It's the nodetach option that I can't imitate with either rsa, pyopenssl or pycrypto.
Has anyone does this on python3? I'd like to avoid using Popen+openssl as much as possible.
It looks like you can achieve this with pyca/cryptography if you do not mind doing some lower-level OpenSSL programming. You can give this a try:
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.bindings.openssl.binding import Binding
_lib = Binding.lib
_ffi = Binding.ffi
msg = "Hello, World!"
with open('key.pem', 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(), None, default_backend())
with open('cert.pem', 'rb') as cert_file:
cert = x509.load_pem_x509_certificate(
cert_file.read(), default_backend())
bio_in = _lib.BIO_new_mem_buf(msg.encode('utf-8'), len(msg))
pkcs7 = _lib.PKCS7_sign(cert._x509, private_key._evp_pkey, _ffi.NULL, bio_in, 0)
bio_out=_lib.BIO_new(_lib.BIO_s_mem())
_lib.PEM_write_bio_PKCS7(bio_out, pkcs7)
result_buffer = _ffi.new('char**')
buffer_length = _lib.BIO_get_mem_data(bio_out, result_buffer)
sout = _ffi.buffer(result_buffer[0], buffer_length)[:]
print(sout.decode('utf-8'))
This script is for illustration purposes only and there might be better ways to do it. This approach basically mimics your openssl smime command.
If you do want to go down this path, you will have to look closer at memory management and free up things when you are done. There is a reason why this stuff is called hazmat...
I actually ended up solving this with OpenSSL.crypto, albeit, with some internal methods:
from OpenSSL import crypto
PKCS7_NOSIGS = 0x4 # defined in pkcs7.h
def create_embeded_pkcs7_signature(data, cert, key):
"""
Creates an embeded ("nodetached") pkcs7 signature.
This is equivalent to the output of::
openssl smime -sign -signer cert -inkey key -outform DER -nodetach < data
:type data: bytes
:type cert: str
:type key: str
""" # noqa: E501
assert isinstance(data, bytes)
assert isinstance(cert, str)
try:
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, key)
signcert = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
except crypto.Error as e:
raise ValueError('Certificates files are invalid') from e
bio_in = crypto._new_mem_buf(data)
pkcs7 = crypto._lib.PKCS7_sign(
signcert._x509, pkey._pkey, crypto._ffi.NULL, bio_in, PKCS7_NOSIGS
)
bio_out = crypto._new_mem_buf()
crypto._lib.i2d_PKCS7_bio(bio_out, pkcs7)
signed_data = crypto._bio_to_string(bio_out)
return signed_data
This is possible using the cryptography package in python 3.
This is the OpenSSL command I was trying to replicate
openssl smime -sign
-signer cert.crt
-inkey cert.key
-certfile intermediate.pem
-nodetach
-outform der
-in mdm.mobileconfig
-out mdm-signed.mobileconfig
import cyptography
with open('cert.crt', 'rb') as fp:
cert = cryptography.x509.load_pem_x509_certificate(fp.read())
with open('intermediate.pem', 'rb') as fp:
ca = cryptography.x509.load_pem_x509_certificate(fp.read())
with open('cert.key', 'rb') as fp:
key = cryptography.hazmat.primitives.serialization.load_pem_private_key(
fp.read(), None,
)
with open('data.bin', 'rb') as fp:
data = fp.read()
signed_data = cryptography.hazmat.primitives.serialization.pkcs7.PKCS7SignatureBuilder(
data=data,
signers=[
(cert, key, cryptography.hazmat.primitives.hashes.SHA512()),
],
additional_certs=[ca],
).sign(
cryptography.hazmat.primitives.serialization.Encoding.DER, options=[],
)
-nodetach is achieved by default with options=[] since openssl adds the detached flag by default.

encrypt text message using rsa public key

I have been given a public key by my client, and I want to send him a text message which would be encrypted with his public key. The public key is with .pub extension.
I am trying to do this in bash via openssl command and via python using pycrypto module with no luck. I am a novice with no experience in cryptography.
How can I go about this.Thanks in advance
public_key
Suppositions:
The public key given by your client is in "key.pub" file
Taking the input from the user at run time for the string or text to be encrypted in a variable named, "msg".
Already installed Crypto.PublicKey library using command "sudo pip install Crypto.PublicKey"
Code:
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5
with open("key.pub", 'r') as f1:
pubkey = f1.read()
msg = raw_input("Enter String to be encrypted: ")
print("raw string->", msg)
keyPub = RSA.importKey(pubkey) # import the public key
cipher = Cipher_PKCS1_v1_5.new(keyPub)
cipher_text = cipher.encrypt(msg.encode()) # now we have the cipher
print("cipher text->", cipher_text)
Format for the Key in the file:
The format of key in the file should be like this,
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAybVqRvfYvWbLsB98BqkD
lWd0/5y6SyhHt6/r6M0l7JXBweqMvxVt7XmI2yqPL56YxzcgQ8ycDkoqHJ+XozgP
iRnLNpYRlCzsiaOElbmQcnrI8iOb9Ahm6j0cbBB1S8VNvD+u9RQJt53zPxPj8/Dq
f1oNGFXOM8udNYWZaRCukLs/TumsAn0a+BF4639WtFiUvTWdVhlyvCQTs49ytRkH
rXH30RkB528RIvTGeW8xBTV4NaiTIzAEKCVSPagLr4Hzbb9b5+bODic/zkLGQazy
/NKOFgiB7kD2+WEMcuhTr5noeXau0PDAhgmrBhzzWOjUwwaO+ACvJLkPXZfjhy7P
+wIDAQAB
-----END PUBLIC KEY-----

Loading a DER-encoded RSA key using M2Crypto

The method M2Crypto.RSA.RSA().save_key_der() can be used to save a key in the DER format. However, I do not see a corresponding method M2Crypto.RSA.load_key_der() as I would expect.
Is there a way to load a DER-encoded RSA key using M2Crypto?
The PEM format is base64-encoded DER data with some additional header and footer lines. You can just read DER as binary, transform it to PEM and pass that to RSA.load_key_string:
import base64
from M2Crypto import RSA
TEMPLATE = """
-----BEGIN RSA PRIVATE KEY-----
%s
-----END RSA PRIVATE KEY-----
"""
raw = open('key.der', 'rb').read()
data = TEMPLATE % base64.encodestring(raw).rstrip()
key = RSA.load_key_string(data)
print key
Output:
<M2Crypto.RSA.RSA instance at 0x10eb710>

Categories

Resources