Prise en charge des jetons PKCS # 11 avec la cryptographie GOST en Python. Partie II - Objets de la classe Token

imageDans l' article précédent , le module pyp11 a été présenté, écrit en C et prenant en charge les jetons PKCS # 11 avec la cryptographie russe. Cet article examinera la classe Token, ce qui simplifiera l'utilisation des fonctionnalités du module pyp11 dans les scripts écrits en Python. Notez que la classe token, écrite en TclOO et utilisée dans l'utilitaire cryptoarmpkcs , a été prise comme un prototype de cette classe :







Prototype de classe de jeton
oo::class create token {
  variable libp11
  variable handle
  variable infotok
  variable pintok
  variable nodet
#
  constructor {handlelp11 labtoken slottoken} {
    global pass
    global yespas
    set handle $handlelp11
    set slots [pki::pkcs11::listslots $handle]
    array set infotok []
    foreach slotinfo $slots {
      set slotflags [lindex $slotinfo 2]
      if {[lsearch -exact $slotflags TOKEN_PRESENT] != -1} {
        if {[string first $labtoken [lindex $slotinfo 1]] != -1} {
          set infotok(slotlabel) [lindex $slotinfo 1]
          set infotok(slotid) [lindex $slotinfo 0]
          set infotok(slotflags) [lindex $slotinfo 2]
          set infotok(token) [lindex $slotinfo 3]
          #  
          break
        }
      }
    }
    #    
    if {[llength [array names infotok]] == 0 } {
      error "Constructor: Token not present for library   : $handle"
    }
    #  
    set nodet [dict create pkcs11_handle $handle]
    dict set nodet pkcs11_slotid $infotok(slotid)
    set tit " PIN-   $infotok(slotlabel)"
    set xa [my read_password $tit]
    if {$xa == "no"} {
      error "   PIN   $infotok(slotlabel)"
    }
    set pintok $pass
    set pass ""
    set rr [my login ]
    if { $rr == 0 } {
      unset pintok
      error " PIN-  $infotok(slotlabel)."
    } elseif {$rr == -1} {
      unset pintok
      error " ."
    }
    my logout
  }
# 
  method infoslot {} {
    return [array get infotok]
  }
  method listcerts {} {
    array set lcerts []
    set certsder [pki::pkcs11::listcertsder $handle $infotok(slotid)]
    # 
    foreach lc $certsder {
      array set derc $lc
      set lcerts($derc(pkcs11_label)) [list $derc(cert_der) $derc(pkcs11_id)]
      #parray derc
    }
    return [array get lcerts]
  }
  method read_password {tit} {
    global yespas
    global pass
    set tit_orig "$::labpas"
    if {$tit != ""} {
      set ::labpas "$tit"
    }
    tk busy hold ".st.fr1"
    tk busy hold ".st.fr3"
    #	place .topPinPw -in .st.fr1.fr2_certs.labCert  -relx 1.0 -rely 3.0 -relwidth 3.5
    place .topPinPw -in .st.labMain  -relx 0.35 -rely 5.0 -relwidth 0.30
    set yespas ""
    focus .topPinPw.labFrPw.entryPw
    vwait yespas
    catch {tk busy forget ".st.fr1"}
    catch {tk busy forget ".st.fr3"}
    if {$tit != ""} {
      set ::labpas "$tit_orig"
    }
    place forget .topPinPw
    return $yespas
  }
  unexport read_password
  method rename {type ckaid newlab} {
    if {$type != "cert" && $type != "key" && $type != "all"} {
      error "Bad type for rename "
    }
    set uu $nodet
    lappend uu "pkcs11_id"
    lappend uu $ckaid
    lappend uu "pkcs11_label"
    lappend uu $newlab
    if { [my login ] == 0 } {
      unset uu
      return 0
    }
    pki::pkcs11::rename $type $uu
    my logout
    return 1
  }
  method changeid {type ckaid newid} {
    if {$type != "cert" && $type != "key" && $type != "all"} {
      error "Bad type for changeid "
    }
    set uu $nodet
    lappend uu "pkcs11_id"
    lappend uu $ckaid
    lappend uu "pkcs11_id_new"
    lappend uu $newid
    if { [my login ] == 0 } {
      unset uu
      return 0
    }
    pki::pkcs11::rename $type $uu
    my logout
    return 1
  }
  method delete {type ckaid} {
    if {$type != "cert" && $type != "key" && $type != "all" && $type != "obj"} {
      error "Bad type for delete"
    }
    set uu $nodet
    lappend uu "pkcs11_id"
    lappend uu $ckaid
    my login
    ::pki::pkcs11::delete $type $uu
    my logout
    return 1
  }
  method deleteobj {hobj} {
    set uu $nodet
    lappend uu "hobj"
    lappend uu $hobj
#tk_messageBox -title "class deleteobj" -icon info -message "hobj: $hobj\n" -detail "$uu"
    return [::pki::pkcs11::delete obj $uu ]
  }
  method listmechs {} {
    set llmech [pki::pkcs11::listmechs $handle $infotok(slotid)]
    return $llmech
  }
  method pubkeyinfo {cert_der_hex} {
    array set linfopk [pki::pkcs11::pubkeyinfo $cert_der_hex $nodet]
    return [array get linfopk]
  }
  method listobjects {type} {
    if {$type != "cert" && $type != "pubkey" && $type != "privkey" && $type != "all" && $type != "data"} {
      error "Bad type for listobjects "
    }
    set allobjs [::pki::pkcs11::listobjects $handle $infotok(slotid) $type]
    return $allobjs
  }
  method importcert {cert_der_hex cka_label} {
    set uu $nodet
    dict set uu pkcs11_label $cka_label
    if {[catch {set pkcs11id [pki::pkcs11::importcert $cert_der_hex $uu]} res] } {
      error "Cannot import this certificate:$res"
      #          return 0
    }
    return $pkcs11id
  }
  method login {} {
    set wh 1
    set rl -1
    while {$wh == 1} {
      if {[catch {set rl [pki::pkcs11::login $handle $infotok(slotid) $pintok]} res]} {
        if {[string first "SESSION_HANDLE_INVALID" $res] != -1} {
          pki::pkcs11::closesession $handle
          continue
        } elseif {[string first "TOKEN_NOT_PRESENT" $res] != -1} {
          set wh 0
          continue
        }
      }
      break
    }
    if {$wh == 0} {
      return -1
    }
    return $rl
  }
  method logout {} {
    return [pki::pkcs11::logout $handle $infotok(slotid)]
  }
  method keypair {typegost parkey} {
    my login
    set skey [pki::pkcs11::keypair $typegost $parkey $nodet]
    my logout
    return $skey
  }
  method digest {typehash source} {
    return [pki::pkcs11::digest $typehash $source $nodet]
  }
  method signkey {ckm digest hobj_priv} {
    set uu $nodet
    dict set uu hobj_privkey $hobj_priv
    my login
    set ss [pki::pkcs11::sign $ckm $digest $uu]
    my logout
    return $ss
  }
  method signcert {ckm digest pkcs11_id} {
    set uu $nodet
    dict set uu pkcs11_id $pkcs11_id
    my login
    set ss  [pki::pkcs11::sign $ckm $digest $uu]
    my logout
    return $ss
  }
  method verify {digest signature asn1pubkey} {
    set uu $nodet
    dict set uu pubkeyinfo $asn1pubkey
    return [pki::pkcs11::verify $digest $signature $uu]
  }
  method tokenpresent {} {
    set slots [pki::pkcs11::listslots $handle]
    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} {
        if {infotok(slotlabel) == $slotlabel && $slotid == $infotok(slotid)} {
          return 1
        }
      }
    }
    return 0
  }
  method setpin {type tpin newpin} {
    if {$type != "user" && $type != "so"} {
      return 0
    }
    if {$type == "user"} {
      if {$tpin != $pintok} {
        return 0
      }
    }
    set ret [::pki::pkcs11::setpin  $handle $infotok(slotid) $type $tpin $newpin]
    if {$type == "user"} {
      if {$ret} {
        set pitok $newpin
      }
    }
    return $ret
  }
  method inituserpin {sopin upin} {
    set ret [::pki::pkcs11::inituserpin $handle $infotok(slotid) $sopin $upin]
    return $ret
  }
  method importkey {uukey} {
    set uu $nodet
    append uu " $uukey"
    my login
    if {[catch {set impkey [pki::pkcs11::importkey $uu ]} res] } {
        set impkey 0
    }
    my logout
    return $impkey
  }
#
  destructor {
    variable handle
    if {[info exists pintok]} {
      my login
    }
    #	    ::pki::pkcs11::unloadmodule  $handle
  }
}
      
      







La classe Token, comme toute classe en Python , comprend un constructeur, des méthodes et un destructeur. Le constructeur et le destructeur sont les mêmes méthodes, uniquement avec des noms prédéfinis. Le constructeur est nommé __init__ et le destructeur est nommé __del__. Les déclarations de constructeur et de destructeur peuvent être omises. Et dans la classe Token, nous omettons la déclaration du destructeur, mais le constructeur sera nécessaire. Le constructeur instanciera la classe Token pour un jeton spécifique avec des attributs spécifiques.



Constructeur de classe de jetons



Ainsi, le constructeur de la classe Token ressemble à ceci:



import sys
import pyp11
class Token:
  def __init__ (self, handlelp11, slottoken, serialnum):
    flags = ''
    self.pyver = sys.version[0]
    if (self.pyver == '2'):
        print ('  python3')
        quit()
# handle  PKCS#11
    self.handle = handlelp11
#    
    self.slotid = slottoken
#   
    self.sn = serialnum
#         
    ret, stat = self.tokinfo()
#  
    if (stat != ''):
#   
        self.returncode = stat
        return
#  ()  
      
      





Les paramètres du constructeur (de la méthode __init__) sont (en plus du self obligatoire) le handle de la bibliothèque de jetons (handlelp11), le numéro d'emplacement (slottoken) dans lequel le jeton doit être situé, et le numéro de série du jeton ( numéro de série).



Pour obtenir le descripteur de la bibliothèque pkcs # 11, les numéros d'emplacement et les informations sur les jetons qu'ils contiennent, vous pouvez utiliser le script suivant:



#!/usr/bin/python3
import sys
import pyp11
from Token import Token
def listslots (handle):
    slots = pyp11.listslots(aa)
    i = 0
    lslots = []
    for v in slots:
        for f in v[2]:
    	    if (f == 'TOKEN_PRESENT'):
                i = 1
                lslots.append(v)
                break
    i += 1
    return (lslots)
#  Linux
# 
lib = '/usr/local/lib64/libls11sw2016.so'
# 
#lib = '/usr/local/lib64/libls11cloud.so'
# 
#lib = '/usr/local/lib64/librtpkcs11ecp_2.0.so'
#  Windows
#lib='C:\Temp\ls11sw2016.dll'
try:
#       handle ( )
    aa = pyp11.loadmodule(lib)
    print('Handle  ' + lib + ': ' + aa)
except:
    print('Except load lib: ')
    e = sys.exc_info()[1]
    e1 = e.args[0]
# 
    print (e1)
    quit()
# 
slots = listslots(aa)
i = 0
for v in slots:
    for f in v[2]:
        if (f == 'TOKEN_PRESENT'):
    	    if (i == 0):
    	        print ('\n    \n')
    	    it = v[3]
    	    print ('slotid=' + str(v[0]))
    	    print ('\tFlags=' + str(v[2]))
    	    print ('\tLabel="' + it[0].strip() + '"')
    	    print ('\tManufacturer="' + it[1].strip() + '"')
    	    print ('\tModel="' + it[2].strip() + '"')
    	    print ('\tSerialNumber="' + it[3].strip() + '"')
    	    i = 1
    	    break
    i += 1
pyp11.unloadmodule(aa)
if (i == 0):
    print ('    .     ')
quit()
      
      





Si tout est clair avec la bibliothèque et l'emplacement, la question peut se poser avec le numéro de série du jeton - pourquoi ce paramètre est nécessaire et pourquoi exactement, mais, par exemple, pas l'étiquette du jeton. Faisons une réservation tout de suite indiquant que c'est fondamental pour les jetons récupérables, lorsqu'un attaquant remplace (ou accidentellement) un jeton dans l'emplacement par un autre jeton. De plus, différentes instances du jeton peuvent avoir les mêmes étiquettes. Et enfin, le jeton n'a peut-être pas encore été initialisé ou le propriétaire le réinitialisera, en particulier, changera l'étiquette du jeton. En théorie, même un numéro de série ne garantit pas son identité; il est optimal de prendre en compte toutes les informations sur un token (numéro de série, modèle, fabricant). C'est la tâche du constructeur de stocker les arguments du jeton dans les variables de l'instance créée de la classe:



...
# handle  PKCS#11
    self.handle = handlelp11
#    
    self.slotid = slottoken
#   
    self.sn = serialnum
...
      
      





La méthode tokinfo () définie dans cette classe vérifie la présence du jeton spécifié dans l'emplacement spécifié .



La méthode tokinfo renvoie deux valeurs (voir ci-dessus dans le constructeur):



#         
    ret, stat = self.tokinfo()
      
      





La première variable (ret) contient le résultat de l'exécution de la méthode et la seconde (stat) contient des informations sur la fin de l'exécution de la méthode. Si la deuxième variable est vide, la méthode tokinfo a réussi. Si la deuxième variable n'est pas vide, la méthode s'est terminée par une erreur. Les informations d'erreur seront dans cette variable. Lorsqu'une erreur est rencontrée lors de l'exécution de la méthode self.tokinfo, le constructeur l'écrit dans la variable returncode:



#         
    ret, stat = self.tokinfo()
#  
    if (stat != ''):
#      returncode
        self.returncode = stat
        return
      
      





Après avoir créé un objet (instance de classe), vous devez vérifier la valeur de la variable returncode pour vous assurer que l'objet pour le jeton spécifié a été créé:



#!/usr/bin/python3
import sys
import pyp11
from Token import Token
# 
# 
lib = '/usr/local/lib64/librtpkcs11ecp_2.0.so'
try:
    aa = pyp11.loadmodule(lib)
except:
    e = sys.exc_info()[1]
    e1 = e.args[0]
    print (e1)
    quit()
#  
sn = '9999999999999999'
slot = 110
#  
t1 = Token(aa, slot, sn)
#  returncode
if (t1.returncode != ''):
#   
    print (t1.returncode)
# 
    del t1
# 
    quit()
#  
. . .
      
      





Si une erreur est détectée lors de la création d'un objet, il est conseillé de détruire cet objet:



del < >
      
      





II. Architecture de méthode dans la classe Token



Le principe principal lors de l'écriture de méthodes était que la gestion des exceptions était à l'intérieur des méthodes et que les informations sur les exceptions (erreurs) étaient renvoyées sous forme de texte. Sur cette base, toutes les méthodes renvoient deux valeurs: le résultat réel de l'exécution et des informations sur l'erreur. S'il n'y a pas d'erreur, la deuxième valeur est vide. Nous l'avons déjà vu en utilisant la méthode tokinfo dans le constructeur. Et voici le code de la méthode tokinfo elle-même:



  def tokinfo(self):
    status = ''
#  
    try:
        slots = pyp11.listslots(self.handle)
    except:
#   
        e = sys.exc_info()[1]
        e1 = e.args[0]
        dd = ''
        status = e1
        return (dd, status)
    status = ''
#      
# 
    for v in slots:
#  
            if (v[0] != self.slotid):
                status = " "
                continue
            self.returncode = ''
#   
            self.flags = v[2]
#    
            if (self.flags.count('TOKEN_PRESENT') !=0):
#   
                tokinf = v[3]
                sn = tokinf[3].strip()
                if (self.sn != sn):
                    status = '  =\"' + sn + '\"     \"' + self.sn + '\"'
                    dd = ''
                    return (dd, status)
                status = ''
                break
            else:
                dd = ''
                status = "   "
                return (dd, status)
    tt = tokinf
    dd = dict(Label=tt[0].strip())
    dd.update(Manufacturer=tt[1].strip())
    dd.update(Model=tt[2].strip())
    dd.update(SerialNumber=tt[3].strip())
    self.infotok = dd
# 
    return (dd, status)
      
      





Une description complète de la classe Token peut être trouvée ici.
import sys
import pyp11
class Token:
  def __init__ (self, handlelp11, slottoken, serialnum):
    flags = ''
    self.pyver = sys.version[0]
    if (self.pyver == '2'):
        print ('  python3')
        quit()
# handle  PKCS#11
    self.handle = handlelp11
#    
    self.slotid = slottoken
#   
    self.sn = serialnum
#          
    ret, stat = self.tokinfo()
#  
    if (stat != ''):
#   
        self.returncode = stat
        return
#  ()  
  def tokinfo(self):
    status = ''
#  
    try:
        slots = pyp11.listslots(self.handle)
    except:
#   
        e = sys.exc_info()[1]
        e1 = e.args[0]
        dd = ''
        status = e1
        return (dd, status)
    status = ''
#      
# 
    for v in slots:
#  
            if (v[0] != self.slotid):
                status = " "
                continue
            self.returncode = ''
#   
            self.flags = v[2]
#    
            if (self.flags.count('TOKEN_PRESENT') !=0):
#   
                tokinf = v[3]
                sn = tokinf[3].strip()
                if (self.sn != sn):
                    status = '  =\"' + sn + '\"     \"' + self.sn + '\"'
                    dd = ''
                    return (dd, status)
                status = ''
                break
            else:
                dd = ''
                status = "   "
                return (dd, status)
    tt = tokinf
    dd = dict(Label=tt[0].strip())
    dd.update(Manufacturer=tt[1].strip())
    dd.update(Model=tt[2].strip())
    dd.update(SerialNumber=tt[3].strip())
    self.infotok = dd
    return (dd, status)
  def listcerts(self):
    try:
        status = ''
        lcerts = pyp11.listcerts(self.handle, self.slotid)
    except:
#   
        e = sys.exc_info()[1]
        e1 = e.args[0]
        lcerts = ''
        status = e1
    return (lcerts, status)
  def listobjects(self, type1, value = '' ):
    try:
        status = ''
        if (value == ''):
    	    lobjs = pyp11.listobjects(self.handle, self.slotid, type1)
        else:
    	    lobjs = pyp11.listobjects(self.handle, self.slotid, type1, value)
    except:
#   
        e = sys.exc_info()[1]
        e1 = e.args[0]
        lobjs = ''
        status = e1
    return (lobjs, status)
  def rename(self, type, pkcs11id, label):
    try:
        status = ''
        dd = dict(pkcs11_id=pkcs11id, pkcs11_label=label)
        ret = pyp11.rename(self.handle, self.slotid, type, dd)
    except:
#   
        e = sys.exc_info()[1]
        e1 = e.args[0]
        ret = ''
        status = e1
    return (ret, status)
  def changeckaid(self, type, pkcs11id, pkcs11idnew):
    try:
        status = ''
        dd = dict(pkcs11_id=pkcs11id, pkcs11_id_new=pkcs11idnew)
        ret = pyp11.rename(self.handle, self.slotid, type, dd)
    except:
#   
        e = sys.exc_info()[1]
        e1 = e.args[0]
        ret = ''
        status = e1
    return (ret, status)
  def login(self, userpin):
    try:
        status = ''
        bb = pyp11.login (self.handle, self.slotid, userpin)
    except:
        e = sys.exc_info()[1]
        e1 = e.args[0]
        bb = 0
        status = e1
    return (bb, status)
  def logout(self):
    try:
        status = ''
        bb = pyp11.logout (self.handle, self.slotid)
    except:
        e = sys.exc_info()[1]
        e1 = e.args[0]
        bb = 0
        status = e1
    return (bb, status)
  def keypair(self, typek, paramk, labkey):
#  
    gost2012_512 = ['1.2.643.7.1.2.1.2.1', '1.2.643.7.1.2.1.2.2', '1.2.643.7.1.2.1.2.3']
    gost2012_256 = ['1.2.643.2.2.35.1', '1.2.643.2.2.35.2',  '1.2.643.2.2.35.3',  '1.2.643.2.2.36.0', '1.2.643.2.2.36.1', '1.2.643.7.1.2.1.1.1', '1.2.643.7.1.2.1.1.2', '1.2.643.7.1.2.1.1.3', '1.2.643.7.1.2.1.1.4']
    gost2001 = ['1.2.643.2.2.35.1', '1.2.643.2.2.35.2',  '1.2.643.2.2.35.3',  '1.2.643.2.2.36.0', '1.2.643.2.2.36.1']
# 
    typekey = ['g12_256', 'g12_512', 'gost2001']
    genkey = ''
    if (typek == typekey[0]):
    	gost = gost2012_256
    elif (typek == typekey[1]):
    	gost = gost2012_512
    elif (typek == typekey[2]):
    	gost = gost2001
    else:
    	status = '  '
    	return (genkey, status)
    if (gost.count(paramk) == 0) :
    	status = '  '
    	return (genkey, status)
    try:
# ,   
    	status = ''
    	genkey = pyp11.keypair(self.handle, self.slotid, typek, paramk, labkey)
    except:
#    
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
    	print (e1)
#    
    	status = e1
    return (genkey, status)   
  def digest(self, typehash, source):
# 
    try:
        status = ''
        digest_hex = pyp11.digest (self.handle, self.slotid, typehash, source)
    except:
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    
    	status = e1
    	digest_hex = ''
    return (digest_hex, status)
# 
  def sign(self, ckmpair, digest_hex, idorhandle):
#    CKA_ID  handle  
    try:
        status = ''
        sign_hex = pyp11.sign(self.handle, self.slotid, ckmpair, digest_hex, idorhandle)
    except:
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    
    	status = e1
    	sign_hex = ''
    return (sign_hex, status)
# 
  def verify(self, digest_hex, sign_hex, pubkeyinfo):
#    CKA_ID  handle  
    try:
        status = ''
        verify = pyp11.verify(self.handle, self.slotid, digest_hex, sign_hex, pubkeyinfo)
    except:
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    status
    	verify = 0
    	status = e1
    return (verify, status)
# 
  def inittoken(self, sopin, labtoken):
    try:
        status = ''
        dd = pyp11.inittoken (self.handle, self.slotid, sopin, labtoken)
    except:
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    status
    	dd = 0
    	status = e1
    return (dd, status)
#  PIN-
  def inituserpin(self, sopin, userpin):
    try:
        status = ''
        dd = pyp11.inituserpin (self.handle, self.slotid, sopin, userpin)
    except:
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    status
    	dd = 0
    	status = e1
    return (dd, status)
#  PIN-
  def changeuserpin(self, oldpin, newpin):
    try:
        status = ''
        dd = pyp11.setpin (self.handle, self.slotid, 'user', oldpin, newpin)
    except:
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    status
    	dd = 0
    	status = e1
    self.closesession ()
    return (dd, status)
  def closesession(self):
    try:
        status = ''
        dd = pyp11.closesession (self.handle)
    except:
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    status
    	dd = 0
    	status = e1
    return (dd, status)
  def parsecert(self, cert_der_hex):
    try:
        status = ''
        dd = pyp11.parsecert (self.handle, self.slotid, cert_der_hex)
    except:
#   
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    status
    	dd = ''
    	status = e1
    return (dd, status)
  def importcert(self, cert_der_hex, labcert):
    try:
        status = ''
        dd = pyp11.importcert (self.handle, self.slotid, cert_der_hex, labcert)
    except:
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    status
    	dd = ''
    	status = e1
    return (dd, status)
  def delobject(self, hobject):
    try:
        status = ''
        hobjc = dict(hobj=hobject)
        dd = pyp11.delete(self.handle, self.slotid, 'obj', hobjc)
    except:
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    status
    	dd = ''
    	status = e1
    return (dd, status)
  def delete(self, type, pkcs11id):
    if (type == 'obj'):
        dd = ''
        status = 'delete for type obj use nethod delobject'
        return (dd, status)
    try:
        status = ''
        idobj = dict(pkcs11_id=pkcs11id)
        dd = pyp11.delete(self.handle, self.slotid, type, idobj)
    except:
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    status
    	dd = ''
    	status = e1
    return (dd, status)
  def listmechs(self):
    try:
        status = ''
        dd = pyp11.listmechs (self.handle, self.slotid)
    except:
#     
    	e = sys.exc_info()[1]
    	e1 = e.args[0]
#    status
    	dd = ''
    	status = e1
    return (dd, status)

      
      







Considérons l'utilisation de la fonctionnalité du module pyp11 et d'opérateurs similaires utilisant la classe Token.

Dans ce dernier cas, il sera également nécessaire de créer l'objet token:



< > = Token(< >, < >, < >)
if (< >.returncode != ''):
   print('   :')
# 
   print(< >.returncode)
# 
   del < >
   quit()
      
      





Commençons par initialiser le token:



try:
    ret = pyp11.inittoken (< >, < >, <SO-PIN>, < >)
except:
#   
    e = sys.exc_info()[1]
    e1 = e.args[0]
    print (e1)
    quit()
      
      





Le code similaire lors de l'utilisation de la classe Token ressemble à ceci (identificateur d'objet t1):



ret, stat = t1.inittoken(<SO-PIN>, < >)
#  
if (stat != ''):
   print('   :')
# 
   print(stat)
   quit()  
      
      





Ensuite, nous donnerons simplement la correspondance entre les principaux opérateurs du module pyp11 et les méthodes de la classe Token sans gérer les exceptions et les erreurs:



<handle> := <  pkcs11>
<slot> := <   >
<error> := <   >
<ret> := <  >
<cert_der_hex> := <  DER-  HEX->
=================================================
#  PIN-
<ret> = pyp11.inituserpin (<handle>, <slot>, <SO-PIN>, <USER-PIN>)
<ret>, <error> = < >.inituserpin (<SO-PIN>, <USER-PIN>)
# USER-PIN 
<ret> = pyp11.setpin (<handle>, <slot>, 'user', <USER-PIN >, <USER-PIN >)
<ret>, <error> = t1.changeuserpin (<USER-PIN >, <USER-PIN >)
# SO-PIN 
<ret> = pyp11.setpin (<handle>, <slot>, 'so', <SO-PIN >, <SO-PIN >)
<ret>, <error> = t1.changesopin (<SO-PIN >, <SO-PIN >)
#Login
<ret> = pyp11.login (<handle>, <slot>, <USER-PIN>)
<ret>, <error> = t1.login (<USER-PIN>)
#Logout
<ret> = pyp11.logout (<handle>, <slot>)
<ret>, <error> = t1.logout ()
# 
<ret> = pyp11.closesession (<handle>)
<ret>, <error> = t1.closesession ()
#   
<ret> = pyp11.listcerts (<handle>, <slot>)
<ret>, <error> = t1.listcerts ()
#   
<ret> = pyp11.listobjects (<handle>, <slot>, <'cert' | 'pubkey' | 'privkey' | 'data' | 'all'> [, 'value'])
<ret>, <error> = t1.listobjects (<'cert' | 'pubkey' | 'privkey' | 'data' | 'all'> [, 'value'])
# 
<ret> = pyp11.parsecert (<handle>, <slot>, <cert_der_hex>)
<ret>, <error> = t1.parsecert(<cert_der_hex>)
# 
<ret> = pyp11.importcert (<handle>, <slot>, <cert_der_hex>, < >)
<ret>, <error> = t1.importcert(<cert_der_hex>, < >)
# 
<ret> = pyp11.digest (<handle>, <slot>, < >, <>)
<ret>, <error> = t1.digest(< >, <>)
#  
<ret> = pyp11.digest (<handle>, <slot>, < >, <  >, <CKA_ID | handle  >)
<ret>, <error> = t1.digest(< >, <  >, <CKA_ID | handle  >)
#  
<ret> = pyp11.verify (<handle>, <slot>, <  >, <>, <asn1- subjectpublickeyinfo  hex>)
<ret>, <error> = t1.verify(<  >, <>, <asn1- subjectpublickeyinfo  hex>)
#  
<ret> = pyp11.keypair (<handle>, <slot>, < >, <OID >, <CKA_LABEL>)
<ret>, <error> = t1.keypair(< >, <OID >, <CKA_LABEL>)

      
      





III. Construction et installation du module pyp11 avec la classe Token



Construire et installer le module pyp11 avec la classe Token n'est pas différent de celui décrit dans la première partie.



Alors, téléchargez l' archive et décompressez-la. Nous allons dans le dossier PythonPKCS11 et exécutons la commande d'installation:



python3 setup.py install
      
      





Après avoir installé le module, allez dans le dossier tests et exécutez des tests pour le module pyp11.

Pour tester la classe Token, accédez au dossier test / classtoken.



Pour connecter le module pyp11 et la classe Token aux scripts, ajoutez simplement les opérateurs suivants:



import pyp11
from Token import Token
      
      





IV. Conclusion



Dans un proche avenir, la troisième partie de l'article devrait apparaître, qui vous dira comment ajouter la prise en charge de la cryptographie russe au projet PyKCS11 .



PS je veux dire merci svyatikov pour avoir aidé à tester le projet sur la plate-forme Windows.



All Articles