Tokens criptográficos PKCS # 11. Utilitário gráfico "com a função de assinar e adicionar um carimbo de data / hora". Parte 1

Nos comentários do artigo “Usando mecanismos de token criptográfico PKCS # 11 em linguagens de script”, o leitor kovserg escreveu :
"Estamos ansiosos por um artigo com a função de assinar um documento e adicionar um carimbo de data / hora."
Anteriormente, outro participante do pas Habr escreveu que seria ótimo para os tokens PKCS # 11 ", que todos podem contar" (significando principalmente operações criptográficas para gerar chaves, gerar e verificar as eletrônicas), livrar-se de todos os tipos de intercalares e ter um utilitário que poderia, usando os mecanismos do próprio token, formar uma solicitação de certificado e assinar documentos, verificar a assinatura de documentos, verificar a assinatura e a validade dos certificados.

Familiaridade com o utilitário


Como resultado, apresentamos a utilidade ao tribunal de usuários

guipkcs7_tclpkcs11:



A força motriz desse utilitário é o token criptográfico PKCS # 11, com suporte para criptografia russa pelo menos GOST R 34.10-2012. Se você pretende usar serviços públicos , etc., ainda precisa adquirir um token que passou nos testes certificados no sistema de certificação do FSB da Rússia. Se esse é o seu gerenciamento interno de documentos eletrônicos, é claro que isso fica a seu critério. Os tokens PKCS # 11 podem ser diferentes: software, hardware ou até nuvem . O utilitário está escrito na linguagem de script Tcl / Tk . Ao adquirir um token PKCS # 11, não esqueça de obter ou perguntar onde é possível baixar as bibliotecas do token adquirido para várias plataformas. As bibliotecas geralmente estão disponíveis gratuitamente. O utilitário usa o pacote TclPKCS11 para acessar recursos criptográficos e outros tokens. O utilitário começa escolhendo uma biblioteca que suporte seus tokens. Observe que as bibliotecas de bibliotecas podem trabalhar simultaneamente com vários tokens (caixa de combinação "selecionar token / cartão inteligente"):



A pergunta pode surgir, mas o que devo fazer se o token não for inicializado ou se precisar alterar os códigos PIN etc.? A resposta é simples - use o utilitário de configuração de token p11conf .

Para atualizar a lista de tokens (desative o token, adicione um novo), clique em
por ícone localizado à direita da caixa de combinação "Escolha um token / cartão inteligente"
O "Certificado" combox contém etiquetas de todos os certificados armazenados no token (atual) selecionado:



Se você clicar no ícone localizada à direita do certificado da caixa de combinação, uma janela é exibida com o conteúdo do certificado:



Se você clicar no botão "Salvar / Salvar" na janela de visualização, o conteúdo do certificado analisado em formato de texto será salvo no arquivo especificado.
Para visualizar informações sobre o token atual, você pode clicar no botão "6. Informações no token" ou mover o cursor para o rótulo do token:



Para descobrir quais mecanismos criptográficos o token atual suporta, basta clicar no botão "5. Lista de mecanismos":



Crie uma solicitação de certificado

Passamos para as principais funções do utilitário. E a primeira função é criar uma solicitação de certificado (botão "3. Solicitação de certificado"):



A mensagem "O token não suporta chaves ..." será exibida se o token selecionado não suportar a geração desse tipo de chave. Nesse caso, você precisa selecionar um tipo diferente de chave ou um token diferente. Neste exemplo, você pode usar o token do RuToken ECP 2.0 (consulte a segunda captura de tela). O "Titular do certificado" da Combobox permite especificar quem será o proprietário do certificado: um indivíduo, uma entidade legal ou um empresário individual. Dependendo disso, os campos a serem preenchidos serão formados nas páginas seguintes.

Um campo significativo aqui é o campo "Nome CIPF". É parte integrante de um certificado qualificado e indica como o sistema de proteção de informações criptográficas irá gerar o par de chaves. Você pode descobrir o nome do certificado de proteção de informações criptográficas no formulário do produto ou no momento da compra do token. O campo de tipo nas informações do token coincide com o nome do sistema de proteção de informações criptográficas, acho difícil dizer. Então é melhor ver o formulário. Clique em Avançar e preencha os campos obrigatórios:



Ao preencher, o utilitário tenta controlar a correção do preenchimento dos campos (email, PSRN etc.) emitindo avisos apropriados. Após preencher os campos principais, você será solicitado a determinar o formato e o local de armazenamento da solicitação de certificado no seu computador. Você também precisará digitar o código PIN do seu token:



Depois de clicar no botão "Avançar", você será solicitado a examinar novamente o que inseriu e confirmar sua decisão pressionando a tecla "Concluir":



E, se você clicar no botão Concluir, um par de chaves será gerado no seu token, uma solicitação será criada e assinada:



E você pode garantir que as chaves sejam geradas e armazenadas no token? Sim Pressionamos o botão "7. Objetos token", inserimos o código PIN para acessar o token e procuramos os objetos SKO_PRIVATE_KEY e CKO_PUBLIV_KEY cujas etiquetas correspondem ao campo "COMMAN NANE" (CN) que você preencheu ao criar a solicitação de certificado. No nosso exemplo, foi o "Todo-Poderoso Habr":



Olhou e imediatamente vá para outra página. A melhor evidência de que um par de chaves foi criado com sucesso é a presença da própria solicitação assinada. Para verificar isso, pressione o botão "Visualizar solicitação / certificado", selecione a solicitação salva, clique no botão "Visualizar solicitação de certificado" e veja as informações sobre o par de chaves:



Depois de garantir que a solicitação tenha sido criada com sucesso, oculte o token com segurança com a chave privada ou coloque-o mais próximo do coração (as pessoas da geração mais velha sabem como armazenar bilhetes de festa ou Komsomol), copie a solicitação para a unidade flash, leve os documentos necessários (passaporte, etc.) e vá para a CA para obter um certificado. Sim, se este não for um CA departamental, você ainda precisará pagar. Tudo é como um passaporte .

Nós vamos para um certificado na CA
Nesse caso, para emitir um certificado para o venerável Habr, também usaremos a CA nas páginas de todo o Habr. A CA inicia a consideração de nosso aplicativo:



Depois que o aplicativo entra no banco de dados da CA, o administrador autorizado o considera e rejeita ou aprova:



Após a aprovação do pedido, o requerente, juntamente com a pessoa autorizada da CA, determina os objetivos do uso do certificado:



E depois disso, nada impede a emissão do certificado:



Após a emissão do certificado, o funcionário da CA exporta o certificado emitido para a unidade flash do Hon. Habr:



Colocamos o certificado de token


E assim, o sortudo detentor do certificado retorna à sua terra natal e, em primeiro lugar, decide colocar o certificado do token ao lado do par de chaves. Para fazer isso, na janela principal do utilitário, clique no botão "4. Exibir solicitação / certificado", selecione o arquivo com o certificado e a operação "Exibir certificado" e clique no botão para executar a operação ":



Também podemos verificar a validade do certificado (mas ainda não tivemos tempo de revogá-lo) ou a exatidão de sua assinatura selecionando a operação apropriada:



Código do Utilitário de Verificação de Assinatura de Certificado
#!/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" } 


Mas agora estamos interessados ​​na operação de importação do certificado recebido para o nosso token. Selecione a operação "Importar certificado para token" e clique no botão "Executar operação". O utilitário verificará a assinatura eletrônica do certificado. Para fazer isso, você precisará digitar o código PIN do token. E se tudo correr bem, o certificado será importado para o token:



O rótulo (apelido) do certificado pode ser visto na lista de certificados:



Este é o nosso certificado pessoal, um certificado para o qual existe um par de chaves. E se você olhar a lista de objetos no token novamente, encontraremos três objetos com o rótulo "Todo-Poderoso Habr das UTs 12_512" e o mesmo CKA_ID. Esses três objetos são as chaves do próprio certificado (CKO_CERTIFICATE), públicas (CKO_PUBLIC_KEY) e privadas (CKO_PRIVATE_KEY). O rótulo para esse triplo de objetos é definido da seguinte maneira:
<Detentor de certificado CN> de <editor de certificado CN>.

Abaixo, mostramos como alterar o rótulo.

Agora que colocamos o certificado no token, como acessá-lo? Para obter acesso às funções de trabalhar com certificados localizados no token, basta mover o cursor para a etiqueta "Certificate" e pressionar o botão direito do mouse:



Assinamos o primeiro documento com assinatura eletrônica


Vamos aguardar o próximo artigo. Você tem que esperar alguns dias. O que mais será considerado lá pode ser entendido na captura de tela:



Continua aqui .

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


All Articles