angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Sichere Datenübertragung mit Public Key Verschlüsselung und pyNaCl

pyNaCl machen es sehr einfach, eine sichere Datenübertragung zu realisieren.

2 Dezember 2023 Aktualisiert 2 Dezember 2023
post main image
https://www.pexels.com/@reezky11

Dies ist ein kurzer Beitrag über die sichere Übertragung von Daten zwischen zwei Personen. Dazu verwenden wir das Paket Python pyNaCl , um private und öffentliche Schlüssel zu erzeugen und die Daten zu ver- und entschlüsseln. Ich habe auch das Paket Python keyring hinzugefügt, um die Pakete private_key und public_key zu speichern. Das ist nicht wirklich schwierig. Ich brauchte eine einfache Klasse, um dies zu tun, und hier teile ich sie. Vielleicht finden Sie sie nützlich.

Wie immer entwickle ich auf Ubuntu 22.04.

Wie es funktioniert

Es gibt zwei Personen, Bob und Alice. Bob möchte einige Daten über das Internet an Alice auf sichere Weise senden. Hier verwenden wir die Public-Key-Verschlüsselung.

Bob erzeugt einen eindeutigen private_key und public_key. Er hält die private_key geheim und teilt die public_key mit Alice. Alice folgt demselben Verfahren, hält ihre private_key geheim und teilt ihre public_key mit Bob.

Um die Daten an Alice zu senden, geht Bob folgendermaßen vor:

  • Bob verschlüsselt die Daten mit dem public_key von Alice
  • Bob signiert die Daten mit seinem eigenen private_key

Wenn Alice die verschlüsselten Daten erhält, verwendet sie ihre eigene private_key , um die Daten zu entschlüsseln, und verwendet die public_key von Bob , um zu überprüfen, dass die Daten tatsächlich von Bob stammen.

Speichern der private_key und public_key

Die meisten Systeme verfügen über einen Ort, an dem Passwörter sicher gespeichert werden, den sogenannten System keyring -Dienst. Das Python keyring -Paket kann als Schnittstelle zum System keyring -Service oder als eigenständige Speicherlösung verwendet werden.

Für jede user unserer Anwendung speichern wir die public_key und (optional) die private_key im Passwortfeld, wobei ein Wörterbuch verwendet wird, das in und aus JSON konvertiert wird.

Der Code

Erstellen Sie eine virtual environment und installieren Sie Folgendes:

> pip install pynacl
> pip install keyring

Sie können die Kodierung Base64 oder Hex für die Schlüssel und Daten wählen. Base64 ist weitaus effizienter. Vergessen Sie nicht, die Schlüssel zu löschen, wenn Sie zu einer anderen Kodierung wechseln!

# my_app.py
import json
import os
import sys
import traceback 

import keyring as kr

from nacl.utils import random
from nacl.public import Box, PrivateKey, PublicKey
from nacl.encoding import Base64Encoder, HexEncoder

class PKUtils:
    def __init__(
        self,
        key_encoding='hex',
        data_encoding='hex',
        kr_servicename=None,
    ):
        self.kr_servicename = kr_servicename
        self.key_encoder = Base64Encoder if key_encoding == 'base64' else HexEncoder
        self.data_encoder = Base64Encoder if data_encoding == 'base64' else HexEncoder

    def get_publ_key_from_priv_key(self, priv_key):
        priv_key_obj = PrivateKey(priv_key, encoder=self.key_encoder)
        publ_key_obj = priv_key_obj.public_key
        publ_key_encoded = publ_key_obj.encode(self.key_encoder)
        return publ_key_encoded.decode('ascii')

    def create_key_pair(self):
        priv_key_obj = PrivateKey.generate()
        priv_key_encoded = priv_key_obj.encode(self.key_encoder)
        priv_key = priv_key_encoded.decode('ascii')
        publ_key = self.get_publ_key_from_priv_key(priv_key)
        return priv_key, publ_key

    def get_box(self, sender_priv_key, receiver_publ_key):
        return Box(
            PrivateKey(sender_priv_key, encoder=self.key_encoder),
            PublicKey(receiver_publ_key, encoder=self.key_encoder)
        )

    def encrypt_data(self, sender_priv_key, receiver_publ_key, data):
        if isinstance(data, str):
            data = bytes(data, 'utf-8')
        box = self.get_box(sender_priv_key, receiver_publ_key)
        nonce = random(Box.NONCE_SIZE)
        encrypted_data = box.encrypt(data, nonce, encoder=self.data_encoder)
        return encrypted_data

    def decrypt_data(self, receiver_priv_key, sender_publ_key, encrypted_data, decode=None):
        box = self.get_box(receiver_priv_key, sender_publ_key)
        data = box.decrypt(encrypted_data, encoder=self.data_encoder)
        if decode is not None:
            data = data.decode('utf-8')
        return data

    def delete_key_pair_from_kr(self, username):
        try:
            kr.delete_password(self.kr_servicename, username)
        except:
            pass

    def get_key_pair_from_kr_or_create_new(self, username):
        try:
            keys = json.loads(kr.get_password(self.kr_servicename, username))
            return keys['priv_key'], keys['publ_key']
        except:
            pass
        priv_key, publ_key = self.create_key_pair()
        kr.set_password(
            self.kr_servicename,
            username,
            json.dumps({'priv_key': priv_key, 'publ_key': publ_key})
        )
        return priv_key, publ_key

    def set_public_key_in_kr(self, username, publ_key, keep_priv_key=False):
        priv_key_cur, publ_key_cur = self.get_key_pair_from_kr_or_create_new(username)
        if not keep_priv_key:
            priv_key_cur = None
        kr.set_password(
            self.kr_servicename,
            username,
            json.dumps({'priv_key': priv_key_cur, 'publ_key': publ_key})
        )
       

def main():
    pku = PKUtils(
        #key_encoding='base64',
        #data_encoding='base64',
        kr_servicename='my_app',
    )

    #pku.delete_key_pair_from_kr('bob')
    #pku.delete_key_pair_from_kr('alice')

    # bob gets/generates priv_key and publ_key
    bob_priv_key, bob_publ_key = pku.get_key_pair_from_kr_or_create_new('bob')
    print(f'bob_priv_key = {bob_priv_key}, bob_publ_key = {bob_publ_key}')

    # alice gets/generates priv_key and publ_key
    alice_priv_key, alice_publ_key = pku.get_key_pair_from_kr_or_create_new('alice')
    print(f'alice_priv_key = {alice_priv_key}, alice_publ_key = {alice_publ_key}')

    # bob wants to send this data
    data = """this is line 1
this is line 2
this is line 3
this is line 4
this is line 5
"""
    print(f'data = {data}')

    # bob encrypts the data
    try:
        encrypted_data = pku.encrypt_data(bob_priv_key, alice_publ_key, data)
        print(f'encrypted_data = {encrypted_data}')
    except Exception as e:
        print(f'encryption exception = {type(e).__name__}, e = {e}')
        traceback.print_exc() 

    # bob sends encrypted_data to alice ...

    # verify it is working, inject error
    #alice_priv_key = alice_publ_key
    #bob_publ_key = alice_publ_key

    # alice decrypts the received encrypted_data
    try:
        decrypted_data = pku.decrypt_data(alice_priv_key, bob_publ_key, encrypted_data, decode='utf-8')
        print(f'decrypted_data = {decrypted_data}')
    except Exception as e:
        print(f'decryption exception = {type(e).__name__}, e = {e}')
        traceback.print_exc() 

    print('ready')


if __name__ == '__main__':
    main() 

Zusammenfassung

Das Python pyNaCl Paket macht es sehr einfach, public_key Verschlüsselung zu implementieren. Die Public-Key-Verschlüsselung ist schwach gegenüber Man-in-the-Middle-Angriffen. Eine dritte Partei kann die öffentlichen Schlüssel ändern.
Denken Sie auch immer daran, dass die verschlüsselten Daten unterwegs kopiert werden können. Das bedeutet, dass alle (!) Daten, die von einem Dritten (über einen langen Zeitraum) kopiert wurden, entschlüsselt werden können, sobald ein Dritter in den Besitz der Schlüssel gelangt. Um dies zu vermeiden, können Sie Ihre Schlüssel nach einiger Zeit erneuern und die alten Schlüssel von Ihrem System entfernen!

Links / Impressum

C 431: Public-Key Encryption With Sodium (25 extra)
https://samsclass.info/141/proj/C431.htm

Public Key Encryption
https://www.geeksforgeeks.org/public-key-encryption

PyNaCl
https://pynacl.readthedocs.io/en/latest

Mehr erfahren

Cryptography

Einen Kommentar hinterlassen

Kommentieren Sie anonym oder melden Sie sich zum Kommentieren an.

Kommentare

Eine Antwort hinterlassen

Antworten Sie anonym oder melden Sie sich an, um zu antworten.