Sichere Datenübertragung mit Public Key Verschlüsselung und pyNaCl
pyNaCl machen es sehr einfach, eine sichere Datenübertragung zu realisieren.
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
Neueste
- Ausblenden der Primärschlüssel der Datenbank UUID Ihrer Webanwendung
- Don't Repeat Yourself (DRY) mit Jinja2
- SQLAlchemy, PostgreSQL, maximale Anzahl von Zeilen pro user
- Anzeige der Werte in den dynamischen Filtern SQLAlchemy
- Sichere Datenübertragung mit Public Key Verschlüsselung und pyNaCl
- rqlite: eine hochverfügbare und distverteilte SQLite -Alternative
Meistgesehen
- Verwendung von Pythons pyOpenSSL zur Überprüfung von SSL-Zertifikaten, die von einem Host heruntergeladen wurden
- Verwendung von UUIDs anstelle von Integer Autoincrement Primary Keys mit SQLAlchemy und MariaDb
- Verbindung zu einem Dienst auf einem Docker -Host von einem Docker -Container aus
- PyInstaller und Cython verwenden, um eine ausführbare Python-Datei zu erstellen
- SQLAlchemy: Verwendung von Cascade Deletes zum Löschen verwandter Objekte
- Flask RESTful API Validierung von Anfrageparametern mit Marshmallow-Schemas