Rutoken, OpenSSL et une autorité de certification locale pour la signature des messages

Il y a quelque temps, il Ă©tait nĂ©cessaire dans le cadre du projet de limiter le nombre simultanĂ© d’ordinateurs ayant accĂšs Ă  une application Web fonctionnant sur le rĂ©seau local du client.

La dĂ©cision d'utiliser des jetons USB matĂ©riels pour identifier l'ordinateur est venue d'elle-mĂȘme. Le choix reposait sur le Rutoken EDS: il fonctionne sans pilotes, pour fonctionner dans une application Web, seul un plug-in pour le navigateur, Ă©mis par le dĂ©veloppeur, est nĂ©cessaire. Étant donnĂ© que le jeton doit identifier l'ordinateur et non l'utilisateur, travailler avec lui doit ĂȘtre complĂštement «transparent»: s'il existe, le systĂšme fonctionne simplement en silence sans poser Ă  l'utilisateur des questions inutiles.

Il a Ă©tĂ© dĂ©cidĂ©: lors de la connexion au systĂšme, signez les informations d'identification de l'utilisateur avec une signature non qualifiĂ©e d'un certificat stockĂ© sur Rutoken Ă  l'aide du plug-in Rootoken, et vĂ©rifiez sur le serveur. AprĂšs une connexion rĂ©ussie Ă  l'aide du plug-in, vĂ©rifiez la prĂ©sence physique du mĂȘme jeton et, en son absence, dĂ©connectez-vous du systĂšme. Dans le cadre du projet mentionnĂ©, c'Ă©tait suffisant.

Il est nĂ©cessaire de crĂ©er votre propre autoritĂ© de certification (CA) pour l'Ă©change de messages signĂ©s, ou plutĂŽt pour le transfert de messages signĂ©s du client vers le serveur. Les certificats clients doivent ĂȘtre situĂ©s sur des jetons USB dans des conteneurs de clĂ©s privĂ©es et la vĂ©rification de la signature doit ĂȘtre effectuĂ©e sur le serveur Ă  l'aide d'OpenSSL.

Alors, la tùche: installation et configuration sur le serveur Linux de l'AC. Déployez des certificats clients qui identifient les ordinateurs sur des jetons USB .

Pour le résoudre, vous aurez besoin de:


  1. Nous crĂ©ons un rĂ©pertoire oĂč se trouvera l'autoritĂ© de certification et copions la configuration OpenSSL incluse avec le systĂšme (il y a /etc/ssl/openssl.cnf sur les derniĂšres versions d'Ubuntu)
  2. Nous configurons "notre" openssl.cnf:

    a) Ajoutez au début des directives de fichier pour connecter le moteur de jeton:

    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) décommenter la ligne

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

    c) dans la section [v3_req] , spécifiez les paramÚtres suivants:

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

    d) dans la section [v3_ca], supprimez l'option critique du paramĂštre basicConstraints:

     basicConstraints = CA:true 

    Pour quoi? RĂ©ponse honnĂȘte: je ne sais pas. Cependant, tous les exemples de certificats racine que j'ai tĂ©lĂ©chargĂ©s en essayant de comprendre le sujet Ă©taient sans signe critique. Je pose la question "pour quoi?" collĂšgues plus expĂ©rimentĂ©s.


    e) définir éventuellement les valeurs par défaut qui seront proposées lors de l'émission de certificats auto-signés et lors de la génération de demandes d'émission de certificats clients. Ces paramÚtres se trouvent dans la section [req_distinguished_name]

    Le paramÚtre avec le suffixe _default est la valeur par défaut. Un exemple:

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

    Lorsque le systÚme vous demande d'entrer le paramÚtre countryName , il indiquera entre crochets qu'il laissera la valeur AU par défaut.


    Ceci termine la configuration de la configuration OpenSSL. Il reste à indiquer à OpenSSL qu'il est nécessaire de l'utiliser. Pour ce faire, définissez la variable d'environnement OPENSSL_CONF:

     export OPENSSL_CONF=/path/to/your/openssl.cnf 
  3. Nous crĂ©ons une structure de rĂ©pertoires oĂč les informations sur notre autoritĂ© de certification seront stockĂ©es.
    Pour ce faire, accĂ©dez au rĂ©pertoire créé avec openssl.cnf qui vient d'ĂȘtre modifiĂ© et procĂ©dez comme suit:

    a) créez-y des sous-répertoires:

    demoCA
    demoCA / privé
    demoCA / newcerts

    Remarque: le nom demoCA est énoncé dans la section [CA_default] du fichier openssl.cnf . Vous pouvez le modifier (à l'étape 2), puis travailler avec lui au lieu de demoCA.

    b) dans le répertoire demoCA, créez un fichier index.txt vide et un fichier série , que nous ouvrons avec un éditeur de texte et y écrivons la ligne 01. C'est le compteur des certificats émis. AprÚs l'émission de chaque certificat suivant, la valeur de ce fichier augmente d'une unité.
  4. Nous pouvons Ă©ventuellement formater notre jeton Ă  l'aide de l'utilitaire rtAdmin. Maintenant, tout est prĂȘt pour le dĂ©ploiement de l'autoritĂ© de certification.

    L'algorithme d'action est globalement simple:

    a) nous émettons le certificat racine du centre de certification en utilisant l'algorithme GOST:

    • gĂ©nĂ©rer une clĂ© privĂ©e pour Ă©mettre un certificat CA auto-signĂ©
    • gĂ©nĂ©rer un certificat X509 auto-signĂ© Ă  l'aide de la clĂ© gĂ©nĂ©rĂ©e

    b) sur chacun des jetons USB

    • gĂ©nĂ©rer une paire de clĂ©s (le soi-disant conteneur de clĂ©s privĂ©es)
    • gĂ©nĂ©rer une demande de signature de certificat Ă  l'aide de la clĂ© de jeton gĂ©nĂ©rĂ©e
    • Ă©mettre un certificat pour cette demande
    • enregistrer le certificat sur le jeton dans le conteneur de clĂ© privĂ©e

    Voici une implémentation de cet algorithme pour un seul jeton:

    Génération de clé privée pour le certificat CA (nous utilisons l'algorithme GOST):

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

    Nous émettons un certificat CA auto-signé:

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

    Remarque: nous avons indiqué sur la ligne de commande qu'il est nécessaire d'utiliser les extensions v3_ca de la configuration openssl_cnf. C'est là que c'est notre CA. Validité de 10 ans. Une chose courante pour CA. Mais plus est possible.

    Dans le processus de délivrance d'un certificat, le systÚme vous demandera de saisir les valeurs des paramÚtres qui se trouvent dans la section [req_distinguished_name] de notre fichier openssl.cnf

    Nous commençons maintenant les opérations de jeton. Si le jeton est nouveau ou formaté avec des valeurs par défaut, le code PIN de l'utilisateur est 12345678. Je pars de l'hypothÚse que c'est exactement le cas. Sinon, vous devez spécifier le code PIN utilisateur correct et généralement essayer de vous assurer que dans les exemples ci-dessous, les noms des objets déjà existants sur le jeton ne chevauchent pas ceux saisis.

    Tout d'abord, nous allons générer une paire de clés. OpenSSL n'est pas en mesure d'effectuer cette opération sur Rutoken, nous allons donc utiliser l'utilitaire pkcs11-tool du package OpenSC:

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

    Remarque importante: nous avons spécifié l'ID 303030303031. Tous les deux chiffres de cet identifiant ne sont rien de plus que le code ASCII des caractÚres «0» et «1», respectivement. Pour les opérations avec OpenSSL, cela ressemblera à "id = 000001"

    Générez une demande de certificat:

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

    Si tout a été fait correctement, alors le systÚme

    • demander un code PIN
    • demandera des paramĂštres de nom de certificat (dans la section [req_distinguished_name] )
    • Ă©mettra un fichier de demande de signature de certificat

    À l'aide de cette demande, nous signons un certificat client ( dans l'exemple, le certificat est valable 1825 jours. Il est important que cette pĂ©riode ne dĂ©passe pas la pĂ©riode de validitĂ© de votre certificat racine ):

     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 

    Le systÚme affichera le certificat, posera des questions sur la décision de le signer (réponse «y») et sur la décision de sauvegarder le nouveau certificat (répondez à nouveau «y»).

    Nous enregistrons le certificat reçu pour le jeton:

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

    C’est tout.

    Tester le «miracle» créé. Pour ce faire, nous signons et vérifions la signature de la phrase "Bonjour tout le monde!":

     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 

    Si tout est fait correctement, le systÚme demandera un code PIN, signera le message, puis vérifiera la signature et, en cas de succÚs, affichera le message d'origine et le résultat de la vérification («succÚs»)

    Remarque . Revenant à la tùche de titre et signant à l'aide du plugin, il convient de noter que par défaut le plugin donne le résultat de la signature non pas au format PEM, mais au format DER, encodé en base64. Par conséquent, pour vérifier la signature, vous devez d'abord décoder à partir de base64, et lors de la vérification, spécifiez le format DER d'entrée.

    Bonne chance!

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


All Articles