Exchange encrypted data between Python and C #

Exchange encrypted data between Python and C

Introduction

Public key cryptography, ** Roman **, isn't it (personal impression) </ sub>? It seems that you can do something fun, such as incorporating it into personally developed software, apart from its practicality.

However, as far as I googled roughly, ~~ I want to copy and paste script kiddies like myself ~~ I couldn't find any implementations that were extremely simple on the simple side, so for practice. just made it.

I thought that about 5% could be considered practical, so I will write it simply in Python and C #, and exchange encrypted data between the two. If this can be done, for example, data encrypted on the client side (C #) can be decrypted on the server side (Python), so it can be put to practical use, although it is a little.

** I don't say there is a better way to put it to practical use. ** **

Assumed situation

  1. Create an RSA key on the server side (Python)
  2. The client side (C #) has the public key created, which encrypts the text file
  3. Decrypt the encrypted file sent (decided) to the server side with the private key

environment

Python side

With Anaconda, it's easy because it contains almost everything and an encryption module.

If you want to start with Python alone, install pycrypto. [^ 1]

[^ 1]: There are multiple modules with the same function (and the function names are slightly different), which seems to be a source of confusion when searching. Here, we will use the one that comes standard with Anaconda.

cmd.exe


pip install -U pycrypto

C # side

.NET Core 3.0 or higher (.NET Framework 5.0 RC1) is required for some functions to apply .NET Standard 2.1.

Implementation

Creating a public / private key

CreateKey.py


from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5

key_length = 1024

def createKey():

    key = RSA.generate(key_length)

    private_key = key.exportKey().decode('utf-8')
    with open(file="private.pem", mode="w", encoding='utf-8') as file_out:
        file_out.write(private_key)

    public_key = key.publickey().exportKey().decode('utf-8')
    with open(file="public.pem", mode="w", encoding='utf-8') as file_out:
        file_out.write(public_key)

This will generate the key. The variable key_length specifies 1024 or greater, but according to the Manual for Another Similar Module (https://pycryptodome.readthedocs.io/en/latest/src/public_key/rsa.html), it should be 2048 or greater. Recommended, 1024,2048,3072 should be one of them. [^ 2] This time it doesn't need to be long, so 1024.

The generated key is saved separately as a private key and a public key. [^ 3]

[^ 2]: pycrypto manual is 404, where is the original?

[^ 3]: Actually, it seems that the public key data is also included in the private key file (?)

Encryption (C #)

Read the public key file created in Python and try to encrypt the short sentence.

The sample is created by the console application (.NET Core 3.1).

main.cs


using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

class Encrypt_sample
{
    static void Main(string[] args)
    {
        const string message = @"This is test message!";

        const string key_begin = "-----BEGIN PUBLIC KEY-----\r\n";
        const string key_end = "\r\n-----END PUBLIC KEY-----";

        string public_key = File.ReadAllText(@"public.pem");
        public_key = public_key.Replace(key_begin, "").Replace(key_end, "");

        var publicKeyBytes = Convert.FromBase64String(public_key);

        using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
        {
            rsa.ImportSubjectPublicKeyInfo(publicKeyBytes, out _);

            byte[] encrypted = rsa.Encrypt(Encoding.UTF8.GetBytes(message), false);

            File.WriteAllText(@"encrypted.txt", Convert.ToBase64String(encrypted));
        }
    }
}

The variable message is the string to be encrypted.

After reading the public key file public.pem created on the Python side, it is converted to bytes after removing the header and footer, and read into the RSACryptoServiceProvider type variable rsa with ImportSubjectPublicKeyInfo (). [^ 4]

[^ 4]: There is a function called ImportRSAPublicKey (), but this is the correct answer.

After that, encrypt the message converted to a byte string with Encrypt () and save the base64 converted text. The conversion is done so that it can be read as a text file.

If the second argument of Encrypt () is set to false, PKCS # 1 v1.5 padding will be used.

Encryption (Python)

In the assumed situation, encryption is done on the C # side, but create a function so that you can confirm that encryption / decryption is possible even on Python.

Encrypt.py


from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5

message = R"This is test message!"

def encrypt():
    with open(file="public.pem", mode='rb') as file_read:
        public_pem = file_read.read()

    public_key = RSA.importKey(public_pem)
    public_cipher = PKCS1_v1_5.new(key=public_key)

    encrypted = public_cipher.encrypt(message=message.encode())

    with open(file="encrypted.txt", mode='w', encoding='utf-8') as w:
        w.write(base64.b64encode(encrypted).decode('utf-8'))

As an actual work,

  1. Import the public key file (public_key)
  2. Convert from public_key to PKCS1_v1_5 format (?) (?) (Public_cipher)
  3. Encrypt message using public_cipher

is.

Decryption (Python)

The last is decryption.

Decrypt.py


from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5

def decrypt():
    with open(file="private.pem", mode='rb') as file_read:
        private_pem = file_read.read()

    private_key = RSA.importKey(private_pem)
    private_cipher = PKCS1_v1_5.new(key=private_key)

    with open(file="encrypted.txt", mode='r', encoding='utf-8') as r:
        encrypt_data = base64.b64decode(s=r.read())

    decrypt_data = private_cipher.decrypt(ct=encrypt_data, sentinel="")

    print(decrypt_data.decode('utf-8'))
  1. Import private key file (private_key)
  2. Convert from private_key to PKCS1_v1_5 format (?) (?) (Private_cipher)
  3. Decrypt the contents of the encrypted file using private_cipher

If the character string displayed by the last print () is the same as the message when it was created in C #, the decryption is successful.

Impressions

It's a frank impression that the code is shorter than I expected and it can be managed. ** I am surprised to find that it is relatively easy to encrypt / decrypt across languages by skipping detailed settings such as error handling, actual security, and practical encryption strength.

Please note that the ** code is really appropriate and should not be put to practical use. ** **

Things you should add

--General error handling --This and that about signatures --Higher encryption strength setting -* A strong heart that you can believe it's okay to implement this way *

Q&A

--Q: Why is there no key creation and decryption on the C # side?
→ Decryption aside (Is the private key deposited on the assumed client side?), And the key creation was a pass because the output to a format that can be shared was slightly troublesome. I will add if there is a good means.

Recommended Posts

Exchange encrypted data between Python and C #
[Python] Conversion memo between time data and numerical data
Easily exchange data between Python, R and Julia using the Feather format
Investigate Java and python data exchange with Apache Arrow
Boundary between C and Golang
Difference between Ruby and Python split
Difference between list () and [] in Python
Difference between == and is in python
Cooperation between python module and API
Differences between Python, stftime and strptime
Difference between python2 series and python3 series dict.keys ()
Hashing data in R and Python
[Python] Difference between function and method
Python --Difference between exec and eval
[Python] Difference between randrange () and randint ()
[Python] Difference between sorted and sorted (Colaboratory)
Communicate between Elixir and Python with gRPC
Differences in authenticity between Python and JavaScript
Differences between Ruby and Python in scope
difference between statements (statements) and expressions (expressions) in Python
Implement FIR filters in Python and C
Differences in syntax between Python and Java
Difference between PHP and Python finally and exit
Difference between @classmethod and @staticmethod in Python
Python data structure and internal implementation ~ List ~
Difference between append and + = in Python list
Difference between nonlocal and global in Python
Write O_SYNC file in C and Python
[Python] Difference between class method and static method
Python data structure and operation (Python learning memo ③)
Easily graph data in shell and Python
[Python3] Switch between Shift_JIS, UTF-8 and ASCII
Socket communication by C language and Python
[python] Difference between rand and randn output
Compress python data and write to sqlite
Differences in multithreading between Python and Jython
Differences between Ruby and Python (basic syntax)
RaspberryPi L Chika with Python and C #
Correspondence between Python built-in functions and Rust
Python C / C ++ Extension Pattern-Pass data to Python as np.array
Relationship between Firestore and Go data type conversion
How to generate permutations in Python and C ++
Data analysis python
Receive and display HTML form data in Python
The answer of "1/2" is different between python2 and 3
[Python] Swapping rows and columns in Numpy data
[python] Difference between variables and self. Variables in class
[Python] How to read data from CIFAR-10 and CIFAR-100
About the difference between "==" and "is" in python
Python hand play (interoperability between CSV and PostgreSQL)
python C ++ notes
Copy data between Google Keep accounts in Python
Try importing MLB data on Mac and Python
cv2 functions and data types (OpenCV python bindings)
Differences in behavior between append () and "+ =" operators when adding data to a list in Python
Full-width and half-width processing of CSV data in Python
List of Python libraries for data scientists and data engineers
Benchmark for C, Java and Python with prime factorization
File write speed comparison experiment between python 2.7.9 and pypy 2.5.0
Receives and outputs standard output of Python 2 and Python 3> C implementations
[Ruby vs Python] Benchmark comparison between Rails and Flask