The unified diff between revisions [bbd67dd4..] and [455efdbb..] is displayed below. It can also be downloaded as a raw diff.

#
#
# patch "mifare.py"
#  from [d0ddf4fab6a2f37bd349d70690260acaf6302d4d]
#    to [c5e94d81f17816ea1cf476a6f883e7f1d7de4c15]
#
============================================================
--- mifare.py	d0ddf4fab6a2f37bd349d70690260acaf6302d4d
+++ mifare.py	c5e94d81f17816ea1cf476a6f883e7f1d7de4c15
@@ -22,6 +22,10 @@ class MIFARECommunicationException(MIFAR
     pass


+class MIFAREAuthenticationException(MIFAREException):
+    pass
+
+
 class MIFAREReader:
     '''An interface to a particular MIFARE reader.'''

@@ -32,6 +36,15 @@ class MIFAREReader:
         if isinstance(self.io, serial.Serial):
             self.io.setTimeout(2)
         self.address = '\x00\x00'
+
+    def _get_absolute_block(self, vector):
+        if vector[0] < 32:
+            return vector[0] * 4 + vector[1]
+        else:
+            # Sectors below 32 are 4 blocks
+            # Sectors above are 16 blocks
+            # Thus, sector 32 starts at block 128, 33 at 144, and so on
+            return 128 + (vector[0] - 32) * 16 + vector[1]

     def send_packet(self, data):
         '''Constructs a packet for the supplied data string, sends it to the
@@ -94,8 +107,24 @@ class MIFAREReader:
             capacity = ord(self.send_packet('\x03\x02' + serial)[3])
             return (serial, capacity)

-    def sector_login(self, keytype, key):
-        pass
+    def sector_login(self, blockvect, key, keytype=0):
+        """Log in to a block using the six-byte key.
+
+        Use a keytype of 1 to use key B."""
+        sector = self.get_absolute_block((blocknum[0], 0))
+
+        if len(key) != 6:
+            raise ValueError, 'key must be a six-byte string'
+
+        keytype = 96 + keytype
+
+        data = chr(keytype) + chr(sector) + key
+
+        result = self.send_packet('\x07\x02' + data)
+        if ord(result[2]) == 16:
+            raise MIFAREAuthenticationError, "incorrect key provided"
+
+        return

     def read_block(self, blocknum):
         pass