Asymmetric Encryption with node js and Decryption with Python - 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

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.

How to loop through a folder to encrypt/decrypt files using AES in python and delete original unencrypted files in that folder?

I am new to python and learning security and I am testing the below code on my kali VirtualBox machine. I would like to encrypt all files in a given directory(/home/kali/Desktop/files) by using a recursive function and giving them the ending format (.h3ckeD). is there such a way to achieve this?
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
# Storing the keys
pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
with open('private_key.pem', 'wb') as f:
f.write(pem)
pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# Encrypting and decrypting
f = open('test.txt', 'rb')
message = f.read()
f.close()
encrypted = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
original_message = private_key.decrypt(
encrypted,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
with open('rsa.decrypted.txt', 'wb') as f:
f.write(original_message)

Can I decrypt openssl encrypted data using any dependancy?

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)

Why does RSA decryption fail in python when encrypted in js?

I'm creating python server and js client. To authenticate users, I used RSA. After server sent public key, client encrypt msg using js 'crypto' module and return encrypted message. But I can't decrypt message in server using python 'cryptography'.
Here is my server(python) code.
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
import socketio
from aiohttp import web
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
sio = socketio.AsyncServer(async_mode='aiohttp', cors_allowed_origins='*')
app = web.Application()
sio.attach(app)
def main(): //key import from .pem
with open("private_key.pem", "rb") as key_file:
key.private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
with open("public_key.pem", "rb") as key_file:
key.public_key = serialization.load_pem_public_key(
key_file.read(),
backend=default_backend()
)
#Serialize to send as a message
key.public_key_serialization = key.public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
print(key.private_key_serialization.decode("utf-8"))
#sio.event
async def get_public_key(sid, data):
await sio.emit('public_key', {
'public': key.public_key_serialization.decode('utf-8'), #send public key
'data': encrypted}, room=sid)
def decrypt(sid, data): #decrypt from encrypted message
original_message = key.private_key.decrypt(
data["data"],
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(original_message)
the data["data"] is the encrypted message like b"'\xf5N\xb9\xe9\xfd\xac\x84'\xc9\x1dKkc\xb2%\xb7\xd2\xcb\x1a4\x8c\xean\xf2\x9b\xab^\xb9\x . . .
It is my client(js) code.
var crypto = require("crypto");
var buffer =require('buffer').Buffer;
const io = require("socket.io-client");
const socket = io.connect('http://localhost:8080');
var msg = crypto.publicEncrypt({
key: data["public"],
oaepHash: 'sha256'
}, buffer.from("encrypt me!")) #ciphertext: encrypt me!
console.log(msg)
(editor recognizes below text as code..)
the data["public"] is
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwvZD07r1IDHYMnDZqVql
glro/loIY9lUTpqdKaZigB0XE82pyDiqPZA2jzgxkAQJBKRO5u5PiN+UC2Ur5oqM
fQUyDefsKuC5c5rpnJK1px6IsjDzCym5DPXZoVbb7nYzmy0rLLwQZC/hZqIiuP/Y
y+3Orz49I+KSI4Lhq2kRWYhLUUhecdF+AJndkbZtWjsW1wc1tsCV0knQuVilPpwe
OmGgYQD/5xqcJRHHsYryGxFMW/2YJ1eD+3EzEUpRkXxaHIc9Uagc8TbT8uVbeoXi
Zrbl2BkfO6O8swBF+VgG3d6qZZoEyrk2TS3rB6oQSQWPFVissh4sFVOcjh37hdB2
BwIDAQAB
-----END PUBLIC KEY-----
private key is
-----BEGIN RSA PRIVATE KEY-----
MIIEpgIBAAKCAQEAwvZD07r1IDHYMnDZqVqlglro/loIY9lUTpqdKaZigB0XE82p
yDiqPZA2jzgxkAQJBKRO5u5PiN+UC2Ur5oqMfQUyDefsKuC5c5rpnJK1px6IsjDz
Cym5DPXZoVbb7nYzmy0rLLwQZC/hZqIiuP/Yy+3Orz49I+KSI4Lhq2kRWYhLUUhe
cdF+AJndkbZtWjsW1wc1tsCV0knQuVilPpweOmGgYQD/5xqcJRHHsYryGxFMW/2Y
J1eD+3EzEUpRkXxaHIc9Uagc8TbT8uVbeoXiZrbl2BkfO6O8swBF+VgG3d6qZZoE
yrk2TS3rB6oQSQWPFVissh4sFVOcjh37hdB2BwIDAQABAoIBAQCdxH961W4L0Yos
t1nMTEhnRn4JZn4nnvU0brYDwFsxZVkJc4KTPhe1ngAowcaJzlol4XjgM7U1BAhf
eE2gUDoD6bJpwmZBBH3OaWvmgmpxhKoF2Mq1G9xd+o1UnF95hzmXt2Oa3c095ek3
Drmej5u22whIk8sSQQUVq5JHDc02b0U/XyBHn+OqNMYn7EFsYHeSUMIcx58bQ/u4
Tvi0NdEovVciURFq173XM+BK+8oRnJBpEglskWfA6kuu5+NlpQgkzIM9vDutQyL0
Y9rJGxg3CvTQhn8vZx6COPyLRXTPc6IOExpwsTVmRAshGxbMbt6yXErCagge7VQh
mNymoqNRAoGBAOB2He8Ge7/tXeuTAptb6vgbNeoUjBxFNYmpDnEbplnM9Ydmgy/k
//2lNOu8bRTxk2wVKx35br/BcrJTlTmjzd2CYWJvBKQ9vYznAX2gVJ4MZXX/vHNO
GZEc1bwn5TaxUwywl0Q51TLT6KlHF+PBIttkQjCErbDhnMlrojlyNGw1AoGBAN5b
DY01XgKIUWegt4pRVG+LiQ+Oz547ksWIM338QP7o6BFLn85jAdByFmt94xgEUe4c
5FNRfZWOgbNLUSlbQ6AmUFVPDr3xfQDEKk65ci9dK4t/S7rajuHGHHzhW8wV/bYp
m7/N5ax0FEsyuJQpP0e0KambT1EJnWti6SERCQjLAoGBAMPers5XJQPdeZjJZ3v0
4PzymcCTf5Rn3IktChovm6E/Vn56OT5BIhXP5XdUrQeaqx+k9UQp1rfkclck0tJC
m7GRRbPk1vMPoWnkZ4udrllgzeUDbgpce7kCpYyUb9OjN6qaKtXxdZbuDlgxXqpz
bhxux8eY8AyrQ+sMTrq8avyFAoGBANOQJvC4Wl5mfa3vyTKd94y6YwqegwS3AgtY
cEXrAZyI1mW+YqrooQ1Hv/U+rhhn49x/OO/dlXP7R4TkoLCM2WdDjSPeONSZNKrJ
+sc0w2Q1bf0ofVGoKlK/QNPBSKqCMghkxoBU07amK7jw5ZZzOHZtAUcTMwCT+Wf3
kIGZx9LJAoGBAIWbpW1FIGiTJUzQDa2Y2n0S3P7vMpAI1YlIC32hGzKjtwKR4sWr
jqIgj7Zw67u3O8h0lwqyAMFxoMBfBbc2A3ctapPwHEs6TFqA5c1WKptt9LiqrP7n
oaD+XcUrgIed4gSa4KoXPoo2AFu3eyFq47/6jmV9rS42hut8s+KAds7r
-----END RSA PRIVATE KEY-----
According the docs, both use OAEP padding.
python cryptography - https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/#:~:text=RSA%20private%20key.-,decrypt,-(ciphertext%2C%20padding)
js crypto - https://nodejs.org/api/crypto.html#crypto_crypto_privatedecrypt_privatekey_buffer
I really don't know why it is failed.. Any advise, comments and suggestions will be appreciated.

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.

Categories

Resources