Prise en charge des jetons PKCS # 11 avec la cryptographie GOST en Python. Partie III - L'enrubanneuse PyKCS11

imageIl est temps de vous dire comment la prise en charge de la cryptographie russe a été ajoutée au projet PyKCS11 . Tout a commencé lorsque je suis tombé sur une correspondance entre le développeur du projet PyKCS11 et des consommateurs potentiels sur le support possible des algorithmes GOST R 34.10-2012. Dans cette correspondance, l' auteur de PkCS11 a déclaré qu'il n'inclurait pas la prise en charge des cryptoalgorithmes russes tant qu'ils ne seraient pas normalisés.

Il m'a fait part de la même idée quand je lui ai demandé de le faire. Et pas seulement pour le faire, mais a envoyé le code de programme approprié:



image



Après cela, j'ai considéré qu'il était possible de charger le code dans mon référentiel et d'y apporter les modifications appropriées. Le projet PyKCS11 avec prise en charge de la cryptographie russe est ici .



I. Ajout de la prise en charge des algorithmes cryptographiques russes



Alors qu'est-ce qui a été fait. J'ai en fait suivi l'un des conseils de l'auteur du projet PyKCS11:

Ce que je peux vous proposer, c'est de créer un fichier PyKCS11_GOST.py avec les noms et fonctions constants que vous souhaitez afin d'étendre PyKCS11 avec le support GOST.

(Je pourrais vous suggérer de créer un fichier PyKCS11_GOST.py avec les noms des constantes et des fonctions que vous souhaitez étendre PyKCS11 pour prendre en charge GOST.)



Toutes les constantes approuvées par TC-26 pour PKCS # 11 ont été consolidées dans un fichier pkcs11t_gost.h, placé dans le dossier src:

//-26
#define NSSCK_VENDOR_PKCS11_RU_TEAM 0xd4321000 
#define NSSCK_VENDOR_PKSC11_RU_TEAM NSSCK_VENDOR_PKCS11_RU_TEAM
#define CK_VENDOR_PKCS11_RU_TEAM_TC26 NSSCK_VENDOR_PKCS11_RU_TEAM
#define CKK_GOSTR3410_512 	0xd4321003UL
#define CKK_KUZNYECHIK 		0xd4321004UL
#define CKK_MAGMA 		0xd4321005UL
#define CKK_GOSTR3410_256 	0xd4321006UL
#define CKP_PKCS5_PBKD2_HMAC_GOSTR3411_TC26_V1 	0xd4321801UL
#define CKP_PKCS5_PBKD2_HMAC_GOSTR3411_2012_256 0xd4321002UL
#define CKP_PKCS5_PBKD2_HMAC_GOSTR3411_2012_512 0xd4321003UL
#define CKM_GOSTR3410_512_KEY_PAIR_GEN		0xd4321005UL
#define CKM_GOSTR3410_512			0xd4321006UL
#define CKM_GOSTR3410_WITH_GOSTR3411		0x00001202
#define CKM_GOSTR3410_WITH_GOSTR3411_12_256	0xd4321008UL
#define CKM_GOSTR3410_WITH_GOSTR3411_12_512	0xd4321009UL
#define CKM_GOSTR3410_12_DERIVE			0xd4321007UL
#define CKM_GOSR3410_2012_VKO_256		0xd4321045UL
#define CKM_GOSR3410_2012_VKO_512		0xd4321046UL
#define CKM_KDF_4357				0xd4321025UL
#define CKM_KDF_GOSTR3411_2012_256		0xd4321026UL
#define CKM_KDF_TREE_GOSTR3411_2012_256		0xd4321044UL
#define CKM_GOSTR3410_PUBLIC_KEY_DERIVE		0xd432100AUL
#define CKM_LISSI_GOSTR3410_PUBLIC_KEY_DERIVE	0xd4321037UL
#define CKM_GOST_GENERIC_SECRET_KEY_GEN		0xd4321049UL
#define CKM_GOST_CIPHER_KEY_GEN			0xd4321048UL
#define CKM_GOST_CIPHER_ECB			0xd4321050UL
#define CKM_GOST_CIPHER_CBC			0xd4321051UL
#define CKM_GOST_CIPHER_CTR			0xd4321052UL
#define CKM_GOST_CIPHER_OFB			0xd4321053UL
#define CKM_GOST_CIPHER_CFB			0xd4321054UL
#define CKM_GOST_CIPHER_OMAC			0xd4321055UL
#define CKM_GOST_CIPHER_KEY_WRAP		0xd4321059UL
#define CKM_GOST_CIPHER_ACPKM_CTR		0xd4321057UL
#define CKM_GOST_CIPHER_ACPKM_OMAC		0xd4321058UL
#define CKM_GOST28147_PKCS8_KEY_WRAP		0xd4321036UL
#define CKM_GOST_CIPHER_PKCS8_KEY_WRAP		0xd432105AUL
#define CKM_GOST28147_CNT			0xd4321825UL
#define CKM_KUZNYECHIK_KEY_GEN			0xd4321019UL
#define CKM_KUZNYECHIK_ECB			0xd432101AUL
#define CKM_KUZNYECHIK_CBC			0xd432101EUL
#define CKM_KUZNYECHIK_CTR			0xd432101BUL
#define CKM_KUZNYECHIK_OFB			0xd432101DUL
#define CKM_KUZNYECHIK_CFB			0xd432101CUL
#define CKM_KUZNYECHIK_OMAC			0xd432101FUL
#define CKM_KUZNYECHIK_KEY_WRAP			0xd4321028UL
#define CKM_KUZNYECHIK_ACPKM_CTR		0xd4321042UL
#define CKM_KUZNYECHIK_ACPKM_OMAC		0xd4321043UL
#define CKM_MAGMA_KEY_GEN			0xd432102AUL
#define CKM_MAGMA_ECB				0xd4321018UL
#define CKM_MAGMA_CBC				0xd4321023UL
#define CKM_MAGMA_CTR				0xd4321020UL
#define CKM_MAGMA_OFB				0xd4321022UL
#define CKM_MAGMA_CFB				0xd4321021UL
#define CKM_MAGMA_OMAC				0xd4321024UL
#define CKM_MAGMA_KEY_WRAP			0xd4321029UL
#define CKM_MAGMA_ACPKM_CTR			0xd4321040UL
#define CKM_MAGMA_ACPKM_OMAC			0xd4321041UL
#define CKM_GOSTR3411_12_256			0xd4321012UL
#define CKM_GOSTR3411_12_512			0xd4321013UL
#define CKM_GOSTR3411_12_256_HMAC		0xd4321014UL
#define CKM_GOSTR3411_12_512_HMAC		0xd4321015UL
#define CKM_PBA_GOSTR3411_WITH_GOSTR3411_HMAC	0xd4321035UL
#define CKM_TLS_GOST_KEY_AND_MAC_DERIVE		0xd4321033UL
#define CKM_TLS_GOST_PRE_MASTER_KEY_GEN		0xd4321031UL
#define CKM_TLS_GOST_MASTER_KEY_DERIVE		0xd4321032UL
#define CKM_TLS_GOST_PRF			0xd4321030UL
#define CKM_TLS_GOST_PRF_2012_256		0xd4321016UL
#define CKM_TLS_GOST_PRF_2012_512		0xd4321017UL
#define CKM_TLS_TREE_GOSTR3411_2012_256		0xd4321047UL
      
      





Cette liste comprend les mécanismes nécessaires à la fois à la formation et à la vérification des signatures conformément à (GOST R 34.10-2012) GOST R 34.10-2012, et au cryptage (GOST R 34.12-2015 et GOST R 34.13-2015 - algorithmes de cryptage Grasshopper et Magma) . Naturellement, les algorithmes de hachage GOST R 34.11-2012 sont également présents ici.

Pour que les constantes GOST soient incluses dans le processus de construction du module, il est nécessaire d'ajouter une instruction include au fichier pkcs11t_gost.h au fichier pkcs11.i (fichier pour SWIG)

%include "pkcs11t_gost.h"
      
      





devant l'opérateur

%include "pkcs11lib.h"
      
      





Mais ce n'est pas tout. Dans la méthode getMechanismList (script PKCS11 / __ init__.py), la sortie des mécanismes dont le code est supérieur à CKM_VENDOR_DEFINED est bloquée (c'est exactement ce sur quoi l'auteur du projet PyKCS11 écrit) (0x80000000L). Notez que les constantes GOST pour les nouveaux algorithmes relèvent de cette restriction. Il est nécessaire de le supprimer au moins pour les GOST, nous allons donc remplacer le code de la méthode getMechanismList par un nouveau:

    def getMechanismList(self, slot):
        """
        C_GetMechanismList

        :param slot: slot number returned by :func:`getSlotList`
        :type slot: integer
        :return: the list of available mechanisms for a slot
        :rtype: list
        """
        mechanismList = PyKCS11.LowLevel.ckintlist()
        rv = self.lib.C_GetMechanismList(slot, mechanismList)
        if rv != CKR_OK:
            raise PyKCS11Error(rv)
        m = []
#  
#define NSSCK_VENDOR_PKCS11_RU_TEAM 0xd4321000 
        for x in range(len(mechanismList)):
            mechanism = mechanismList[x]
            if mechanism >= CKM_VENDOR_DEFINED:
                if mechanism >= CKM_VENDOR_DEFINED and mechanism < 0xd4321000:
                    k = 'CKM_VENDOR_DEFINED_0x%X' % (mechanism - CKM_VENDOR_DEFINED)
                    CKM[k] = mechanism
                    CKM[mechanism] = k
            m.append(CKM[mechanism])
        return m
#ORIGINAL
#        for x in range(len(mechanismList)):
#            mechanism = mechanismList[x]
#            if mechanism >= CKM_VENDOR_DEFINED:
#                k = 'CKM_VENDOR_DEFINED_0x%X' % (mechanism - CKM_VENDOR_DEFINED)
#                CKM[k] = mechanism
#                CKM[mechanism] = k
#            m.append(CKM[mechanism])
#        return m
      
      







Notez également que bien que le module inclue tous les mécanismes définis dans les fichiers d'inclusion pkcs11t.h et pkcs11t_gost.h pour pkcs11 v.2.40, tous ces mécanismes ne peuvent pas être implémentés. Le problème est que certains d'entre eux nécessitent une structure de paramètres spécifique. Ceci s'applique en particulier au mécanisme CKM_RSA_PKCS_OAEP, qui nécessite des paramètres sous la forme d'une structure CK_RSA_PKCS_OAEP_PARAMS, et au mécanisme CKM_PKCS5_PBKD2, qui attend des paramètres sous la forme d'une structure CK_PKCS5_PBKD2_PARAMS. Il existe également d'autres mécanismes. Mais puisque l'auteur a implémenté des structures séparées pour des mécanismes séparés (pour le même CKM_RSA_PKCS_OAEP), il ne sera pas difficile d'implémenter le support des structures de paramètres pour d'autres mécanismes. Donc, si quelqu'un a besoin de travailler avec un conteneur PKCS # 12,alors vous devrez implémenter la prise en charge de la structure CK_PKCS5_PBKD2_PARAMS.

Tout cela renvoie à des mécanismes cryptographiques assez complexes.

Mais tout ce qui concerne le hachage, la formation de la vérification d'une signature électronique et enfin le cryptage, tout fonctionne à merveille. Mais vous devez d'abord monter un projet.



II. Construire un wrapper PyKCS11 avec le support GOST



Ce n'est pas différent de la construction du wrapper PkCS11 natif, sauf que vous devez obtenir le code source ici .

Ensuite, suivez les instructions pour créer et installer le package PyKCS11.

Les tests nécessitent un jeton avec prise en charge de la cryptographie russe. Nous entendons ici GOST R 34.10-2012 et GOST R 34.11-2012. Il peut s'agir d'un jeton matériel, par exemple RuTokenECP-2.0, ou d'un jeton logiciel ou cloud.

Vous pouvez installer un jeton logiciel ou accéder à un jeton cloud à l'aide de l'utilitaire cryptoarmpkcs.

Vous pouvez télécharger l'utilitaire cryptoarmpkcs ici.
  • Linux32
  • Linux64
  • OS X
  • WIN32
  • WIN64




Après avoir démarré l'utilitaire, vous devez aller dans l'



image



onglet "Créer des jetons": Sur l'onglet, vous pouvez trouver des instructions pour obtenir et installer des jetons.



III. Test des algorithmes russes



Pour les tests, vous pouvez utiliser les scripts qui se trouvent dans le dossier testGost:

  • ckm_kuznyechik_cbc.py
  • ckm_gostr3411_12_256.py
  • ckm_gostr3410_with_gostr3411_12_256.py
  • ckm_gostr3410_512.py


Pour les tests, les données initiales ont été tirées à la fois des GOST correspondants et des recommandations du TK-26.

Les mécanismes suivants sont testés dans ces scripts:

1. Génération de paires de clés:

  • CKM_GOSTR3410_512_KEY_PAIR_GEN (GOST R 34.10-2012 avec une longueur de clé de 1024 bits)
  • CKM_GOSTR3410_KEY_PAIR_GEN (GOST R 34.10-2012 avec une longueur de clé de 512 bits)


2. Formation et vérification d'une signature électronique:

  • CKM_GOSTR3410
  • CKM_GOSTR3410_512
  • CKM_GOSTR3410_WITH_GOSTR3411_12_256


3. Hashing:

  • CKM_GOSTR3411_12_256


4. Cryptage / décryptage

  • CKM_KUZNYECHIK_CBC




La génération de paires de clés permet au détenteur du jeton d'obtenir une clé privée avec laquelle il peut signer, par exemple, une demande de certificat. Une demande de certificat peut être envoyée à un centre de certification et un certificat peut y être émis. Le propriétaire du certificat peut l'importer dans le jeton où la clé privée est stockée. Le propriétaire du jeton dispose désormais d'un certificat personnel avec une clé privée qu'il peut utiliser pour signer des documents.

Eh bien, s'il a besoin d'un mode de sécurité spécial, il peut crypter le document en utilisant l'un des algorithmes, à savoir Magma ou Grasshopper. Tout cela, bien sûr, si le jeton lui-même prend en charge ces mécanismes, le package PyKCS11 n'est qu'un intermédiaire.

Ceci conclut notre histoire liée à la prise en charge des jetons avec la cryptographie russe en Python.



All Articles