4 Stimmen

Python 3 - Öffentlichen Schlüssel aus X509-Zertifikat extrahieren und damit verschlüsseln

Da die M2Crypto-Bibliothek für Python 3 nicht verfügbar ist, suche ich nach einer Möglichkeit, ein X509-Zertifikat einzulesen, den öffentlichen Schlüssel daraus zu extrahieren und für die RSA-Verschlüsselung zu verwenden.

Ich habe derzeit die folgenden beiden Funktionen:

from ssl import PEM_cert_to_DER_cert  # Standardbibliothek
from Crypto.Util import asn1  # http://pycrypto.org
from OpenSSL.crypto import *  # https://pythonhosted.org/pyOpenSSL/

def extract_publickey_1(certstr):
    """ von http://stackoverflow.com/questions/12911373 """
    der = PEM_cert_to_DER_cert(certstr)
    cert = asn1.DerSequence()
    cert.decode(der)
    tbs = asn1.DerSequence()
    tbs.decode(cert[0])
    return tbs[6]

def extract_publickey_2(certstr):
    return dump_privatekey(FILETYPE_ASN1, 
                           load_certificate(FILETYPE_PEM, certstr).get_pubkey())

Die erste Funktion wirft für einige Zertifikate einen IndexError aus, insbesondere für diejenigen, die nicht aus der OpenSSL-Befehlszeile generiert wurden, sondern aus einer kryptografischen Bibliothek (Python- und C#-Bibliotheken wurden getestet). Sie funktioniert für Zertifikate, die mit der OpenSSL-Befehlszeile generiert wurden.

Ich habe die Ausgabe der zweiten Funktion untersucht und sie war nicht identisch mit der ersten, aber die letzten 266 Byte der Ausgabe sind äquivalent:

extract_publickey_1(certstr)[-266:] == extract_publickey_2(certstr)[-266:]

gibt True zurück.

Meine Frage ist, was passiert hier? Gibt es eine Lösung dafür?

4voto

Anton Samsonov Punkte 1240

Zunächst müssen Sie verstehen, dass ein X.509-Zertifikat im ASN.1-Format codiert ist und daher als tief verschachtelte und beliebig verschachtelte Sammlung verschiedener Werte dargestellt wird — und dass das Verschachtelungsstil und Wertdatentypen sogar im DER-Modus beliebig sein können. Es ist also sehr naiv, ein Feld an einer festen Stelle und in einer festen Form zu erwarten, d.h. ohne weitere Verschachtelung und mit einem strikten Datentyp (insbesondere wenn es um Textzeichenketten geht); ganz zu schweigen davon, dass die Verwendung von "Magischen Konstanten" immer eine schlechte Idee ist. Deshalb sollten Sie spezialisierte Funktionen verwenden wie get_pubkey() wann immer möglich, anstatt zu versuchen, ein komplexes Dokument selbst zu parsen wie Sie es mit der Klasse asn1 getan haben.

Zweitens müssen Sie verstehen, dass, weil die X.509-Spezifikation algorithmus-agnostisch ist, es keine spezifischen Felder für "RSA-Modulus", "RSA öffentlicher Exponent" und so weiter gibt. Stattdessen gibt es nur ein generisches Feld "Öffentlicher Schlüssel", das eine verschachtelte Reihe von Unterfeldern hat — die den Algorithmus OID und seine numerischen Attribute spezifizieren. Zum Beispiel haben RSA-öffentliche Schlüssel 2 Attribute: den Modulus n und den Verschlüsselungsexponenten e; zusätzlich präfixt Ihre Funktion extract_publickey_2() ein Attribut, das immer Null ist, und ich habe keine Ahnung, wofür es steht. Es ist sehr wahrscheinlich, dass Ihre RSA-Implementierung numerische Argumente anstelle von Byte-Arrays oder einer komplexen ASN.1-Wert erwartet, und deshalb werden Sie sie wahrscheinlich mit asn1.DerSequence.decode() oder einer spezifischeren RSA-Funktion extrahieren müssen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X