
Dalam komentar di artikel “Menggunakan Mekanisme Token Kriptografis PKCS # 11 dalam Bahasa Scripting”, pembaca
kovserg menulis :
"Kami menantikan artikel dengan fungsi menandatangani dokumen dan menambahkan cap waktu."
Sebelumnya, peserta
pas Habr yang lain
menulis bahwa itu akan bagus untuk token PKCS # 11, "yang dapat dihitung oleh semua orang" (artinya operasi kriptografi terutama untuk menghasilkan kunci, menghasilkan dan memverifikasi yang elektronik), menyingkirkan semua jenis interlayers dan memiliki satu utilitas yang dapat, menggunakan mekanisme token itu sendiri, membentuk permintaan sertifikat dan menandatangani dokumen, memverifikasi tanda tangan dokumen, memverifikasi tanda tangan dan validitas sertifikat.
Kenalan dengan utilitas
Akibatnya, kami menyajikan utilitas ke pengadilan pengguna

Kekuatan pendorong utilitas ini adalah
token kriptografi
PKCS # 11 dengan dukungan untuk kriptografi Rusia, setidaknya GOST R 34.10-2012. Jika Anda berniat untuk menggunakan
layanan publik , dll., Anda masih perlu membeli token yang telah lulus tes sertifikasi dalam sistem sertifikasi FSB Rusia. Jika ini adalah manajemen dokumen elektronik internal Anda, maka ini, tentu saja, atas kebijakan Anda. Token PKCS # 11 dapat berbeda: perangkat lunak, perangkat keras, atau bahkan
cloud . Utilitas ditulis dalam bahasa scripting
Tcl / Tk . Saat Anda membeli token PKCS # 11, jangan lupa untuk mendapatkan atau bertanya di mana Anda dapat mengunduh perpustakaan untuk token yang dibeli untuk berbagai platform. Perpustakaan umumnya tersedia secara bebas. Utilitas menggunakan paket
TclPKCS11 untuk mengakses fitur kriptografis dan token lainnya. Utilitas dimulai dengan memilih perpustakaan yang mendukung token Anda. Perhatikan bahwa perpustakaan perpustakaan secara bersamaan dapat bekerja dengan beberapa token (kotak kombo “pilih token / smartcard”):

Mungkin muncul pertanyaan, tetapi apa yang harus saya lakukan jika token tidak diinisialisasi atau saya perlu mengubah kode PIN, dll? Jawabannya sederhana - gunakan utilitas konfigurasi token
p11conf .
Untuk memperbarui daftar token (nonaktifkan token, tambahkan yang baru) cukup klik
oleh ikon

terletak di sebelah kanan kotak kombo “Pilih token / kartu pintar”
Combox "Certificate" berisi label semua sertifikat yang disimpan pada token yang dipilih (saat ini):

Jika Anda mengklik ikon

terletak di sebelah kanan Sertifikat kotak kombo, sebuah jendela muncul dengan isi sertifikat:

Jika Anda mengklik tombol "Simpan / Simpan" di jendela tampilan, konten sertifikat yang diurai dalam format teks akan disimpan dalam file yang Anda tentukan.
Untuk melihat informasi tentang token saat ini, Anda dapat mengklik tombol "6. Informasi tentang token" atau memindahkan kursor ke label token:

Untuk mengetahui mekanisme kriptografi mana yang didukung token saat ini, cukup klik tombol "5. Daftar mekanisme":

Buat permintaan sertifikat
Kami beralih ke fungsi utama utilitas. Dan fungsi pertama seperti itu adalah untuk membuat permintaan sertifikat (tombol "3. Permintaan sertifikat"):

Pesan "Token tidak mendukung kunci ..." muncul jika token yang dipilih tidak mendukung pembuatan jenis kunci ini. Dalam hal ini, Anda harus memilih jenis kunci atau token yang berbeda. Dalam contoh ini, Anda dapat menggunakan token RuToken ECP 2.0 (lihat tangkapan layar kedua). "Pemegang Sertifikat" Combobox memungkinkan Anda menentukan siapa yang akan memiliki sertifikat: individu, badan hukum, atau pengusaha individu. Bergantung pada ini, bidang yang akan diisi akan dibentuk pada halaman-halaman berikut.
Bidang signifikan di sini adalah bidang "Nama CIPF". Ini adalah bagian integral dari sertifikat yang berkualifikasi dan menunjukkan bagaimana sistem perlindungan informasi kriptografi akan menghasilkan pasangan kunci. Anda dapat mengetahui nama sertifikat perlindungan informasi kriptografis dalam formulir produk atau pada saat pembelian token. Apakah jenis bidang dalam informasi token bertepatan dengan nama sistem perlindungan informasi kriptografis, saya merasa sulit untuk mengatakannya. Jadi lebih baik melihat formulir. Klik Berikutnya dan isi bidang yang wajib diisi:

Saat mengisi, utilitas mencoba untuk mengontrol kebenaran mengisi kolom (email, PSRN, dll.) Dengan mengeluarkan peringatan yang sesuai. Setelah mengisi bidang utama, Anda akan diminta untuk menentukan format dan lokasi penyimpanan permintaan sertifikat di komputer Anda. Anda juga akan diminta untuk memasukkan kode PIN token Anda:

Setelah mengklik tombol "Selanjutnya", Anda akan diminta untuk melihat lagi apa yang Anda masukkan dan mengkonfirmasi keputusan Anda dengan menekan tombol "Selesai":

Dan, jika Anda mengklik tombol "Selesai", maka pasangan kunci akan dihasilkan pada token Anda, permintaan akan dibuat dan ditandatangani:

Dan dapatkah Anda memastikan bahwa kunci dibuat dan disimpan di token? Ya Kami menekan tombol "7. Objek token", masukkan kode PIN untuk mengakses token dan mencari objek SKO_PRIVATE_KEY dan CKO_PUBLIV_KEY, yang labelnya cocok dengan bidang "COMMON NANE" (CN) yang Anda isi saat membuat permintaan sertifikat. Dalam contoh kita, itu adalah "Habraha Mahakuasa":

Tampak dan segera pergi ke halaman lain. Bukti terbaik bahwa pasangan kunci telah berhasil dibuat adalah adanya permintaan yang ditandatangani itu sendiri. Untuk memverifikasi ini, tekan tombol "Lihat permintaan / sertifikat", pilih permintaan yang disimpan, klik tombol "Lihat permintaan untuk sertifikat" dan lihat informasi tentang pasangan kunci:

Setelah memastikan bahwa permintaan telah berhasil dibuat, sembunyikan token dengan kunci privat atau dekatkan ke hati (orang-orang dari generasi yang lebih tua tahu cara menyimpan tiket partai atau Komsomol), salin permintaan ke flash drive, ambil dokumen yang diperlukan (paspor, dll.) dan pergi ke CA untuk mendapatkan sertifikat. Ya, jika ini bukan CA departemen, maka Anda masih harus membayar uang. Semuanya seperti dengan
paspor .
Kami mencari sertifikat di CADalam hal ini, untuk menerbitkan sertifikat kepada Habr yang terhormat, kami juga akan menggunakan
CA dari semua Habr. CA mulai mempertimbangkan aplikasi kami:

Setelah aplikasi memasuki basis data CA, administrator yang berwenang mempertimbangkannya dan menolak atau menyetujui:

Setelah aplikasi disetujui, pemohon, bersama dengan orang yang berwenang dari CA, menentukan tujuan penggunaan sertifikat:

Dan setelah itu, tidak ada yang mencegah penerbitan sertifikat:

Setelah sertifikat dikeluarkan, karyawan CA mengekspor sertifikat yang diterbitkan ke flash drive Hon. Habr:

Kami menempatkan sertifikat token
Dan pemegang sertifikat yang beruntung itu kembali ke tanah asalnya dan pertama-tama memutuskan untuk meletakkan sertifikat untuk token di sebelah pasangan kunci. Untuk melakukan ini, pada jendela utama utilitas, klik tombol "4. Lihat permintaan / sertifikat", pilih file dengan sertifikat dan operasi "Lihat sertifikat" dan klik tombol untuk melakukan operasi ":

Kami juga dapat memeriksa validitas sertifikat (tetapi kami belum punya waktu untuk mencabutnya) atau kebenaran tanda tangannya dengan memilih operasi yang sesuai:

Kode Utilitas Verifikasi Penandatanganan Sertifikat#!/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" }
Tetapi kami sekarang tertarik pada operasi mengimpor sertifikat yang diterima ke token kami. Pilih operasi "Impor sertifikat untuk token" dan klik tombol "Lakukan operasi". Utilitas akan memverifikasi tanda tangan elektronik sertifikat. Untuk melakukan ini, Anda harus memasukkan kode PIN untuk token tersebut. Dan jika semuanya berjalan dengan baik, maka sertifikat akan diimpor ke token:

Label (nama panggilan) sertifikat dapat dilihat dalam daftar sertifikat:

Ini adalah sertifikat pribadi kami, sertifikat yang ada pasangan kunci. Dan jika Anda melihat daftar objek pada token lagi, kita akan menemukan tiga objek yang memiliki label "Mahakuasa Habr dari UT 12_512" dan CKA_ID yang sama.
Tiga objek ini adalah sertifikat itu sendiri (CKO_CERTIFICATE), publik (CKO_PUBLIC_KEY) dan kunci pribadi (CKO_PRIVATE_KEY). Label untuk triple objek ini ditetapkan sebagai berikut:
<Pemegang sertifikat CN> dari <penerbit sertifikat CN>.
Di bawah ini kami tunjukkan cara mengganti label.
Sekarang kita telah meletakkan sertifikat pada token, bagaimana cara mengaksesnya? Untuk mendapatkan akses ke fungsi bekerja dengan sertifikat yang terletak di token, cukup gerakkan kursor ke label "Sertifikat" dan tekan tombol mouse kanan:

Kami menandatangani dokumen pertama dengan tanda tangan elektronik
Mari kita tunggu artikel selanjutnya. Anda harus menunggu beberapa hari. Apa lagi yang akan dianggap dapat dipahami dari tangkapan layar:
Berlanjut ke sini .