
In den Kommentaren zum Artikel „Verwenden von kryptografischen Token-Mechanismen von PKCS # 11 in Skriptsprachen“ schrieb der
kovserg- Leser:
"Wir freuen uns auf einen Artikel mit der Funktion, ein Dokument zu signieren und einen Zeitstempel hinzuzufügen."
Zuvor schrieb ein anderer Teilnehmer des
Pas Habr
, dass es großartig wäre, wenn PKCS # 11-Token, "die jeder zählen kann" (dh hauptsächlich kryptografische Operationen zum Generieren von Schlüsseln, Generieren und Überprüfen elektronischer), alle Arten von Zwischenschichten loswerden und haben würden Ein Dienstprogramm, das mithilfe der Mechanismen des Tokens selbst eine Zertifikatanforderung bilden und Dokumente signieren, die Signatur von Dokumenten überprüfen, die Signatur und Gültigkeit von Zertifikaten überprüfen kann.
Bekanntschaft mit dem Dienstprogramm
Infolgedessen präsentieren wir das Dienstprogramm dem Benutzergericht

Die treibende Kraft dieses Dienstprogramms ist das kryptografische
PKCS # 11-Token mit Unterstützung für die russische Kryptografie mindestens GOST R 34.10-2012. Wenn Sie
öffentliche Dienste usw. nutzen
möchten , müssen Sie dennoch ein Token erwerben, das zertifizierte Tests im Zertifizierungssystem des FSB von Russland bestanden hat. Wenn dies Ihre interne elektronische Dokumentenverwaltung ist, liegt dies natürlich in Ihrem Ermessen. PKCS # 11-Token können unterschiedlich sein: Software, Hardware oder sogar
Cloud . Das Dienstprogramm ist in der Skriptsprache
Tcl / Tk geschrieben . Vergessen Sie beim Kauf eines PKCS # 11-Tokens nicht, zu erfahren, wo Sie die Bibliotheken für das gekaufte Token für verschiedene Plattformen herunterladen können. Bibliotheken sind in der Regel frei verfügbar. Das Dienstprogramm verwendet das
TclPKCS11- Paket, um auf kryptografische und andere
Tokenfunktionen zuzugreifen. Das Dienstprogramm wählt zunächst eine Bibliothek aus, die Ihre Token unterstützt. Beachten Sie, dass Bibliotheksbibliotheken gleichzeitig mit mehreren Token arbeiten können (Kombinationsfeld „Token / Smartcard auswählen“):

Die Frage kann sich stellen, aber was soll ich tun, wenn das Token nicht initialisiert ist oder ich PIN-Codes usw. ändern muss? Die Antwort ist einfach: Verwenden Sie das Token-Konfigurationsprogramm
p11conf .
Um die Liste der Token zu aktualisieren (deaktivieren Sie das Token, fügen Sie ein neues hinzu), klicken Sie einfach auf
nach Symbol

befindet sich rechts neben der Combobox "Wählen Sie einen Token / eine Smartcard"
Die Combox „Zertifikat“ enthält Beschriftungen aller Zertifikate, die auf dem ausgewählten (aktuellen) Token gespeichert sind:

Wenn Sie auf das Symbol klicken

Rechts neben dem Combobox-Zertifikat wird ein Fenster mit dem Inhalt des Zertifikats angezeigt:

Wenn Sie im Anzeigefenster auf die Schaltfläche „Speichern / Speichern“ klicken, wird der Inhalt des analysierten Zertifikats im Textformat in der von Ihnen angegebenen Datei gespeichert.
Um Informationen zum aktuellen Token anzuzeigen, können Sie auf die Schaltfläche "6. Informationen zum Token" klicken oder den Cursor auf die Token-Bezeichnung bewegen:

Um herauszufinden, welche kryptografischen Mechanismen das aktuelle Token unterstützt, klicken Sie einfach auf die Schaltfläche „5. Liste der Mechanismen“:

Erstellen Sie eine Zertifikatanforderung
Wir gehen zu den Hauptfunktionen des Dienstprogramms über. Und die erste solche Funktion besteht darin, eine Zertifikatanforderung zu erstellen (Schaltfläche "3. Zertifikatanforderung"):

Die Meldung "Token unterstützt keine Schlüssel ..." wird angezeigt, wenn das ausgewählte Token die Generierung dieses Schlüsseltyps nicht unterstützt. In diesem Fall müssen Sie einen anderen Schlüsseltyp oder ein anderes Token auswählen. In diesem Beispiel können Sie das RuToken ECP 2.0-Token verwenden (siehe den zweiten Screenshot). In der Combobox "Zertifikatsinhaber" können Sie angeben, wem das Zertifikat gehört: einer Person, einer juristischen Person oder einem einzelnen Unternehmer. Abhängig davon werden die auszufüllenden Felder auf den folgenden Seiten gebildet.
Ein wichtiges Feld ist hier das Feld "Name CIPF". Es ist ein wesentlicher Bestandteil eines qualifizierten Zertifikats und gibt an, wie das kryptografische Informationsschutzsystem das Schlüsselpaar generiert. Den Namen des Schutzzertifikats für kryptografische Informationen finden Sie im Produktformular oder zum Zeitpunkt des Kaufs des Tokens. Stimmt das Typfeld in den Token-Informationen mit dem Namen des kryptografischen Informationsschutzsystems überein, fällt es mir schwer zu sagen. Es ist also besser, das Formular zu sehen. Klicken Sie auf Weiter und füllen Sie die erforderlichen Felder aus:

Beim Ausfüllen versucht das Dienstprogramm, die Richtigkeit des Ausfüllens der Felder (E-Mail, PSRN usw.) durch entsprechende Warnungen zu überprüfen. Nach dem Ausfüllen der Hauptfelder werden Sie aufgefordert, das Format und den Speicherort der Zertifikatanforderung auf Ihrem Computer zu bestimmen. Sie müssen außerdem den PIN-Code Ihres Tokens eingeben:

Nachdem Sie auf die Schaltfläche "Weiter" geklickt haben, werden Sie aufgefordert, die eingegebenen Daten erneut zu überprüfen und Ihre Entscheidung durch Drücken der Taste "Fertig stellen" zu bestätigen:

Wenn Sie auf die Schaltfläche Fertig stellen klicken, wird auf Ihrem Token ein Schlüsselpaar generiert, eine Anforderung erstellt und signiert:

Und können Sie sicherstellen, dass die Schlüssel generiert und auf dem Token gespeichert werden? Ja Wir drücken die Schaltfläche „7. Token-Objekte“, geben den PIN-Code ein, um auf das Token zuzugreifen, und suchen nach den Objekten SKO_PRIVATE_KEY und CKO_PUBLIV_KEY, deren Beschriftungen mit dem Feld „COMMON NANE“ (CN) übereinstimmen, das Sie beim Erstellen der Zertifikatanforderung ausgefüllt haben. In unserem Beispiel war es der "Allmächtige Habr":

Sah und ging sofort zu einer anderen Seite. Der beste Beweis dafür, dass ein Schlüsselpaar erfolgreich erstellt wurde, ist das Vorhandensein der signierten Anforderung selbst. Um dies zu überprüfen, klicken Sie auf die Schaltfläche "Anforderung / Zertifikat anzeigen", wählen Sie die gespeicherte Anforderung aus, klicken Sie auf die Schaltfläche "Anforderung für Zertifikat anzeigen" und sehen Sie sich die Informationen zum Schlüsselpaar an:

Nachdem Sie sichergestellt haben, dass die Anfrage erfolgreich erstellt wurde, verstecken Sie das Token sicher mit dem privaten Schlüssel oder legen Sie es näher an das Herz (Menschen der älteren Generation wissen, wie man Party- oder Komsomol-Tickets speichert), kopieren Sie die Anfrage auf das Flash-Laufwerk, nehmen Sie die erforderlichen Dokumente (Reisepass usw.). und gehen Sie zur Zertifizierungsstelle, um ein Zertifikat zu erhalten. Ja, wenn dies keine Abteilungs-Zertifizierungsstelle ist, müssen Sie trotzdem Geld bezahlen. Alles ist wie mit einem
Reisepass .
Wir streben ein Zertifikat in CA anIn diesem Fall verwenden wir für die Ausstellung eines Zertifikats an den ehrwürdigen Habr auch die Zertifizierungsstelle von den Seiten aller Habr. CA beginnt mit der Prüfung unserer Anwendung:

Nachdem die Anwendung in die CA-Datenbank eingegeben wurde, berücksichtigt der autorisierte Administrator sie und lehnt Folgendes ab oder genehmigt sie:

Nachdem der Antrag genehmigt wurde, bestimmt der Antragsteller zusammen mit der autorisierten Person der Zertifizierungsstelle die Zwecke der Verwendung des Zertifikats:

Und danach hindert nichts die Ausstellung des Zertifikats:

Nach Ausstellung des Zertifikats exportiert der CA-Mitarbeiter das ausgestellte Zertifikat auf das Flash-Laufwerk von Hon. Habr:

Wir legen das Token-Zertifikat
Und so kehrt der glückliche Inhaber des Zertifikats in seine Heimat zurück und beschließt zunächst, das Zertifikat für den Token neben das Schlüsselpaar zu stellen. Klicken Sie dazu im Hauptfenster des Dienstprogramms auf die Schaltfläche "4. Anforderung / Zertifikat anzeigen", wählen Sie die Datei mit dem Zertifikat und die Operation "Zertifikat anzeigen" aus und klicken Sie auf die Schaltfläche, um die Operation auszuführen ":

Wir können auch die Gültigkeit des Zertifikats (aber wir hatten noch keine Zeit, es zu widerrufen) oder die Richtigkeit seiner Signatur überprüfen, indem wir den entsprechenden Vorgang auswählen:

Dienstprogrammcode zur Überprüfung der Zertifikatsignatur#!/usr/bin/env tclsh package require pki load ./tclpkcs11.so Tclpkcs11 # PKCS#11 #set pkcs11_module "/usr/local/lib64/librtpkcs11ecp_2.0.so" set pkcs11_module "/usr/local/lib64/libls11sw2016.so" puts "Connect the Token and press Enter" gets stdin yes set handle [pki::pkcs11::loadmodule $pkcs11_module] set slots [pki::pkcs11::listslots $handle] set i 0 foreach slotinfo $slots { set slotid [lindex $slotinfo 0] set slotlabel [lindex $slotinfo 1] set slotflags [lindex $slotinfo 2] if {[lsearch -exact $slotflags TOKEN_PRESENT] != -1} { set token_slotlabel $slotlabel set token_slotid $slotid # incr i break } } if {$i == 0} { puts " . ." exit } # PEM DER proc ::cert_to_der {data} { if {[string first "-----BEGIN CERTIFICATE-----" $data] != -1} { set data [string map {"\r\n" "\n"} $data] } array set parsed_cert [::pki::_parse_pem $data "-----BEGIN CERTIFICATE-----" "-----END CERTIFICATE-----"] if {[string range $parsed_cert(data) 0 0 ] == "0" } { # DER- "0" == 0x30 set asnblock $parsed_cert(data) } else { set asnblock "" } return $asnblock } proc usage {use error} { puts "Copyright(C) Orlov Vladimir (http://museum.lissi-crypto.ru/) 2019" if {$use == 1} { puts $error puts "Usage:\nverify_cert_with_pkcs11 <file with certificate> \[<file with CA certificate>\]\n" } } set countcert [llength $argv] if { $countcert < 1 || $countcert > 2 } { usage 1 "Bad usage!" exit } set file [lindex $argv 0] if {![file exists $file]} { usage 1 "File $file not exist" exit } # cert_user puts "Loading user certificate: $file" set fd [open $file] chan configure $fd -translation binary set cert_user [read $fd] close $fd if {$cert_user == "" } { usage 1 "Bad file with certificate user: $file" exit } set cert_user [cert_to_der $cert_user] if {$cert_user == ""} { puts "User certificate bad" exit } catch {array set cert_parse [::pki::x509::parse_cert $cert_user]} if {![info exists cert_parse]} { puts "User certificate bad" exit } #parray cert_parse if {$countcert == 1} { if {$cert_parse(issuer) != $cert_parse(subject)} { puts "Bad usage: not self signed certificate" } else { set cert_CA $cert_user } } else { set fileca [lindex $argv 1] if {![file exists $fileca]} { usage 1 "File $fileca not exist" exit } # cert_CA puts "Loading CA certificate: $fileca" set fd [open $fileca] chan configure $fd -translation binary set cert_CA [read $fd] close $fd if {$cert_CA == "" } { usage 1 "Bad file with certificate CA=$fileca" exit } set cert_CA [cert_to_der $cert_CA] if {$cert_CA == ""} { puts "CA certificate bad" exit } } foreach slotinfo $slots { set slotid [lindex $slotinfo 0] set slotlabel [lindex $slotinfo 1] set slotflags [lindex $slotinfo 2] if {[lsearch -exact $slotflags TOKEN_PRESENT] != -1} { set token_slotlabel $slotlabel set token_slotid $slotid } } # catch {array set cert_parse_CA [::pki::x509::parse_cert $cert_CA]} if {![info exists cert_parse_CA]} { puts "CA certificate bad" exit } # if {$cert_parse(issuer) != $cert_parse_CA(subject)} { puts "Bad issuer" exit } set aa [dict create pkcs11_handle $handle pkcs11_slotid $token_slotid] set tbs_cert [binary format H* $cert_parse(cert)] catch {set signature_algo_number [::pki::_oid_name_to_number $cert_parse(signature_algo)]} if {![info exists signature_algo_number]} { set signature_algo_number $cert_parse(signature_algo) } switch -- $signature_algo_number { "1.2.643.2.2.3" - "1 2 643 2 2 3" { # "GOST R 34.10-2001 with GOST R 34.11-94" set digest_algo "gostr3411" } "1.2.643.7.1.1.3.2" - "1 2 643 7 1 1 3 2" { # "GOST R 34.10-2012-256 with GOSTR 34.11-2012-256" set digest_algo "stribog256" } "1.2.643.7.1.1.3.3" - "1 2 643 7 1 1 3 3" { # "GOST R 34.10-2012-512 with GOSTR 34.11-2012-512" set digest_algo "stribog512" } default { puts " :$signature_algo_number" exit } } # tbs-!!!! set digest_hex [pki::pkcs11::digest $digest_algo $tbs_cert $aa] # asn- # binary scan $cert_CA H* cert_CA_hex array set infopk [pki::pkcs11::pubkeyinfo $cert_CA_hex [list pkcs11_handle $handle pkcs11_slotid $token_slotid]] set lpk [dict create pkcs11_handle $handle pkcs11_slotid $token_slotid] # pybkeyinfo lappend lpk "pubkeyinfo" lappend lpk $infopk(pubkeyinfo) array set lpkar $lpk puts "Enter PIN user for you token \"$token_slotlabel\":" gets stdin password if { [pki::pkcs11::login $handle $token_slotid $password] == 0 } { puts "Bad PIN" exit } if {[catch {set verify [pki::pkcs11::verify $digest_hex $cert_parse(signature) $lpk]} res] } { puts " =$res" exit } if {$verify != 1} { puts "BAD SIGNATURE=$verify" } else { puts "SIGNATURE OK=$verify" }
Wir sind jetzt jedoch daran interessiert, das empfangene Zertifikat in unser Token zu importieren. Wählen Sie den Vorgang "Zertifikat für Token importieren" und klicken Sie auf die Schaltfläche "Vorgang ausführen". Das Dienstprogramm überprüft die elektronische Signatur des Zertifikats. Dazu müssen Sie den PIN-Code für das Token eingeben. Und wenn alles gut geht, wird das Zertifikat in das Token importiert:

Die Bezeichnung (Spitzname) des Zertifikats ist in der Liste der Zertifikate aufgeführt:

Dies ist unser persönliches Zertifikat, ein Zertifikat, für das es ein Schlüsselpaar gibt. Wenn Sie sich die Liste der Objekte auf dem Token noch einmal ansehen, finden Sie drei Objekte mit der Bezeichnung "Allmächtiger Habr von UTs 12_512" und derselben CKA_ID. Diese
drei Objekte sind das Zertifikat selbst (CKO_CERTIFICATE), der öffentliche (CKO_PUBLIC_KEY) und der private (CKO_PRIVATE_KEY) Schlüssel. Die Bezeichnung für dieses Dreifach von Objekten lautet wie folgt:
<Inhaber eines CN-Zertifikats> von <Herausgeber eines CN-Zertifikats>.
Im Folgenden zeigen wir, wie Sie das Etikett ändern können.
Wie kann ich darauf zugreifen, nachdem wir das Zertifikat auf das Token gelegt haben? Um Zugriff auf die Funktionen zum Arbeiten mit Zertifikaten auf dem Token zu erhalten, bewegen Sie den Cursor einfach auf die Beschriftung „Zertifikat“ und drücken Sie die rechte Maustaste:

Wir unterschreiben das erste Dokument mit elektronischer Signatur
Warten wir auf den nächsten Artikel. Du musst ein paar Tage warten. Was dort noch berücksichtigt wird, geht aus dem Screenshot hervor:
Fortsetzung hier .