Rutoken, OpenSSL, dan CA lokal untuk menandatangani pesan

Beberapa waktu lalu, ada kebutuhan dalam kerangka kerja proyek untuk membatasi jumlah komputer secara simultan yang memiliki akses ke aplikasi web yang berjalan dalam jaringan area lokal pelanggan.

Keputusan untuk menggunakan token USB perangkat keras untuk mengidentifikasi komputer datang dengan sendirinya. Pilihannya ada pada Rutoken EDS: ini bekerja tanpa driver, untuk bekerja dalam aplikasi Web hanya diperlukan plug-in untuk browser, yang dikeluarkan oleh pengembang. Karena token harus mengidentifikasi komputer, bukan pengguna, bekerja dengannya harus benar-benar "transparan": jika ada, maka sistem hanya bekerja secara diam-diam tanpa mengajukan pertanyaan yang tidak perlu kepada pengguna.

Diputuskan: ketika masuk ke sistem, tandatangani kredensial pengguna dengan tanda tangan yang tidak memenuhi syarat dari sertifikat yang disimpan di Rutoken menggunakan plugin Rootoken, dan periksa di server. Setelah login berhasil menggunakan plug-in, periksa keberadaan fisik dari token yang sama, dan jika tidak ada, logout dari sistem. Dalam kerangka proyek yang disebutkan, ini sudah cukup.

Ada kebutuhan untuk membuat Otoritas Sertifikasi Anda sendiri (CA) untuk bertukar pesan yang ditandatangani, atau lebih tepatnya, untuk mengirim pesan yang ditandatangani dari klien ke server. Sertifikat klien harus ditempatkan pada token USB dalam wadah kunci pribadi, dan verifikasi tanda tangan harus dilakukan pada server menggunakan OpenSSL

Jadi, tugas: instalasi dan konfigurasi pada server Linux CA. Menyebarkan sertifikat klien yang mengidentifikasi komputer pada token USB .

Untuk mengatasinya, Anda perlu:


  1. Kami membuat direktori di mana CA akan ditemukan dan menyalin konfigurasi OpenSSL yang disertakan dengan sistem (ada /etc/ssl/openssl.cnf di versi terbaru Ubuntu)
  2. Kami mengkonfigurasi "kami" openssl.cnf:

    a) Tambahkan ke awal arahan file untuk menghubungkan mesin token:

    openssl_conf = openssl_def [ openssl_def ] engines = engine_section [ engine_section ] rtengine = gost_section [ gost_section ] dynamic_path = /path/to/rutoken/openssl/connector/librtengine.so MODULE_PATH = /path/to/rutoken/pkcs11/librtpkcs11ecp.so RAND_TOKEN = pkcs11:manufacturer=Aktiv%20Co.;model=Rutoken%20ECP default_algorithms = CIPHERS, DIGEST, PKEY, RAND 

    b) batalkan komentar pada garis

     # req_extensions = v3_req # The extensions to add to a certificate request 

    c) di bagian [v3_req] , tentukan parameter berikut:

     subjectSignTool = ASN1:FORMAT:UTF8,UTF8String:   extendedKeyUsage=emailProtection keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment 

    d) di bagian [v3_ca], hapus opsi kritis dari parameter basicConstraints:

     basicConstraints = CA:true 

    Untuk apa? Jawaban jujur: Saya tidak tahu. Namun, semua contoh sertifikat root yang saya unduh saat mencoba mencari tahu topik itu tanpa tanda kritis. Saya mengajukan pertanyaan "untuk apa?" kolega yang lebih berpengalaman.


    e) secara opsional mengatur nilai-nilai default yang akan ditawarkan ketika menerbitkan sertifikat yang ditandatangani sendiri dan menghasilkan permintaan untuk menerbitkan sertifikat klien. Parameter ini ada di bagian [req_distinguished_name]

    Parameter dengan postfix _default adalah nilai default. Contoh:

     countryName = Country Name (2 letter code) countryName_default = AU countryName_min = 2 countryName_max = 2 

    Ketika sistem meminta Anda untuk memasukkan parameter countryName , itu akan menunjukkan dalam tanda kurung siku bahwa itu akan meninggalkan nilai AU secara default.


    Ini melengkapi konfigurasi konfigurasi OpenSSL. Tetap menunjukkan ke OpenSSL bahwa perlu untuk menggunakannya. Untuk melakukan ini, setel variabel lingkungan OPENSSL_CONF:

     export OPENSSL_CONF=/path/to/your/openssl.cnf 
  3. Kami membuat struktur direktori tempat informasi tentang CA kami akan disimpan.
    Untuk melakukan ini, buka direktori yang dibuat dengan openssl.cnf yang baru diedit, dan lakukan langkah-langkah berikut:

    a) membuat subdirektori di dalamnya:

    demoCA
    demoCA / pribadi
    demoCA / newcerts

    Catatan: nama demoCA dieja dalam bagian [CA_default] pada file openssl.cnf . Anda dapat mengubahnya (dalam langkah 2) dan kemudian bekerja dengannya alih-alih demoCA.

    b) di direktori demoCA, buat file index.txt kosong dan file serial , yang kita buka dengan editor teks dan tulis baris 01 di sana. Ini adalah counter sertifikat yang dikeluarkan. Setelah penerbitan setiap sertifikat berikutnya, nilai dalam file ini bertambah satu.
  4. Kami secara opsional memformat token kami menggunakan utilitas rtAdmin. Sekarang semuanya siap untuk penerapan CA.

    Algoritme tindakan secara luas sederhana:

    a) kami mengeluarkan sertifikat root dari pusat sertifikasi menggunakan algoritma GOST:

    • menghasilkan kunci pribadi untuk mengeluarkan sertifikat CA yang ditandatangani sendiri
    • menghasilkan sertifikat X509 yang ditandatangani sendiri menggunakan kunci yang dibuat

    b) pada masing-masing token USB

    • menghasilkan pasangan kunci (yang disebut wadah kunci pribadi)
    • buat permintaan penandatanganan sertifikat menggunakan kunci token yang dihasilkan
    • keluarkan sertifikat untuk permintaan ini
    • simpan sertifikat pada token dalam wadah kunci pribadi

    Berikut ini adalah implementasi algoritme ini untuk token tunggal:

    Pembuatan kunci pribadi untuk sertifikat CA (kami menggunakan algoritma GOST):

     openssl genpkey -algorithm gost2012_256 -pkeyopt paramset:A -outform PEM -out demoCA/private/cakey.pem 

    Kami menerbitkan sertifikat CA yang ditandatangani sendiri:

     <b>openssl req -new -x509 -key demoCA/private/cakey.pem -out demoCA/certs/cacert.pem -extensions v3_ca -days +3650 -outform PEM 

    Harap dicatat: kami menunjukkan pada baris perintah bahwa perlu untuk menggunakan ekstensi v3_ca dari config openssl_cnf. Di sanalah CA kami. Validitas 10 tahun. Suatu hal yang umum untuk CA. Tetapi lebih banyak yang mungkin.

    Dalam proses penerbitan sertifikat, sistem akan meminta Anda untuk memasukkan nilai parameter yang ada di bagian [req_distinguished_name] dari file openssl.cnf kami

    Sekarang kita mulai operasi token. Jika token baru atau diformat dengan nilai default, maka PIN pengguna di 12345678. Saya melanjutkan dari asumsi bahwa ini persis begitu. Jika tidak, Anda harus menentukan PIN pengguna yang benar dan umumnya mencoba memastikan bahwa dalam contoh di bawah ini nama objek yang sudah ada pada token tidak tumpang tindih dengan yang dimasukkan.

    Pertama-tama, kami akan menghasilkan pasangan kunci. OpenSSL tidak dapat melakukan operasi ini pada Rutoken, jadi kami akan menggunakan utilitas pkcs11-tool dari paket OpenSC:

     pkcs11-tool --module /path/to/your/librtpkcs11ecp.so --login --pin 12345678 --keypairgen --key-type GOSTR3410:A --id 303030303031 --label 'client01' 

    Catatan penting: kami tentukan id 303030303031. Setiap dua digit id ini tidak lebih dari kode ASCII dari karakter β€œ0” dan β€œ1”. Untuk operasi dengan OpenSSL, akan terlihat seperti "id = 000001"

    Buat permintaan sertifikat:

     openssl req -utf8 -new -keyform engine -key 'pkcs11:id=000001' -engine rtengine -out demoCA/newcerts/client01.csr 

    Jika semuanya dilakukan dengan benar, maka sistem

    • meminta PIN
    • akan meminta parameter nama sertifikat (dari bagian [req_distinguished_name] )
    • akan mengeluarkan file permintaan penandatanganan sertifikat

    Dengan menggunakan permintaan ini, kami menandatangani sertifikat klien ( dalam contoh, sertifikat ini berlaku selama 1825 hari. Penting bahwa periode ini tidak melebihi periode validitas sertifikat root Anda ):

     openssl ca -utf8 -days +1825 -keyfile demoCA/private/cakey.pem -cert demoCA/certs/cacert.pem -in demoCA/newcerts/client01.csr -outdir demoCA/newcerts -out demoCA/certs/client01.pem 

    Sistem akan menampilkan sertifikat, bertanya tentang keputusan untuk menandatanganinya (jawab "y"), dan tentang keputusan untuk menyimpan sertifikat baru (sekali lagi jawab "y").

    Kami menyimpan sertifikat yang diterima untuk token:

     pkcs11-tool --module /path/to/your/librtpkcs11ecp.so --login --pin 12345678 --id=303030303031 -w demoCA/certs/client01.pem -y cert 

    Itu saja.

    Menguji "keajaiban" yang dibuat. Untuk melakukan ini, kami menandatangani dan memverifikasi tanda tangan dari frasa "Halo, dunia!":

     echo Hello,world! | openssl cms -nodetach -sign -signer demoCA/certs/client01.pem -keyform engine -inkey "pkcs11:id=000001" -engine rtengine -binary -noattr -outform PEM | openssl cms -verify -CAfile demoCA/certs/cacert.pem -inform PEM 

    Jika semuanya dilakukan dengan benar, sistem akan meminta PIN, menandatangani pesan, kemudian memverifikasi tanda tangan dan, jika berhasil, akan menampilkan pesan asli dan hasil verifikasi ("berhasil")

    Komentar . Kembali ke tugas judul dan penandatanganan menggunakan plugin, harus dicatat bahwa secara default plugin memberikan hasil penandatanganan tidak dalam format PEM, tetapi dalam format DER, dikodekan dalam base64. Oleh karena itu, untuk memverifikasi tanda tangan, Anda harus terlebih dahulu mendekode dari base64, dan ketika memeriksa tentukan format input DER.

    Semoga beruntung

Source: https://habr.com/ru/post/id444646/


All Articles