Найти - Пользователи
Полная версия: работа со смарткартами, не могу окончательно понять принципы работы некоторых модулей
Начало » Python для новичков » работа со смарткартами, не могу окончательно понять принципы работы некоторых модулей
1
Cuzzz
необходимо подключить картридер со вставленной картой, и получить информацию по карте
"""The CardConnection abstract class manages connections with a card and apdu transmission.
__author__ = "http://www.gemalto.com"
Copyright 2001-2008 gemalto
Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com
This file is part of pyscard.
pyscard is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
pyscard is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with pyscard; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
"""
from smartcard.CardConnectionEvent import CardConnectionEvent
from smartcard.Exceptions import SmartcardException
from smartcard.Observer import Observer
from smartcard.Observer import Observable
class CardConnection(Observable):
    """Card connection abstract class.
    Known subclasses: smartcard.pcsc.PCSCCardConnection
    """
    T0_protocol         = 0x00000001
    T1_protocol         = 0x00000002
    RAW_protocol        = 0x00010000
    T15_protocol        = 0x00000008
    def __init__( self, reader ):
        """Construct a new card connection.
        readerName: name of the reader in which the smartcard to connect to is located.
        """
        Observable.__init__(self)
        self.reader = reader
        self.errorcheckingchain=None
        self.defaultprotocol = CardConnection.T0_protocol | CardConnection.T1_protocol
    def __del__( self ):
        """Connect to card."""
        pass
    def addSWExceptionToFilter( self, exClass ):
        """Add a status word exception class to be filtered.
        exClass: the class to filter, e.g. smartcard.sw.SWException.WarningProcessingException
        Filtered exceptions will not be raised when encountered in the
        error checking chain."""
        if None!=self.errorcheckingchain:
            self.errorcheckingchain[0].addFilterException( exClass )
    def addObserver(self, observer):
        """Add a CardConnection observer."""
        Observable.addObserver( self, observer )
    def deleteObserver(self, observer):
        """Remove a CardConnection observer."""
        Observable.deleteObserver( self, observer )
    def connect( self, protocol=None ):
        """Connect to card.
        protocol: a bit mask of the protocols to use, from CardConnection.T0_protocol, CardConnection.T1_protocol,
        CardConnection.RAW_protocol, CardConnection.T15_protocol
        """
        Observable.setChanged( self )
        Observable.notifyObservers( self, CardConnectionEvent('connect') )
    def disconnect( self ):
        """Disconnect from card."""
        Observable.setChanged( self )
        Observable.notifyObservers( self, CardConnectionEvent('disconnect') )
    def getATR( self ):
        """Return card ATR"""
        pass
    def getProtocol( self ):
        """Return bit mask for the protocol of connection, or None if no protocol set.
        The return value is a bit mask of CardConnection.T0_protocol, CardConnection.T1_protocol,
        CardConnection.RAW_protocol, CardConnection.T15_protocol
        """
        return self.defaultprotocol
    def getReader( self ):
        """Return card connection reader"""
        return self.reader
    def setErrorCheckingChain( self, errorcheckingchain ):
        """Add an error checking chain.
        errorcheckingchain: a smartcard.sw.ErrorCheckingChain object
        The error checking strategies in errorchecking chain will be tested
        with each received response APDU, and a smartcard.sw.SWException.SWException
        will be raised upon error."""
        self.errorcheckingchain=errorcheckingchain
    def setProtocol( self, protocol ):
        """Set protocol for card connection.
        protocol: a bit mask of CardConnection.T0_protocol, CardConnection.T1_protocol,
        CardConnection.RAW_protocol, CardConnection.T15_protocol
        e.g. setProtocol( CardConnection.T1_protocol | CardConnection.T0_protocol )
        """
        self.defaultprotocol = protocol
    def transmit( self, bytes, protocol=None ):
        """Transmit an apdu. Internally calls doTransmit() class method and notify observers
        upon command/response APDU events.
        Subclasses must override the doTransmit() class method.
        bytes:      list of bytes to transmit
        protocol:   the transmission protocol, from CardConnection.T0_protocol, CardConnection.T1_protocol,
                    or CardConnection.RAW_protocol
        """
        Observable.setChanged( self )
        Observable.notifyObservers( self, CardConnectionEvent('command', [bytes, protocol] ) )
        data, sw1, sw2 = self.doTransmit( bytes, protocol )
        Observable.setChanged( self )
        Observable.notifyObservers( self, CardConnectionEvent( 'response', [data, sw1, sw2 ] ) )
        if None!=self.errorcheckingchain:
            self.errorcheckingchain[0]( data, sw1, sw2 )
        return data, sw1, sw2
    def doTransmit( self, bytes, protocol ):
        """Performs the command APDU transmission.
        Subclasses must override this method for implementing apdu transmission."""
        pass
"""Card Names class
__author__ = "http://www.gemalto.com"
Copyright 2001-2008 gemalto
Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com
This file is part of pyscard.
pyscard is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
pyscard is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with pyscard; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
"""
from _bsddb import DBNotFoundError
from bsddb import hashopen
from os import environ
from os.path import join
from pickle import dumps, loads, HIGHEST_PROTOCOL
from smartcard.Synchronization import Synchronization, synchronize
from smartcard.util import toBytes
class __CardNames__(Synchronization): 
    """__CardNames__ inner class.
    Stores card names and card types into a bsddb hash database.
    The smartcard.CardNames.CardNames singleton manages the creation 
    of the unique instance of this class.
    """
    def __init__( self ):
        Synchronization.__init__(self)
        carddb_dir=environ['ALLUSERSPROFILE']
        carddb_file='cardnames.bdb'
        carddb_file=join( carddb_dir, carddb_file )
        self.db=hashopen( carddb_file, 'w' )
    
    def __del__(self):
        self.db.sync()
        self.db.close()
    def add( self, cardname, cardtype ):
        self.db[cardname]=dumps(cardtype, HIGHEST_PROTOCOL )
        self.db.sync()
    def delete( self, cardname ):
        try:
            del self.db[cardname]
        except DBNotFoundError:
            pass
    def dump( self ):
        for k,v in self.db.iteritems():
            print k, `loads(v)`
    def find( self, atr, reader=None ):
        for k,v in self.db.iteritems():
            if loads(v).matches( atr, reader ): return k
                
synchronize( __CardNames__, "add delete dump find" )
class CardNames:
    """The CardNames organizes cards by a unique name and an associated smartcard.CardType.CardType."""
    """The single instance of __CardNames__"""
    instance = None
    """Constructor: create a single instance of __readergroups on first call"""
    def __init__(self ):
        if None==CardNames.instance:
            CardNames.instance = __CardNames__()
    """All operators redirected to inner class."""
    def __getattr__(self, name):
        return getattr(self.instance, name)
if __name__ == '__main__':
    from smartcard.CardType import ATRCardType
    
    # define a card by its ATR
    ct = ATRCardType( [0x3B, 0x16, 0x94, 0x20, 0x02, 0x01, 0x00, 0x00, 0x0D] )
    
    # create CardName
    cn=CardNames()
    cn.add( "Palmera Protect V2", ct )
    cn.dump()
    print cn.find( [0x3B, 0x16, 0x94, 0x20, 0x02, 0x01, 0x00, 0x00, 0x0D] )
    print cn.find( [0x3B, 0x16, 0x94, 0x20, 0x02, 0x01, 0x00, 0x00] )
    cn.delete( "Palmera Protect V2" )
    print '---------'
    cn.dump()
"""ATR class managing some of the Answer To Reset content.
__author__ = "http://www.gemalto.com"
Copyright 2001-2008 gemalto
Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com
This file is part of pyscard.
pyscard is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
pyscard is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with pyscard; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
"""
class ATR:
    clockrateconversion=[ 372, 372, 558, 744, 1116, 1488, 1860, 'RFU', 'RFU', 512, 768, 1024, 1536, 2048, 'RFU', 'RFU', 'RFU' ]
    bitratefactor=['RFU', 1, 2, 4, 8, 16, 32, 'RFU', 12, 20, 'RFU', 'RFU', 'RFU', 'RFU', 'RFU', 'RFU' ]
    currenttable=[ 25, 50, 100, 'RFU' ]
    """ATR class."""
    def __init__( self, bytes ):
        """Construct a new atr from bytes."""
        self.bytes = bytes
        self.__initInstance__()
    def __checksyncbyte__( self ):
        """Check validity of TS."""
        if not 0x3b==self.bytes[0] and not 0x03f==self.bytes[0]:
            raise 'invalid TS',"0x%-0.2x"%self.bytes[0]
    def __initInstance__( self ):
        """Parse ATR and initialize members:
            TS: initial character
            T0: format character
            TA[n], TB[n], TC[n], TD[n], for n=0,1,...: protocol parameters
                note: protocol parameters indices start at 0, e.g. TA[0], TA[1] correspond to the ISO standard TA1, TA2 parameters
            historicalBytes: the ATR T1, T2, ..., TK historical bytes
            TCK: checksum byte (only for protocols different than T=0
            FI: clock rate conversion factor
            DI: voltage adjustment factor
            PI1: programming voltage factor
            II: maximum programming current factor
            N: extra guard time
        """
        self.__checksyncbyte__()
        # initial character
        self.TS = self.bytes[0]
        # format character
        self.T0 = self.bytes[1]
        # count of historical bytes
        self.K = self.T0 & 0x0f
        # initialize optional characters lists
        self.TA = []
        self.TB = []
        self.TC = []
        self.TD = []
        self.Y = []
        self.hasTA = []
        self.hasTB = []
        self.hasTC = []
        self.hasTD = []
        TD=self.T0
        hasTD=1
        n=0
        offset=1
        self.interfaceBytesCount=0
        while hasTD:
            self.Y += [TD>>4 & 0x0f]
            self.hasTD += [(self.Y[n] & 0x08)!=0 ]
            self.hasTC += [(self.Y[n] & 0x04)!=0 ]
            self.hasTB += [(self.Y[n] & 0x02)!=0 ]
            self.hasTA += [(self.Y[n] & 0x01)!=0 ]
            self.TA += [None]
            self.TB += [None]
            self.TC += [None]
            self.TD += [None]
            if self.hasTA[n]: self.TA[n]=self.bytes[ offset+self.hasTA[n] ]
            if self.hasTB[n]: self.TB[n]=self.bytes[ offset+self.hasTA[n]+self.hasTB[n] ]
            if self.hasTC[n]: self.TC[n]=self.bytes[ offset+self.hasTA[n]+self.hasTB[n]+self.hasTC[n] ]
            if self.hasTD[n]: self.TD[n]=self.bytes[ offset+self.hasTA[n]+self.hasTB[n]+self.hasTC[n]+self.hasTD[n] ]
            self.interfaceBytesCount += self.hasTA[n]+self.hasTB[n]+self.hasTC[n]+self.hasTD[n]
            TD=self.TD[n]
            hasTD=self.hasTD[n]
            offset=offset+self.hasTA[n]+self.hasTB[n]+self.hasTC[n]+self.hasTD[n]
            n=n+1
        # historical bytes
        self.historicalBytes=self.bytes[offset+1:offset+1+self.K]
        # checksum
        self.hasChecksum = (len(self.bytes)==offset+1+self.K+1)
        if self.hasChecksum:
            self.TCK=self.bytes[-1]
            checksum=0
            for b in self.bytes[1:]: checksum = checksum ^ b
            self.checksumOK = (checksum==0)
        else:
            self.TCK = None
        # clock-rate conversion factor
        if self.hasTA[0]:
            self.FI = self.TA[0]>>4 & 0x0f
        else:
            self.FI = None
        # bit-rate adjustment factor
        if self.hasTA[0]:
            self.DI = self.TA[0] & 0x0f
        else:
            self.DI = None
        # maximum programming current factor
        if self.hasTB[0]:
            self.II = self.TB[0]>>5 & 0x03
        else:
            self.II = None
        # programming voltage factor
        if self.hasTB[0]:
            self.PI1 = self.TB[0] & 0x1f
        else:
            self.PI1 = None
        # extra guard time
        self.N = self.TC[0]
    def getChecksum( self ):
        """Return the checksum of the ATR. Checksum is mandatory only for T=1."""
        return self.TCK
    def getHistoricalBytes( self ):
        """Return historical bytes."""
        return self.historicalBytes
    def getHistoricalBytesCount( self ):
        """Return count of historical bytes."""
        return len( self.historicalBytes )
    def getInterfaceBytesCount( self ):
        """Return count of interface bytes."""
        return self.interfaceBytesCount
    def getTA1( self ):
        """Return TA1 byte."""
        return self.TA[0]
    def getTB1( self ):
        """Return TB1 byte."""
        return self.TB[0]
    def getTC1( self ):
        """Return TC1 byte."""
        return self.TC[0]
    def getTD1(self):
        """Return TD1 byte."""
        return self.TD[0]
    def getBitRateFactor( self ):
        """Return bit rate factor."""
        if self.DI!=None:
            return ATR.bitratefactor[ self.DI ]
        else:
            return 1
    def getClockRateConversion( self ):
        """Return clock rate conversion."""
        if self.FI!=None:
            return ATR.clockrateconversion[ self.FI ]
        else:
            return 372
    def getProgrammingCurrent( self ):
        """Return maximum programming current."""
        if self.II!=None:
            return ATR.currenttable[ self.II ]
        else:
            return 50
    def getProgrammingVoltage( self ):
        """Return programming voltage."""
        if self.PI1!=None:
            return 5*(1+self.PI1)
        else:
            return 5
    def getGuardTime( self ):
        """Return extra guard time."""
        return self.N
    def getSupportedProtocols( self ):
        """Returns a dictionnary of supported protocols."""
        protocols={}
        for td in self.TD:
            if td!=None:
                strprotocol = "T=%d" % (td & 0x0F)
                protocols[strprotocol]=True
        if not self.hasTD[0]:
            protocols['T=0']=True
        return protocols
    def isT0Supported( self ):
        """Return True if T=0 is supported."""
        protocols=self.getSupportedProtocols()
        return protocols.has_key( 'T=0' )
    def isT1Supported( self ):
        """Return True if T=1 is supported."""
        protocols=self.getSupportedProtocols()
        return protocols.has_key( 'T=1' )
    def isT15Supported( self ):
        """Return True if T=15 is supported."""
        protocols=self.getSupportedProtocols()
        return protocols.has_key( 'T=15' )
    def dump( self ):
        """Dump the details of an ATR."""
        for i in range( 0, len(self.TA) ):
            if self.TA[i]!=None: print "TA%d: %x" % (i+1,self.TA[i])
            if self.TB[i]!=None: print "TB%d: %x" % (i+1,self.TB[i])
            if self.TC[i]!=None: print "TC%d: %x" % (i+1,self.TC[i])
            if self.TD[i]!=None: print "TD%d: %x" % (i+1,self.TD[i])
        print 'supported protocols', self.getSupportedProtocols()
        print 'T=0 supported', self.isT0Supported()
        print 'T=1 supported', self.isT1Supported()
        print 'checksum:', self.getChecksum()
        print '\tclock rate conversion factor:', self.getClockRateConversion()
        print '\tbit rate adjustment factor:', self.getBitRateFactor()
        print '\tmaximum programming current:', self.getProgrammingCurrent()
        print '\tprogramming voltage:', self.getProgrammingVoltage()
        print '\tguard time:', self.getGuardTime()
        print 'nb of interface bytes:', self.getInterfaceBytesCount()
        print 'nb of historical bytes:', self.getHistoricalBytesCount()
    def __str__( self ):
        """Returns a string representation of the ATR as a strem of bytes."""
        return reduce( lambda a, b: a+"%-0.2X " % ((b+256)%256), self.bytes, '' )
if __name__ == '__main__':
    """Small sample illustrating the use of ATR."""
    atrs = [ [ 0x3F, 0x65, 0x25, 0x00, 0x2C, 0x09, 0x69, 0x90, 0x00 ],
             [ 0x3F, 0x65, 0x25, 0x08, 0x93, 0x04, 0x6C, 0x90, 0x00 ],
             [ 0x3B, 0x16, 0x94, 0x7C, 0x03, 0x01, 0x00, 0x00, 0x0D ],
             [ 0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03 ],
             [ 0x3B, 0xE3, 0x00, 0xFF, 0x81, 0x31, 0x52, 0x45, 0xA1, 0xA2, 0xA3, 0x1B],
             [ 0x3B, 0xE5, 0x00, 0x00, 0x81, 0x21, 0x45, 0x9C, 0x10, 0x01, 0x00, 0x80, 0x0D ]
           ]
    for atr in atrs:
        a=ATR( atr )
        print 80*'-'
        print a
        a.dump()
        print reduce( lambda a, b: a+"%-0.2X " % ((b+256)%256), a.getHistoricalBytes(), '' )

если возможно накидайте рабочий код на подключение карты, дальше по примеру надеюсь смогу разобраться
ad3w
Здесь вроде все подробно описано - http://pyscard.sourceforge.net/pyscard-usersguide.html
Cuzzz
спасибо!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB