pyscard smartcard framework samples

pyscard is a Python module adding smart cards support to Python.

It consists of smartcard.scard, an extension module wrapping Windows smart card base components (also known as PCSC), and smartcard, a Python framework library hiding PCSC complexity.

Display the ATR of inserted cards

#! /usr/bin/env python3
"""
Sample script that displays the ATR of inserted cards.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 gemalto
Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com
Copyright 2010 Ludovic Rousseau
Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr

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.Exceptions import NoCardException
from smartcard.System import readers
from smartcard.util import toHexString
import sys

for reader in readers():
    try:
        connection = reader.createConnection()
        connection.connect()
        print(reader, toHexString(connection.getATR()))
    except NoCardException:
        print(reader, 'no card inserted')

if 'win32' == sys.platform:
    print('press Enter to continue')
    sys.stdin.read(1)

Selecting the DF_TELECOM of a card

#! /usr/bin/env python3
"""
Sample script that tries to select the DF_TELECOM on all inserted cards.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 gemalto
Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com
Copyright 2010 Ludovic Rousseau
Author: Ludovic Rousseau, mailto:ludovic.rousseau@free.fr

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.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
from smartcard.Exceptions import CardRequestTimeoutException
import sys

# define the apdus used in this script
GET_RESPONSE = [0XA0, 0XC0, 00, 00]
SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
DF_TELECOM = [0x7F, 0x10]

# request any card type
cardtype = AnyCardType()

try:
    # request card insertion
    print('insert a card (SIM card if possible) within 10s')
    cardrequest = CardRequest(timeout=10, cardType=cardtype)
    cardservice = cardrequest.waitforcard()

    # attach the console tracer
    observer = ConsoleCardConnectionObserver()
    cardservice.connection.addObserver(observer)

    # connect to the card and perform a few transmits
    cardservice.connection.connect()

    apdu = SELECT + DF_TELECOM
    response, sw1, sw2 = cardservice.connection.transmit(apdu)

    # there is a DF_TELECOM
    if sw1 == 0x9F:
        apdu = GET_RESPONSE + [sw2]
        response, sw1, sw2 = cardservice.connection.transmit(apdu)

    else:
        print('no DF_TELECOM')

except CardRequestTimeoutException:
    print('time-out: no card inserted during last 10s')

if 'win32' == sys.platform:
    print('press Enter to continue')
    sys.stdin.read(1)

A simple apdu tracer and interpreter

#! /usr/bin/env python3
"""
Sample script that defines a custom card connection observer.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 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.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.CardConnectionObserver import CardConnectionObserver
from smartcard.util import toHexString


class TracerAndSELECTInterpreter(CardConnectionObserver):
    """This observer will interprer SELECT and GET RESPONSE bytes
    and replace them with a human readable string."""

    def update(self, cardconnection, ccevent):

        if 'connect' == ccevent.type:
            print('connecting to ' + cardconnection.getReader())

        elif 'disconnect' == ccevent.type:
            print('disconnecting from ' + cardconnection.getReader())

        elif 'command' == ccevent.type:
            str = toHexString(ccevent.args[0])
            str = str.replace("A0 A4 00 00 02", "SELECT")
            str = str.replace("A0 C0 00 00", "GET RESPONSE")
            print('>', str)

        elif 'response' == ccevent.type:
            if [] == ccevent.args[0]:
                print('<  []', "%-2X %-2X" % tuple(ccevent.args[-2:]))
            else:
                print('<',
                      toHexString(ccevent.args[0]),
                      "%-2X %-2X" % tuple(ccevent.args[-2:]))


# define the apdus used in this script
GET_RESPONSE = [0XA0, 0XC0, 00, 00]
SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
DF_TELECOM = [0x7F, 0x10]


# we request any type and wait for 10s for card insertion
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=10, cardType=cardtype)
cardservice = cardrequest.waitforcard()

# create an instance of our observer and attach to the connection
observer = TracerAndSELECTInterpreter()
cardservice.connection.addObserver(observer)


# connect and send APDUs
# the observer will trace on the console
cardservice.connection.connect()

apdu = SELECT + DF_TELECOM
response, sw1, sw2 = cardservice.connection.transmit(apdu)
if sw1 == 0x9F:
    apdu = GET_RESPONSE + [sw2]
    response, sw1, sw2 = cardservice.connection.transmit(apdu)
else:
    print('no DF_TELECOM')

import sys
if 'win32' == sys.platform:
    print('press Enter to continue')
    sys.stdin.read(1)

Tracing connection events

#! /usr/bin/env python3
"""
Sample script that monitors card connection events.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 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.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver

# define the apdus used in this script
GET_RESPONSE = [0XA0, 0XC0, 00, 00]
SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
DF_TELECOM = [0x7F, 0x10]


# request any card type
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=1.5, cardType=cardtype)
cardservice = cardrequest.waitforcard()


# attach the console tracer
observer = ConsoleCardConnectionObserver()
cardservice.connection.addObserver(observer)


# connect to the card and perform a few transmits
cardservice.connection.connect()

apdu = SELECT + DF_TELECOM
response, sw1, sw2 = cardservice.connection.transmit(apdu)

if sw1 == 0x9F:
    apdu = GET_RESPONSE + [sw2]
    response, sw1, sw2 = cardservice.connection.transmit(apdu)


import sys
if 'win32' == sys.platform:
    print('press Enter to continue')
    sys.stdin.read(1)

Decorating Card Connections to add custom behavior

#! /usr/bin/env python3
"""
Sample script that illustrates card connection decorators.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 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.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
from smartcard.CardConnectionDecorator import CardConnectionDecorator
from smartcard.util import toHexString

# define two custom CardConnectionDecorator
# the decorators are very simple, just to illustrate
# shortly how several decorators can be added to the
# card connection


class SecureChannelConnection(CardConnectionDecorator):
    '''This decorator is a mockup of secure channel connection.
    It merely pretends to cypher/uncypher upon apdu transmission.'''

    def __init__(self, cardconnection):
        CardConnectionDecorator.__init__(self, cardconnection)

    def cypher(self, bytes):
        '''Cypher mock-up; you would include the secure channel logics here.'''
        print('cyphering', toHexString(bytes))
        return bytes

    def uncypher(self, data):
        '''Uncypher mock-up;
        you would include the secure channel logics here.'''
        print('uncyphering', toHexString(data))
        return data

    def transmit(self, bytes, protocol=None):
        """Cypher/uncypher APDUs before transmission"""
        cypheredbytes = self.cypher(bytes)
        data, sw1, sw2 = CardConnectionDecorator.transmit(
            self, cypheredbytes, protocol)
        if [] != data:
            data = self.uncypher(data)
        return data, sw1, sw2


class FakeATRConnection(CardConnectionDecorator):
    '''This decorator changes the fist byte of the ATR. This is just an example
    to show that decorators can be nested.'''

    def __init__(self, cardconnection):
        CardConnectionDecorator.__init__(self, cardconnection)

    def getATR(self):
        """Replace first BYTE of ATR by 3F"""
        atr = CardConnectionDecorator.getATR(self)
        return [0x3f] + atr[1:]


# define the apdus used in this script
GET_RESPONSE = [0XA0, 0XC0, 00, 00]
SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
DF_TELECOM = [0x7F, 0x10]


# request any card type
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=1.5, cardType=cardtype)
cardservice = cardrequest.waitforcard()

# attach the console tracer
observer = ConsoleCardConnectionObserver()
cardservice.connection.addObserver(observer)

# attach our decorator
cardservice.connection = FakeATRConnection(
    SecureChannelConnection(cardservice.connection))

# connect to the card and perform a few transmits
cardservice.connection.connect()

print('ATR', toHexString(cardservice.connection.getATR()))

apdu = SELECT + DF_TELECOM
response, sw1, sw2 = cardservice.connection.transmit(apdu)

if sw1 == 0x9F:
    apdu = GET_RESPONSE + [sw2]
    response, sw1, sw2 = cardservice.connection.transmit(apdu)


import sys
if 'win32' == sys.platform:
    print('press Enter to continue')
    sys.stdin.read(1)

Detecting response apdu errors

#! /usr/bin/env python3
"""Sample script for APDU error checking.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 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.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver

from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain
from smartcard.sw.ISO7816_4ErrorChecker import ISO7816_4ErrorChecker
from smartcard.sw.ISO7816_8ErrorChecker import ISO7816_8ErrorChecker
from smartcard.sw.ISO7816_9ErrorChecker import ISO7816_9ErrorChecker
from smartcard.sw.SWExceptions import SWException, WarningProcessingException


# define the apdus used in this script
GET_RESPONSE = [0XA0, 0XC0, 00, 00]
SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
DF_TELECOM = [0x7F, 0x10]


if __name__ == '__main__':

    print('Insert a card within 10 seconds')
    print('Cards without a DF_TELECOM will except')

    # request any card type
    cardtype = AnyCardType()
    cardrequest = CardRequest(timeout=10, cardType=cardtype)
    cardservice = cardrequest.waitforcard()

    # use ISO7816-4 and ISO7816-8 error checking strategy
    # first check iso7816_8 errors, then iso7816_4 errors
    errorchain = []
    errorchain = [ErrorCheckingChain(errorchain, ISO7816_9ErrorChecker())]
    errorchain = [ErrorCheckingChain(errorchain, ISO7816_8ErrorChecker())]
    errorchain = [ErrorCheckingChain(errorchain, ISO7816_4ErrorChecker())]
    cardservice.connection.setErrorCheckingChain(errorchain)

    # filter Warning Processing Exceptions (sw1 = 0x62 or 0x63)
    cardservice.connection.addSWExceptionToFilter(WarningProcessingException)

    # attach the console tracer
    observer = ConsoleCardConnectionObserver()
    cardservice.connection.addObserver(observer)

    # connect to the card and perform a few transmits
    cardservice.connection.connect()

    try:
        apdu = SELECT + DF_TELECOM
        response, sw1, sw2 = cardservice.connection.transmit(apdu)

        if sw1 == 0x9F:
            apdu = GET_RESPONSE + [sw2]
            response, sw1, sw2 = cardservice.connection.transmit(apdu)

    except SWException as e:
        print(str(e))

    cardservice.connection.disconnect()

    import sys
    if 'win32' == sys.platform:
        print('press Enter to continue')
        sys.stdin.read(1)

Implementing a custom ErrorChecker

#! /usr/bin/env python3
"""Sample script for APDU error checking with a custom error checker.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 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.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver

from smartcard.sw.ErrorCheckingChain import ErrorCheckingChain
from smartcard.sw.ErrorChecker import ErrorChecker
from smartcard.sw.SWExceptions import SWException


class MyErrorChecker(ErrorChecker):
    """Our custom error checker that will except if 0x61<sw1<0x70."""

    def __call__(self, data, sw1, sw2):
        print(sw1, sw2)
        if 0x61 < sw1 and 0x70 > sw1:
            raise SWException(data, sw1, sw2)

# define the apdus used in this script
GET_RESPONSE = [0XA0, 0XC0, 00, 00]
SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
DF_TELECOM = [0x7F, 0x10]

if __name__ == '__main__':

    print('Insert a card within 10 seconds')
    print('Cards without a DF_TELECOM will except')

    # request any card
    cardtype = AnyCardType()
    cardrequest = CardRequest(timeout=10, cardType=cardtype)
    cardservice = cardrequest.waitforcard()

    # our error checking chain
    errorchain = []
    errorchain = [ErrorCheckingChain([], MyErrorChecker())]
    cardservice.connection.setErrorCheckingChain(errorchain)

    # attach the console tracer
    observer = ConsoleCardConnectionObserver()
    cardservice.connection.addObserver(observer)

    # send a few apdus; exceptions will occur upon errors
    cardservice.connection.connect()

    try:
        SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02]
        DF_TELECOM = [0x7F, 0x10]
        apdu = SELECT + DF_TELECOM
        response, sw1, sw2 = cardservice.connection.transmit(apdu)
        if sw1 == 0x9F:
            GET_RESPONSE = [0XA0, 0XC0, 00, 00]
            apdu = GET_RESPONSE + [sw2]
            response, sw1, sw2 = cardservice.connection.transmit(apdu)
    except SWException as e:
        print(e, "{:x} {:x}".format(e.sw1, e.sw2))

        cardservice.connection.disconnect()

    import sys
    if 'win32' == sys.platform:
        print('press Enter to continue')
        sys.stdin.read(1)

Implementing a custom card type

#! /usr/bin/env python3
"""
Sample script that demonstrates how to create a custom CardType.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 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.CardType import CardType
from smartcard.CardRequest import CardRequest
from smartcard.util import toHexString


class DCCardType(CardType):
    # define our custom CardType
    # this card type defines direct convention card
    # (first atr byte equal to 0x3b)

    def matches(self, atr, reader=None):
        return atr[0] == 0x3B


# request a direct convention card
cardtype = DCCardType()
cardrequest = CardRequest(timeout=1, cardType=cardtype)
cardservice = cardrequest.waitforcard()


# connect and print atr and reader
cardservice.connection.connect()
print(toHexString(cardservice.connection.getATR()))
print(cardservice.connection.getReader())


import sys
if 'win32' == sys.platform:
    print('press Enter to continue')
    sys.stdin.read(1)

Monitoring smartcard readers

#! /usr/bin/env python3
"""
Sample script that monitors smartcard readers.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 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 time import sleep

from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver


class printobserver(ReaderObserver):
    """A simple reader observer that is notified
    when readers are added/removed from the system and
    prints the list of readers
    """

    def update(self, observable, actions):
        (addedreaders, removedreaders) = actions
        print("Added readers", addedreaders)
        print("Removed readers", removedreaders)

if __name__ == '__main__':
    print("Add or remove a smartcard reader to the system.")
    print("This program will exit in 10 seconds")
    print("")
    readermonitor = ReaderMonitor()
    readerobserver = printobserver()
    readermonitor.addObserver(readerobserver)

    sleep(10)

    # don't forget to remove observer, or the
    # monitor will poll forever...
    readermonitor.deleteObserver(readerobserver)

    import sys
    if 'win32' == sys.platform:
        print('press Enter to continue')
        sys.stdin.read(1)

Monitoring smartcard insertion/removal

#! /usr/bin/env python3
"""
Sample script that monitors smartcard insertion/removal.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 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 time import sleep

from smartcard.CardMonitoring import CardMonitor, CardObserver
from smartcard.util import toHexString


# a simple card observer that prints inserted/removed cards
class PrintObserver(CardObserver):
    """A simple card observer that is notified
    when cards are inserted/removed from the system and
    prints the list of cards
    """

    def update(self, observable, actions):
        (addedcards, removedcards) = actions
        for card in addedcards:
            print("+Inserted: ", toHexString(card.atr))
        for card in removedcards:
            print("-Removed: ", toHexString(card.atr))

if __name__ == '__main__':
    print("Insert or remove a smartcard in the system.")
    print("This program will exit in 10 seconds")
    print("")
    cardmonitor = CardMonitor()
    cardobserver = PrintObserver()
    cardmonitor.addObserver(cardobserver)

    sleep(10)

    # don't forget to remove observer, or the
    # monitor will poll forever...
    cardmonitor.deleteObserver(cardobserver)

    import sys
    if 'win32' == sys.platform:
        print('press Enter to continue')
        sys.stdin.read(1)

APDU/ATR byte to string utilities

#! /usr/bin/env python3
"""
Sample script to illustrate toHexString() utility method

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 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.util import *


print(40 * '-')
bytes = [59, 101, 0, 0, 156, 17, 1, 1, 3]
print('bytes = [59, 101, 0, 0, 156, 17, 1, 1, 3]')
print('toHexString(bytes) =', toHexString(bytes))
print('toHexString(bytes, COMMA) =', toHexString(bytes, COMMA))
print('toHexString(bytes, PACK) =', toHexString(bytes, PACK))
print('toHexString(bytes, HEX) =', toHexString(bytes, HEX))
print('toHexString(bytes, HEX | COMMA) =', toHexString(bytes, HEX | COMMA))
print('toHexString(bytes, HEX | UPPERCASE) =',
      toHexString(bytes, HEX | UPPERCASE))
print('toHexString(bytes, HEX | UPPERCASE | COMMA) =',
      toHexString(bytes, HEX | UPPERCASE | COMMA))


print(40 * '-')
bytes = [0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03]
print('bytes = [ 0x3B, 0x65, 0x00, 0x00, 0x9C, 0x11, 0x01, 0x01, 0x03 ]')
print('toHexString(bytes, COMMA) =', toHexString(bytes, COMMA))
print('toHexString(bytes) =', toHexString(bytes))
print('toHexString(bytes, PACK) =', toHexString(bytes, PACK))
print('toHexString(bytes, HEX) =', toHexString(bytes, HEX))
print('toHexString(bytes, HEX | COMMA) =', toHexString(bytes, HEX | COMMA))
print('toHexString(bytes, HEX | UPPERCASE) =',
      toHexString(bytes, HEX | UPPERCASE))
print('toHexString(bytes, HEX | UPPERCASE | COMMA) =',
      toHexString(bytes, HEX | UPPERCASE | COMMA))


import sys
if 'win32' == sys.platform:
    print('press Enter to continue')
    sys.stdin.read(1)