Unterstützung für PKCS # 11-Token mit GOST-Kryptografie in Python. Teil II - Objekte der Token-Klasse

BildIm vorherigen Artikel wurde das pyp11-Modul vorgestellt, in C geschrieben und bietet Unterstützung für PKCS # 11-Token mit russischer Kryptographie. In diesem Artikel wird die Token-Klasse behandelt, die die Verwendung der Funktionalität des pyp11- Moduls in in Python geschriebenen Skripten vereinfacht . Beachten Sie, dass die in TclOO geschriebene und im Dienstprogramm cryptoarmpkcs verwendete Token-Klasse als Prototyp dieser Klasse verwendet wurde :







Prototyp der Token-Klasse
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
  }
}
      
      







Die Token-Klasse enthält wie jede Klasse in Python einen Konstruktor, Methoden und einen Destruktor. Konstruktor und Destruktor sind dieselben Methoden, nur mit vordefinierten Namen. Der Konstruktor heißt __init__ und der Destruktor heißt __del__. Konstruktor- und Destruktordeklarationen können weggelassen werden. In der Token-Klasse wird die Destruktordeklaration weggelassen, aber der Konstruktor wird benötigt. Der Konstruktor instanziiert die Token-Klasse für ein bestimmtes Token mit bestimmten Attributen.



I. Token-Klassenkonstruktor



Der Konstruktor der Token-Klasse sieht also folgendermaßen aus:



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
#  ()  
      
      





Die Parameter des Konstruktors (der Methode __init__) sind (zusätzlich zum obligatorischen Selbst) das Handle der Token-Bibliothek (handlelp11), die Steckplatznummer (slottoken), in der sich das Token befinden soll, und die Token-Seriennummer ( Seriennummer).



Verwenden Sie das folgende Skript, um den Überblick über die pkcs # 11-Bibliothek, die Steckplatznummern und Informationen zu den darin enthaltenen Token zu erhalten:



#!/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()
      
      





Wenn mit der Bibliothek und dem Steckplatz alles klar ist, kann sich die Frage mit der Seriennummer des Tokens stellen - warum dieser Parameter benötigt wird und warum genau, aber zum Beispiel nicht mit der Token-Bezeichnung. Machen wir gleich eine Reservierung, dass dies für abrufbare Token von grundlegender Bedeutung ist, wenn ein Angreifer (oder versehentlich) einen Token im Slot durch einen anderen Token ersetzt. Darüber hinaus können verschiedene Instanzen des Tokens dieselben Bezeichnungen haben. Und schließlich wurde das Token möglicherweise noch nicht initialisiert, oder der Eigentümer wird es neu initialisieren, insbesondere das Token-Label ändern. Theoretisch garantiert selbst eine Seriennummer nicht ihre Identität, es ist optimal, alle Informationen über ein Token (Seriennummer, Modell, Hersteller) zu berücksichtigen. Es ist die Aufgabe des Konstruktors, die Argumente des Tokens in den Variablen der erstellten Instanz der Klasse zu speichern:



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





Die in dieser Klasse definierte Methode tokinfo () prüft, ob das angegebene Token im angegebenen Steckplatz vorhanden ist .



Die tokinfo-Methode gibt zwei Werte zurück (siehe oben im Konstruktor):



#         
    ret, stat = self.tokinfo()
      
      





Die erste Variable (ret) enthält das Ergebnis der Methodenausführung und die zweite (stat) enthält Informationen darüber, wie die Ausführung der Methode beendet wurde. Wenn die zweite Variable leer ist, war die tokinfo-Methode erfolgreich. Wenn die zweite Variable nicht leer ist, wurde die Methode mit einem Fehler beendet. Die Fehlerinformationen befinden sich in dieser Variablen. Wenn während der Ausführung der Methode self.tokinfo ein Fehler auftritt, schreibt der Konstruktor ihn in die Rückgabecode-Variable:



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





Nach dem Erstellen eines Objekts (Klasseninstanz) müssen Sie den Wert der Returncode-Variablen überprüfen, um sicherzustellen, dass das Objekt für das angegebene Token erstellt wurde:



#!/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()
#  
. . .
      
      





Wenn beim Erstellen eines Objekts ein Fehler festgestellt wird, empfiehlt es sich, dieses Objekt zu zerstören:



del < >
      
      





II. Methodenarchitektur in der Token-Klasse



Das Hauptprinzip beim Schreiben von Methoden war, dass sich die Ausnahmebehandlung innerhalb der Methoden befand und Informationen zu Ausnahmen (Fehlern) in Textform zurückgegeben wurden. Basierend darauf geben alle Methoden zwei Werte zurück: das tatsächliche Ausführungsergebnis und Informationen zum Fehler. Wenn keine Fehler vorliegen, ist der zweite Wert leer. Wir haben dies bereits mit der tokinfo-Methode im Konstruktor gesehen. Und hier ist der Code für die Tokinfo-Methode selbst:



  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)
      
      





Eine vollständige Beschreibung der Token-Klasse finden Sie hier.
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)

      
      







Betrachten wir die Funktionalität des pyp11-Moduls und ähnlicher Operatoren unter Verwendung der Token-Klasse.

Im letzteren Fall muss auch das Token-Objekt erstellt werden:



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





Beginnen wir mit der Initialisierung des Tokens:



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





Der ähnliche Code bei Verwendung der Token-Klasse sieht folgendermaßen aus (Objektkennung t1):



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





Als nächstes geben wir einfach die Entsprechung zwischen den Hauptoperatoren des pyp11-Moduls und den Methoden der Token-Klasse an, ohne Ausnahmen und Fehler zu behandeln:



<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. Erstellen und Installieren des pyp11-Moduls mit der Token-Klasse



Das Erstellen und Installieren des pyp11-Moduls mit der Token-Klasse unterscheidet sich nicht von dem im ersten Teil beschriebenen.



Laden Sie also das Archiv herunter und entpacken Sie es. Wir gehen in den PythonPKCS11-Ordner und führen den Installationsbefehl aus:



python3 setup.py install
      
      





Wechseln Sie nach der Installation des Moduls in den Testordner und führen Sie Tests für das pyp11-Modul aus.

Wechseln Sie zum Testen der Token-Klasse in den Ordner test / classtoken.



Fügen Sie einfach die folgenden Operatoren hinzu, um das pyp11-Modul und die Token-Klasse mit den Skripten zu verbinden:



import pyp11
from Token import Token
      
      





IV. Fazit



In naher Zukunft sollte der dritte Teil des Artikels erscheinen, in dem erläutert wird, wie Sie dem PyKCS11-Projekt Unterstützung für die russische Kryptographie hinzufügen können .



PS Ich möchte mich bedanken svyatikov um beim Testen des Projekts auf der Windows-Plattform zu helfen.



All Articles