def getPubKey(self, bac_cp, mrz_value):
        """
        It uses method from pypassport.doc9303.bac in order to authenticate and establish the session keys

        @param bac_cp: A BAC for the authentication and establishment of session keys
        @type bac_cp: A pypassport.doc9303.bac.BAC() object
        @param mrz_value: A MRZ
        @type mrz_value: String value ("PPPPPPPPPPcCCCYYMMDDcSYYMMDDc<<<<<<<<<<<<<<cd")

        @return: The public key (DG15)
        """
        self.log("Reset conenction")
        self._iso7816.rstConnection()

        self.log("Generate the MRZ object")
        mrz_pass = mrz.MRZ(mrz_value)
        self.log("Check the MRZ")
        mrz_pass.checkMRZ()

        self.log("Authentication and establishment of session keys")
        (KSenc, KSmac, ssc) = bac_cp.authenticationAndEstablishmentOfSessionKeys(mrz_pass)
        self.log("Encryption key: {0}".format(binToHexRep(KSenc)))
        self.log("MAC key: {0}".format(binToHexRep(KSmac)))
        self.log("Send Sequence Counter: {0}".format(binToHexRep(ssc)))
        sm = SecureMessaging(KSenc, KSmac, ssc)
        self._iso7816.setCiphering(sm)

        dgReader = datagroup.DataGroupReaderFactory().create(self._iso7816)

        tag = converter.toTAG("DG15")
        dgFile = dgReader.readDG(tag)
        self.log("Get public key")
        dg15 = datagroup.DataGroupFactory().create(dgFile)
        self.log("Public key: {0}".format(binToHexRep(dg15.body)))
        return dg15.body
Exemplo n.º 2
0
    def sessionKeys(self, data):
        """
        Calculate the session keys (KSenc, KSmac) and the SSC from the data
        received by the mutual authenticate command.

        @param data: the data received from the mutual authenticate command sent to the chip.
        @type data: a binary string
        @return: A set of two 16 bytes keys (KSenc, KSmac) and the SSC
        """

        self.log("Decrypt and verify received data and compare received RND.IFD with generated RND.IFD")
        if mac(self._ksmac, pad(data[0:32])) != data[32:]:
            raise Exception, "The MAC value is not correct"

        tdes= DES3.new(self._ksenc,DES.MODE_CBC, b'\x00\x00\x00\x00\x00\x00\x00\x00')
        response = tdes.decrypt(data[0:32])
        response_kicc = response[16:32]
        Kseed = self._xor(self._kifd, response_kicc)
        self.log("Calculate XOR of Kifd and Kicc")
        self.log("\tKseed: " + binToHexRep(Kseed))

        KSenc = self.keyDerivation(Kseed,BAC.KENC)
        KSmac = self.keyDerivation(Kseed,BAC.KMAC)
        self.log("Calculate Session Keys (KSenc and KSmac) using Appendix 5.1")
        self.log("\tKSenc: " + binToHexRep(KSenc))
        self.log("\tKSmac: " + binToHexRep(KSmac))

        ssc = self._rnd_icc[-4:] + self._rnd_ifd[-4:]
        self.log("Calculate Send Sequence Counter")
        self.log("\tSSC: " + binToHexRep(ssc))
        return (KSenc, KSmac, ssc)
Exemplo n.º 3
0
    def sessionKeys(self, data):
        """
        Calculate the session keys (KSenc, KSmac) and the SSC from the data 
        received by the mutual authenticate command.
        
        @param data: the data received from the mutual authenticate command send to the chip.
        @type data: a binary string
        @return: A set of two 16 bytes keys (KSenc, KSmac) and the SSC 
        """
        self.log(
            "Decrypt and verify received data and compare received RND.IFD with generated RND.IFD "
            + binToHexRep(self._ksmac))
        # this does not work, encryption with cards ksmac
        # mac(self._ksmac, data[0:32]) != data[32:]:
        #    raise Exception("The MAC value is not correct")

        tdes = DES3.new(self._ksenc, DES.MODE_CBC, b'\0' * 8)
        response = tdes.decrypt(data[0:32])
        response_kicc = response[16:32]
        Kseed = self._xor(self._kifd, response_kicc)
        self.log("Calculate XOR of Kifd and Kicc")
        self.log("\tKseed: " + binToHexRep(Kseed))

        KSenc = self.keyDerivation(Kseed, BAC.KENC)
        KSmac = self.keyDerivation(Kseed, BAC.KMAC)
        self.log("Calculate Session Keys (KSenc and KSmac) using Appendix 5.1")
        self.log("\tKSenc: " + binToHexRep(KSenc))
        self.log("\tKSmac: " + binToHexRep(KSmac))

        ssc = self._rnd_icc[-4:] + self._rnd_ifd[-4:]
        self.log("Calculate Send Sequence Counter")
        self.log("\tSSC: " + binToHexRep(ssc))
        return (KSenc, KSmac, ssc)
Exemplo n.º 4
0
    def sha1Hash(self):
        h = sha1(self.field1Form.get()).digest()

        self.writeToLog("SHA-1 HASH:\n  message: {0}\n  hash: {1}".format(
            self.field1Form.get(), binToHexRep(h)))

        self.field1Form.delete(0, END)
        self.field2Form.delete(0, END)
        self.field1Form.insert(0, binToHexRep(h))
Exemplo n.º 5
0
    def sha1Hash(self):
        h = sha1(self.field1Form.get()).digest()

        self.writeToLog("SHA-1 HASH:\n  message: {0}\n  hash: {1}".format(self.field1Form.get(),
                                                                          binToHexRep(h)))

        self.field1Form.delete(0, END)
        self.field2Form.delete(0, END)
        self.field1Form.insert(0, binToHexRep(h))
Exemplo n.º 6
0
    def sscGenerator(self):
        rnd_icc = hexRepToBin(self.field1Form.get())
        rnd_ifd = hexRepToBin(self.field2Form.get())
        ssc = rnd_icc[-4:] + rnd_ifd[-4:]
        self.writeToLog(
            "SSC GENERATOR:\n  RND ICC: {0}\n  RND IFD: {1}\n  SSC: {2}".
            format(self.field1Form.get(), self.field2Form.get(),
                   binToHexRep(ssc)))

        self.field1Form.delete(0, END)
        self.field2Form.delete(0, END)
        self.field1Form.insert(0, binToHexRep(ssc))
Exemplo n.º 7
0
    def createMAC(self):
        try:
            m = iso9797.mac(hexRepToBin(self.field2Form.get()), iso9797.pad(hexRepToBin(self.field1Form.get())))

            self.writeToLog("MAC:\n  message: {0}\n  Key: {1}\n  MAC: {2}".format(self.field1Form.get(),
                                                                          self.field2Form.get(),
                                                                          binToHexRep(m)))

            self.field1Form.delete(0, END)
            self.field2Form.delete(0, END)
            self.field1Form.insert(0, binToHexRep(m))
        except Exception, msg:
            tkMessageBox.showerror("Error: BAC", str(msg))
Exemplo n.º 8
0
    def createMAC(self):
        try:
            m = iso9797.mac(hexRepToBin(self.field2Form.get()),
                            iso9797.pad(hexRepToBin(self.field1Form.get())))

            self.writeToLog(
                "MAC:\n  message: {0}\n  Key: {1}\n  MAC: {2}".format(
                    self.field1Form.get(), self.field2Form.get(),
                    binToHexRep(m)))

            self.field1Form.delete(0, END)
            self.field2Form.delete(0, END)
            self.field1Form.insert(0, binToHexRep(m))
        except Exception, msg:
            tkMessageBox.showerror("Error: BAC", str(msg))
Exemplo n.º 9
0
    def initOffline(self, mrz):
        """
        In order to perform an offline brute force attack
        the attacker needs a nonce and a BAC response
        from a legitimate communication between a reader and a passort.

        @param id_pass: Document number
        @type id_pass: String (0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ<)
        @param dob: Date of birth
        @type dob: String (YYMMDD)
        @param exp: Expiration date
        @type exp: String (YYMMDD)

        @return: A set composed of (nonce, response) required for the offline attack
        """

        kmrz = mrz[0:10] + mrz[13:20] + mrz[21:28]
        kseed = self._genKseed(kmrz)
        kenc = self._keyDerivation(kseed, BruteForce.KENC)
        kmac = self._keyDerivation(kseed, BruteForce.KMAC)

        #rnd_icc = self._iso7816.getChallenge()
        rnd_icc = os.urandom(8)
        cmd_data = self._authentication(rnd_icc, kenc, kmac)

        return binToHexRep(cmd_data)
Exemplo n.º 10
0
    def initOffline(self, mrz):
        """
        In order to perform an offline brute force attack
        the attacker needs a nonce and a BAC response
        from a legitimate communication between a reader and a passort.

        @param id_pass: Document number
        @type id_pass: String (0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ<)
        @param dob: Date of birth
        @type dob: String (YYMMDD)
        @param exp: Expiration date
        @type exp: String (YYMMDD)

        @return: A set composed of (nonce, response) required for the offline attack
        """

        kmrz = mrz[0:10] + mrz[13:20] + mrz[21:28]
        kseed = self._genKseed(kmrz)
        kenc = self._keyDerivation(kseed, BruteForce.KENC)
        kmac = self._keyDerivation(kseed, BruteForce.KMAC)

        # rnd_icc = self._iso7816.getChallenge()
        rnd_icc = os.urandom(8)
        cmd_data = self._authentication(rnd_icc, kenc, kmac)

        return binToHexRep(cmd_data)
Exemplo n.º 11
0
    def getHighestSign(self, max=100):
        """
        Sign a random number several times (100 by default)
        Keep the highest signature

        @param max: The # of loop. The highest the more accurate is suppose to be the output
        @type max: int <1

        @return: The highest signature
        """

        if not self.isVulnerable():
            raise AATraceabilityException("This passport is not vulnerable for a AA traceability")

        higher = ""
        i = 0
        self.log("Start the internal authentication loop {0} times".format(max))
        while i<max:
            try:
                rnd = os.urandom(8)
                signature = binToHexRep(self._iso7816.internalAuthentication(rnd))
                if signature > higher:
                    higher = signature
            except Iso7816Exception, msg:
                print msg
            i += 1
Exemplo n.º 12
0
    def send(self):
        try:
            self.initIso7816()

            cla = self.customCLAForm.get()
            ins = self.customINSForm.get()
            p1 = self.customP1Form.get()
            p2 = self.customP2Form.get()
            lc = self.customLCForm.get()
            data = self.customDATAForm.get()
            le = self.customLEForm.get()

            if not lc:
                if data:
                    lc = hexToHexRep(len(data)/2)

            toSend = apdu.CommandAPDU(cla, ins, p1, p2, lc, data, le)

            ans = self._iso7816.transmitRaw(toSend)
            rep = binToHexRep(ans.res)
            sw1 = ans.sw1
            sw2 = ans.sw2
            self.writeToLog("REQUEST:\n  APDU: CLA:{0} INS:{1} P1:{2} P2:{3} LC:{4} DATA:{5} LE:{6}".format(cla, ins, p1, p2, lc, data, le))
            self.writeToLog("RESPONSE:\n  APDU:\n    Data:{0}\n    SW1:{1}\n    SW2:{2}".format(rep, hex(sw1), hex(sw2)))

            self.customRespDataForm.delete(0, END)
            self.customRespDataForm.insert(0, rep)
            self.customSW1Form.delete(0, END)
            self.customSW1Form.insert(0, sw1)
            self.customSW2Form.delete(0, END)
            self.customSW2Form.insert(0, sw2)

        except Exception, msg:
            tkMessageBox.showerror("Error: Send", str(msg))
Exemplo n.º 13
0
    def getHighestSign(self, max=100):
        """
        Sign a random number several times (100 by default)
        Keep the highest signature

        @param max: The # of loop. The highest the more accurate is suppose to be the output
        @type max: int <1

        @return: The highest signature
        """

        if not self.isVulnerable():
            raise AATraceabilityException(
                "This passport is not vulnerable for a AA traceability")

        higher = ""
        i = 0
        self.log(
            "Start the internal authentication loop {0} times".format(max))
        while i < max:
            try:
                rnd = os.urandom(8)
                signature = binToHexRep(
                    self._iso7816.internalAuthentication(rnd))
                if signature > higher:
                    higher = signature
            except Iso7816Exception, msg:
                print msg
            i += 1
Exemplo n.º 14
0
    def sign(self, message_to_sign="1122334455667788", mrz_value=None):
        """
        Get the signature of a 64bits message from the reader.
        In order to prevent ICC cloning, the passport implements an Active Authentication (AA) security.
        The passport signs the 64bits message sent by the reader thanks to its Private key stored in secured memory.
        This method lets the user decide the 64bits and checks (if MRZ set) with the public key if the message has been signed properly

        @params message_to_sign: 64bits message to sign
        @type message_to_sign: String (16 HEX values)

        @return: A set composed of (The signature, Boolean that states if the signature has been checked)
        """
        validated = False
        if mrz_value:
            self.log("Validation required")
            self.log("MRZ: {0}".format(mrz_value))
            public_key = self.getPubKey(self._bac, mrz_value)

        message = message_to_sign
        message_bin = hexRepToBin(message)

        signature = self._iso7816.internalAuthentication(message_bin)
        self.log("Signature: {0}".format(binToHexRep(signature)))

        if mrz_value:
            self.log("Check if the signature is correct regarding the public key:")
            data = self._openssl.retrieveSignedData(public_key, signature)
            data_hex = binToHexRep(data)
            header = data_hex[:2]
            self.log("\tHeader: {0}".format(header))
            M1 = data_hex[2:214]
            self.log("\tM1: {0}".format(M1))
            hash_M = data_hex[214:254]
            self.log("\tHash: {0}".format(hash_M))
            trailer = data_hex[254:256]
            self.log("\tTrailer: {0}".format(trailer))

            # If using SHA-1
            if header=='6A' and trailer=='BC':
                M = hexRepToBin(M1 + message)
                new_hash = sha1(M).digest()
                hash_M_bin = hexRepToBin(hash_M)
                if new_hash==hash_M_bin:
                    self.log("hash(M|message to sign) == Hash")
                    validated = True

        return (binToHexRep(signature), validated)
Exemplo n.º 15
0
    def tdesDecrypt(self):
        try:
            tdes = DES3.new(hexRepToBin(self.field2Form.get()), DES.MODE_CBC,
                            b'\x00\x00\x00\x00\x00\x00\x00\x00')
            m = tdes.decrypt(hexRepToBin(self.field1Form.get()))

            self.writeToLog(
                "TDES DECRYPTION:\n  cipher: {0}\n  key: {1}\n  message: {2}".
                format(self.field1Form.get(), self.field2Form.get(),
                       binToHexRep(m)))

            self.field1Form.delete(0, END)
            self.field2Form.delete(0, END)
            self.field1Form.insert(0, binToHexRep(m))

        except Exception, msg:
            tkMessageBox.showerror("Error: BAC", str(msg))
Exemplo n.º 16
0
    def _getPair(self):
        """Get a message with a valid MAC (regarding the derived Kmac from the MRZ)

        @return: A valid binary message/MAC APDU
        """

        self.log("Get a message with a valid MAC")
        self.log("MRZ: " + self._mrz.getMrz())

        self._bac.derivationOfDocumentBasicAccesKeys(self._mrz)
        rnd_icc = self._iso7816.getChallenge()
        self.log("RND.ICC: " + binToHexRep(rnd_icc))
        cmd_data = self._bac.authentication(rnd_icc)
        self.log("The valid pair:" + binToHexRep(cmd_data))
        self.log("RST connection")
        self._iso7816.rstConnection()
        return cmd_data
Exemplo n.º 17
0
    def _getPair(self):
        """Get a message with a valid MAC (regarding the derived Kmac from the MRZ)

        @return: A valid binary message/MAC APDU
        """

        self.log("Get a message with a valid MAC")
        self.log("MRZ: " + self._mrz.getMrz())

        self._bac.derivationOfDocumentBasicAccesKeys(self._mrz)
        rnd_icc = self._iso7816.getChallenge()
        self.log("RND.ICC: " + binToHexRep(rnd_icc))
        cmd_data = self._bac.authentication(rnd_icc)
        self.log("The valid pair:" + binToHexRep(cmd_data))
        self.log("RST connection")
        self._iso7816.rstConnection()
        return cmd_data
Exemplo n.º 18
0
 def genBACKeys(self):
     try:
         if self.mrz.buildMRZ():
             basic_access_control = bac.BAC(self._iso7816)
             mrz_to_send = mrz.MRZ(self.mrz.buildMRZ())
             mrz_to_send.checkMRZ()
             (Kenc, Kmac) = basic_access_control.derivationOfDocumentBasicAccesKeys(mrz_to_send)
             Kenc = binToHexRep(Kenc)
             Kmac = binToHexRep(Kmac)
             self.writeToLog("GENERATE THE BAC KEYS:\n  Kenc: {0}\n  Kmac: {1}".format(Kenc, Kmac))
             self.field1Form.delete(0, END)
             self.field1Form.insert(0, Kenc)
             self.field2Form.delete(0, END)
             self.field2Form.insert(0, Kmac)
         else:
             tkMessageBox.showerror("Error: Generate BAC keys", "You have to set the proper MRZ first")
     except Exception, msg:
         tkMessageBox.showerror("Error: BAC", str(msg))
Exemplo n.º 19
0
    def _sendCmdData(self, cmd_data):
        """
        @note: Code fragment from the pyPassport.doc9303.bac.BAC class
        """
        data = binToHexRep(cmd_data)
        lc = hexToHexRep(len(data)/2)
        toSend = apdu.CommandAPDU("00", "82", "00", "00", lc, data, "28")

        return self._iso7816.transmit(toSend, "Mutual Authentication")
Exemplo n.º 20
0
    def _sendCmdData(self, cmd_data):
        """
        @note: Code fragment from the pyPassport.doc9303.bac.BAC class
        """
        data = binToHexRep(cmd_data)
        lc = hexToHexRep(len(data) / 2)
        toSend = apdu.CommandAPDU("00", "82", "00", "00", lc, data, "28")

        return self._iso7816.transmit(toSend, "Mutual Authentication")
Exemplo n.º 21
0
    def _computeKeysFromKseed(self, Kseed):
        """
        This function is used during the Derivation of Document Basic Acces Keys.

        @param Kseed: A 16 bytes random value
        @type Kseed: Binary
        @return: A set of two 8 bytes encryption keys
        """

        self.log("Input")
        self.log("\tKseed: " + binToHexRep(Kseed))

        self.log("Compute Encryption key (c:" + binToHexRep(BAC.KENC) + ")")
        kenc = self.keyDerivation(Kseed,BAC.KENC)

        self.log("Compute MAC Computation key (c:" + binToHexRep(BAC.KMAC) + ")")
        kmac = self.keyDerivation(Kseed,BAC.KMAC)

        return (kenc, kmac)
Exemplo n.º 22
0
    def authentication(self, rnd_icc, rnd_ifd=None, kifd=None):
        """
		Construct the command data for the mutual authentication.
			- Request an 8 byte random number from the MRTD's chip (rnd.icc)
			- Generate an 8 byte random (rnd.ifd) and a 16 byte random (kifd)
			- Concatenate rnd.ifd, rnd.icc and kifd (s = rnd.ifd + rnd.icc + kifd)
			- Encrypt it with TDES and the Kenc key (eifd = TDES(s, Kenc))
			- Compute the MAC over eifd with TDES and the Kmax key (mifd = mac(pad(eifd))
			- Construct the APDU data for the mutualAuthenticate command (cmd_data = eifd + mifd)
			
		@param rnd_icc: The challenge received from the ICC.
		@type rnd_icc: A 8 bytes binary string
		@return: The APDU binary data for the mutual authenticate command   
		"""

        if self._force_fail == 1:
            rnd_icc = hexToBin(binToHex(rnd_icc) + 1)
        elif self._force_fail == 2:
            self._ksmac = hexToBin(binToHex(self._ksmac) + 1)

        self._rnd_icc = rnd_icc
        self.log("Request an 8 byte random number from the MRTD's chip")
        self.log("\tRND.ICC: " + binToHexRep(self._rnd_icc))

        if not rnd_ifd:
            rnd_ifd = os.urandom(8)
        if not kifd:
            kifd = os.urandom(16)

        self.log("Generate an 8 byte random and a 16 byte random")
        self.log("\tRND.IFD: " + binToHexRep(rnd_ifd))
        self.log("\tRND.Kifd: " + binToHexRep(kifd))

        s = rnd_ifd + self._rnd_icc + kifd
        self.log("Concatenate RND.IFD, RND.ICC and Kifd")
        self.log("\tS: " + binToHexRep(s))

        tdes = DES3.new(self._ksenc, DES.MODE_CBC)
        eifd = tdes.encrypt(s)
        self.log("Encrypt S with TDES key Kenc as calculated in Appendix 5.2")
        self.log("\tEifd: " + binToHexRep(eifd))

        mifd = mac(self._ksmac, pad(eifd))
        self.log(
            "Compute MAC over eifd with TDES key Kmac as calculated in-Appendix 5.2"
        )
        self.log("\tMifd: " + binToHexRep(mifd))
        #Construct APDU

        cmd_data = eifd + mifd
        self.log("Construct command data for MUTUAL AUTHENTICATE")
        self.log("\tcmd_data: " + binToHexRep(cmd_data))

        self._rnd_ifd = rnd_ifd
        self._kifd = kifd

        return cmd_data
Exemplo n.º 23
0
    def sscGenerator(self):
        rnd_icc = hexRepToBin(self.field1Form.get())
        rnd_ifd = hexRepToBin(self.field2Form.get())
        ssc = rnd_icc[-4:] + rnd_ifd[-4:]
        self.writeToLog("SSC GENERATOR:\n  RND ICC: {0}\n  RND IFD: {1}\n  SSC: {2}".format(self.field1Form.get(),
                                                                                            self.field2Form.get(),
                                                                                            binToHexRep(ssc)))

        self.field1Form.delete(0, END)
        self.field2Form.delete(0, END)
        self.field1Form.insert(0, binToHexRep(ssc))
Exemplo n.º 24
0
    def _genKseed(self, kmrz):
        """
        Calculate the kseed from the kmrz:
            - Calculate a SHA-1 hash of the kmrz 
            - Take the most significant 16 bytes to form the Kseed.
        
        @param kmrz: The MRZ information
        @type kmrz: a string
        @return: a 16 bytes string
        """

        self.log("Calculate the SHA-1 hash of MRZ_information")
        kseedhash = sha1(rawbytes(kmrz))
        kseed = kseedhash.digest()
        self.log("\tHsha1(MRZ_information): " + binToHexRep(kseed))

        self.log("Take the most significant 16 bytes to form the Kseed")
        self.log("\tKseed: " + binToHexRep(kseed[:16]))

        return kseed[:16]
Exemplo n.º 25
0
    def _computeKeysFromKseed(self, Kseed):
        """
        This function is used during the Derivation of Document Basic Acces Keys.
        
        @param Kseed: A 16 bytes random value
        @type Kseed: Binary
        @return: A set of two 8 bytes encryption keys
        """

        self.log("Input")
        self.log("\tKseed: " + binToHexRep(Kseed))

        self.log("Compute Encryption key (c:" + binToHexRep(BAC.KENC) + ")")
        kenc = self.keyDerivation(Kseed, BAC.KENC)

        self.log("Compute MAC Computation key (c:" + binToHexRep(BAC.KMAC) +
                 ")")
        kmac = self.keyDerivation(Kseed, BAC.KMAC)

        return (kenc, kmac)
Exemplo n.º 26
0
    def _genKseed(self, kmrz):
        """
        Calculate the kseed from the kmrz:
            - Calculate a SHA-1 hash of the kmrz
            - Take the most significant 16 bytes to form the Kseed.

        @param kmrz: The MRZ information
        @type kmrz: a string
        @return: a 16 bytes string
        """

        self.log("Calculate the SHA-1 hash of MRZ_information")
        kseedhash= sha1(str(kmrz))
        kseed = kseedhash.digest()
        self.log("\tHsha1(MRZ_information): " + binToHexRep(kseed))

        self.log("Take the most significant 16 bytes to form the Kseed")
        self.log("\tKseed: " + binToHexRep(kseed[:16]))

        return kseed[:16]
Exemplo n.º 27
0
 def genBACKeys(self):
     try:
         if self.mrz.buildMRZ():
             basic_access_control = bac.BAC(self._iso7816)
             mrz_to_send = mrz.MRZ(self.mrz.buildMRZ())
             mrz_to_send.checkMRZ()
             (Kenc, Kmac
              ) = basic_access_control.derivationOfDocumentBasicAccesKeys(
                  mrz_to_send)
             Kenc = binToHexRep(Kenc)
             Kmac = binToHexRep(Kmac)
             self.writeToLog(
                 "GENERATE THE BAC KEYS:\n  Kenc: {0}\n  Kmac: {1}".format(
                     Kenc, Kmac))
             self.field1Form.delete(0, END)
             self.field1Form.insert(0, Kenc)
             self.field2Form.delete(0, END)
             self.field2Form.insert(0, Kmac)
         else:
             tkMessageBox.showerror("Error: Generate BAC keys",
                                    "You have to set the proper MRZ first")
     except Exception, msg:
         tkMessageBox.showerror("Error: BAC", str(msg))
Exemplo n.º 28
0
    def tdesDecrypt(self):
        try:
            tdes= DES3.new(hexRepToBin(self.field2Form.get()), DES.MODE_CBC, b'\x00\x00\x00\x00\x00\x00\x00\x00')
            m = tdes.decrypt(hexRepToBin(self.field1Form.get()))

            self.writeToLog("TDES DECRYPTION:\n  cipher: {0}\n  key: {1}\n  message: {2}".format(self.field1Form.get(),
                                                                                                 self.field2Form.get(),
                                                                                                 binToHexRep(m)))

            self.field1Form.delete(0, END)
            self.field2Form.delete(0, END)
            self.field1Form.insert(0, binToHexRep(m))

        except Exception, msg:
            tkMessageBox.showerror("Error: BAC", str(msg))
Exemplo n.º 29
0
    def authentication(self, rnd_icc, rnd_ifd=None, kifd=None):
        """
        Construct the command data for the mutual authentication.
            - Request an 8 byte random number from the MRTD's chip (rnd.icc)
            - Generate an 8 byte random (rnd.ifd) and a 16 byte random (kifd)
            - Concatenate rnd.ifd, rnd.icc and kifd (s = rnd.ifd + rnd.icc + kifd)
            - Encrypt it with TDES and the Kenc key (eifd = TDES(s, Kenc))
            - Compute the MAC over eifd with TDES and the Kmax key (mifd = mac(pad(eifd))
            - Construct the APDU data for the mutualAuthenticate command (cmd_data = eifd + mifd)

        @param rnd_icc: The challenge received from the ICC.
        @type rnd_icc: A 8 bytes binary string
        @return: The APDU binary data for the mutual authenticate command
        """
        self._rnd_icc = rnd_icc
        self.log("Request an 8 byte random number from the MRTD's chip")
        self.log("\tRND.ICC: " + binToHexRep(self._rnd_icc))

        if not rnd_ifd:
            rnd_ifd = os.urandom(8)
        if not kifd:
            kifd = os.urandom(16)

        self.log("Generate an 8 byte random and a 16 byte random")
        self.log("\tRND.IFD: " + binToHexRep(rnd_ifd))
        self.log("\tRND.Kifd: " + binToHexRep(kifd))

        s = rnd_ifd + self._rnd_icc + kifd
        self.log("Concatenate RND.IFD, RND.ICC and Kifd")
        self.log("\tS: " + binToHexRep(s))

        tdes= DES3.new(self._ksenc,DES.MODE_CBC, b'\x00\x00\x00\x00\x00\x00\x00\x00')
        eifd= tdes.encrypt(s)
        self.log("Encrypt S with TDES key Kenc as calculated in Appendix 5.2")
        self.log("\tEifd: " + binToHexRep(eifd))

        mifd = mac(self._ksmac, pad(eifd))
        self.log("Compute MAC over eifd with TDES key Kmac as calculated in-Appendix 5.2")
        self.log("\tMifd: " + binToHexRep(mifd))
        #Construct APDU

        cmd_data = eifd + mifd
        self.log("Construct command data for MUTUAL AUTHENTICATE")
        self.log("\tcmd_data: " + binToHexRep(cmd_data))

        self._rnd_ifd = rnd_ifd
        self._kifd = kifd

        return cmd_data
Exemplo n.º 30
0
    def getModulo(self, mrz_value):
        """
        If an attacker eavesdrops a legitimate communication between a passport and a reader
        it is possible to get the public key used during the AA

        @param mrz_value: A MRZ
        @type mrz_value: String value ("PPPPPPPPPPcCCCYYMMDDcSYYMMDDc<<<<<<<<<<<<<<cd")

        @return: The modulo from the public key
        """

        pub_key = self._getPubKey(mrz_value)
        pub_key_hex = binToHexRep(pub_key)
        self.log("Public key: {0}".format(pub_key_hex))
        modulo = pub_key_hex[58:314]
        self.log("Modulo: {0}".format(modulo))
        return modulo
Exemplo n.º 31
0
    def getModulo(self, mrz_value):
        """
        If an attacker eavesdrops a legitimate communication between a passport and a reader
        it is possible to get the public key used during the AA

        @param mrz_value: A MRZ
        @type mrz_value: String value ("PPPPPPPPPPcCCCYYMMDDcSYYMMDDc<<<<<<<<<<<<<<cd")

        @return: The modulo from the public key
        """

        pub_key = self._getPubKey(mrz_value)
        pub_key_hex = binToHexRep(pub_key)
        self.log("Public key: {0}".format(pub_key_hex))
        modulo = pub_key_hex[58:314]
        self.log("Modulo: {0}".format(modulo))
        return modulo
Exemplo n.º 32
0
    def keyDerivation(self):

        keyBin = hexRepToBin(self.field1Form.get())
        h = sha1(str(keyBin)).digest()

        Ka = h[:8]
        Kb = h[8:16]

        Ka = self.DESParity(Ka)
        Kb = self.DESParity(Kb)

        key = binToHexRep(Ka+Kb)

        self.writeToLog("KEY DERIVATION:\n  key: {0}\n  derived key: {1}".format(self.field1Form.get(),
                                                                          key))
        self.field1Form.delete(0, END)
        self.field2Form.delete(0, END)
        self.field1Form.insert(0, key)
Exemplo n.º 33
0
    def sendCustom(self, cla="00", ins="00", p1="00", p2="00", lc="", data="", le="00"):
        """
        Send custom APDU in order to trigger errors.

        @param cla, ins, p1, p2, lc, data, le: APDU value
        @type cla, ins, p1, p2, lc, data, le: String of 2hex (from 00 to FF) except lc and date that may be an empty String

        @return: A set composed of boolean (True=Succeed, False=Error) and a passport answer
        """

        toSend = apdu.CommandAPDU(cla, ins, p1, p2, lc, data, le)

        try:
            self.log("Send APDU: {0}:{1}:{2}:{3}:{4}:{5}:{6}".format(cla, ins, p1, p2, lc, data, le))
            ans = self._iso7816.transmit(toSend, "Custom APDU")
            return (True, binToHexRep(ans))
        except Iso7816Exception, msg:
            return (False, msg)
Exemplo n.º 34
0
    def keyDerivation(self):

        keyBin = hexRepToBin(self.field1Form.get())
        h = sha1(str(keyBin)).digest()

        Ka = h[:8]
        Kb = h[8:16]

        Ka = self.DESParity(Ka)
        Kb = self.DESParity(Kb)

        key = binToHexRep(Ka + Kb)

        self.writeToLog(
            "KEY DERIVATION:\n  key: {0}\n  derived key: {1}".format(
                self.field1Form.get(), key))
        self.field1Form.delete(0, END)
        self.field2Form.delete(0, END)
        self.field1Form.insert(0, key)
Exemplo n.º 35
0
    def _sendPair(self, cmd_data="\x55" * 40):
        """Send a message/MAC.
        If the cmd_data is not set, it sends a random pair in order to make sure the MAC check fails
        If set, a wrong message is sent together with a valid MAC in order to pass the MAC check

        @param cmd_data: pair to send
        @type cmd_data: a string of the raw data to send

        @return: The response time together with error message
        """
        self._iso7816.getChallenge()

        data = binToHexRep(cmd_data)
        self.log("Send a message with a wrong MAC")
        self.log("Message/MAC:" + data)
        lc = hexToHexRep(len(data) / 2)
        toSend = apdu.CommandAPDU("00", "82", "00", "00", lc, data, "28")
        starttime = time.time()
        try:
            response = self._iso7816.transmit(toSend, "Wrong MAC")
        except Iso7816Exception, msg:
            response = msg
Exemplo n.º 36
0
    def _sendPair(self, cmd_data="\x55" * 40):
        """Send a message/MAC.
        If the cmd_data is not set, it sends a random pair in order to make sure the MAC check fails
        If set, a wrong message is sent together with a valid MAC in order to pass the MAC check

        @param cmd_data: pair to send
        @type cmd_data: a string of the raw data to send

        @return: The response time together with error message
        """
        self._iso7816.getChallenge()

        data = binToHexRep(cmd_data)
        self.log("Send a message with a wrong MAC")
        self.log("Message/MAC:" + data)
        lc = hexToHexRep(len(data) / 2)
        toSend = apdu.CommandAPDU("00", "82", "00", "00", lc, data, "28")
        starttime = time.time()
        try:
            response = self._iso7816.transmit(toSend, "Wrong MAC")
        except Iso7816Exception, msg:
            response = msg
Exemplo n.º 37
0
    def send(self):
        try:
            self.initIso7816()

            cla = self.customCLAForm.get()
            ins = self.customINSForm.get()
            p1 = self.customP1Form.get()
            p2 = self.customP2Form.get()
            lc = self.customLCForm.get()
            data = self.customDATAForm.get()
            le = self.customLEForm.get()

            if not lc:
                if data:
                    lc = hexToHexRep(len(data) / 2)

            toSend = apdu.CommandAPDU(cla, ins, p1, p2, lc, data, le)

            ans = self._iso7816.transmitRaw(toSend)
            rep = binToHexRep(ans.res)
            sw1 = ans.sw1
            sw2 = ans.sw2
            self.writeToLog(
                "REQUEST:\n  APDU: CLA:{0} INS:{1} P1:{2} P2:{3} LC:{4} DATA:{5} LE:{6}"
                .format(cla, ins, p1, p2, lc, data, le))
            self.writeToLog(
                "RESPONSE:\n  APDU:\n    Data:{0}\n    SW1:{1}\n    SW2:{2}".
                format(rep, hex(sw1), hex(sw2)))

            self.customRespDataForm.delete(0, END)
            self.customRespDataForm.insert(0, rep)
            self.customSW1Form.delete(0, END)
            self.customSW1Form.insert(0, sw1)
            self.customSW2Form.delete(0, END)
            self.customSW2Form.insert(0, sw2)

        except Exception, msg:
            tkMessageBox.showerror("Error: Send", str(msg))
Exemplo n.º 38
0
    def keyDerivation(self, kseed, c):
        """
        Key derivation from the kseed:
            - Concatenate Kseed and c (c=0 for KENC or c=1 for KMAC)
            - Calculate the hash of the concatenation of kseed and c (h = (sha1(kseed + c)))
            - Adjust the parity bits
            - return the key (The first 8 bytes are Ka and the next 8 bytes are Kb)

        @param kseed: The Kseed
        @type kseed: a 16 bytes string
        @param c: specify if it derives KENC (c=0) of KMAC (c=1)
        @type c: a byte
        @return: Return a 16 bytes key
        """

        if c not in (BAC.KENC,BAC.KMAC):
            raise BACException, "Bad parameter (c=0 or c=1)"

        d = kseed + c
        self.log("\tConcatenate Kseed and c")
        self.log("\t\tD: " + binToHexRep(d))

        h = sha1(str(d)).digest()
        self.log("\tCalculate the SHA-1 hash of D")
        self.log("\t\tHsha1(D): " + binToHexRep(h))

        Ka = h[:8]
        Kb = h[8:16]

        self.log("\tForm keys Ka and Kb")
        self.log("\t\tKa: " + binToHexRep(Ka))
        self.log("\t\tKb: " + binToHexRep(Kb))

        Ka = self.DESParity(Ka)
        Kb = self.DESParity(Kb)

        self.log("\tAdjust parity bits")
        self.log("\t\tKa: " + binToHexRep(Ka))
        self.log("\t\tKb: " + binToHexRep(Kb))

        return Ka+Kb
Exemplo n.º 39
0
    def keyDerivation(self, kseed, c):
        """
        Key derivation from the kseed:
            - Concatenate Kseed and c (c=0 for KENC or c=1 for KMAC) 
            - Calculate the hash of the concatenation of kseed and c (h = (sha1(kseed + c)))
            - Adjust the parity bits
            - return the key (The first 8 bytes are Ka and the next 8 bytes are Kb)
            
        @param kseed: The Kseed
        @type kseed: a 16 bytes string
        @param c: specify is it derives KENC (c=0) of KMAC (c=1)
        @type c: a byte
        @return: Return a 16 bytes key
        """

        if c not in (BAC.KENC, BAC.KMAC):
            raise BACException, "Bad parameter (c=0 or c=1)"

        d = kseed + c
        self.log("\tConcatenate Kseed and c")
        self.log("\t\tD: " + binToHexRep(d))

        h = sha1(str(d)).digest()
        self.log("\tCalculate the SHA-1 hash of D")
        self.log("\t\tHsha1(D): " + binToHexRep(h))

        Ka = h[:8]
        Kb = h[8:16]

        self.log("\tForm keys Ka and Kb")
        self.log("\t\tKa: " + binToHexRep(Ka))
        self.log("\t\tKb: " + binToHexRep(Kb))

        Ka = self.DESParity(Ka)
        Kb = self.DESParity(Kb)

        self.log("\tAdjust parity bits")
        self.log("\t\tKa: " + binToHexRep(Ka))
        self.log("\t\tKb: " + binToHexRep(Kb))

        return Ka + Kb
Exemplo n.º 40
0
 def _mutualAuthentication(self, cmd_data):
     data = binToHexRep(cmd_data)
     lc = hexToHexRep(len(data)/2)
     toSend = apdu.CommandAPDU("00", "82", "00", "00", lc, data, "28")
     return self._iso7816.transmit(toSend, "Mutual Authentication")
Exemplo n.º 41
0
    def _mutualAuthentication(self, cmd_data):
        data = binToHexRep(cmd_data)
        lc = hexToHexRep(len(data) / 2)
        toSend = apdu.CommandAPDU("00", "82", "00", "00", lc, data, "28")

        return self._iso7816.transmit(toSend, "Mutual Authentication")
Exemplo n.º 42
0
 def _xor(self, kifd, response_kicc):
     kseed = ""
     for i in range(len(binToHexRep(kifd))):
         kseed += hex(int(binToHexRep(kifd)[i],16) \
                      ^ int(binToHexRep(response_kicc)[i],16))[2:]
     return hexRepToBin(kseed)
Exemplo n.º 43
0
 def _xor(self, kifd, response_kicc):
     kseed = ""
     for i in range(len(binToHexRep(kifd))):
         kseed += hex(int(binToHexRep(kifd)[i],16) \
                      ^ int(binToHexRep(response_kicc)[i],16))[2:]
     return hexRepToBin(kseed)