Esempio n. 1
0
    def generate_key(self, request):
        """
        Get response to HC command
        TODO: generating keys for different schemes
        """
        response = OutgoingMessage(data=None, header=self.header)
        response.set_response_code('HD')
        response.set_error_code('00')

        new_clear_key = modify_key_parity(bytes(os.urandom(16)))
        self._debug_trace('Generated key: {}'.format(raw2str(new_clear_key)))

        current_key = request.get('Current Key')
        if current_key[0:1] in [b'U']:
            current_key = current_key[1:]

        clear_current_key = self.cipher.decrypt(B2raw(current_key))
        curr_key_cipher = DES3.new(clear_current_key, DES3.MODE_ECB)

        new_key_under_current_key = curr_key_cipher.encrypt(new_clear_key)
        new_key_under_lmk = self.cipher.encrypt(new_clear_key)

        response.set('New key under the current key',
                     b'U' + raw2B(new_key_under_current_key))
        response.set('New key under LMK', b'U' + raw2B(new_key_under_lmk))

        return response
Esempio n. 2
0
 def info(self):
     """
     """
     dump = ''
     dump += 'LMK: {}\n'.format(raw2str(self.LMK))
     dump += 'Firmware version: {}\n'.format(self.firmware_version)
     if self.header:
         dump += 'Message header: {}\n'.format(self.header.decode('utf-8'))
     return dump
Esempio n. 3
0
    def __init__(self,
                 host=None,
                 port=None,
                 id=None,
                 merchant=None,
                 master_key=None,
                 terminal_key=None,
                 show_keys=None):
        """
        Terminal initialization
        """
        self.pinblock_format = '01'

        # Host to connect to
        self.host = host if host else '127.0.0.1'

        # Port ot connect to
        try:
            self.port = int(port) if port else 1337
        except ValueError:
            raise ValueError('Invalid TCP port: {}'.format(port))

        # Terminal ID
        self.terminal_id = id if id else '10001337'

        # Merchant ID
        self.merchant_id = merchant if merchant else '999999999999001'

        self.currency = '643'
        self.country_code = '643'

        # Keys
        self.keyfile_name = '.terminalkey.cache'
        self.master_key = bytes.fromhex(
            master_key) if master_key else bytes.fromhex(
                'CF7730DBA6CAC5E13C3FB45CAF8D71E1')

        if terminal_key:
            self.terminal_key = bytes.fromhex(terminal_key)
        else:
            stored_key = self.get_stored_key()
            if stored_key:
                self.terminal_key = bytes.fromhex(stored_key)
            else:
                self.terminal_key = bytes.fromhex(
                    'FA9F90D49CB27B7D14A3FA9CCCFF6CB7')
                self.store_terminal_key(raw2str(self.terminal_key))

        self.tpk_cipher = DES3.new(self.terminal_key, DES3.MODE_ECB)
        self.tmk_cipher = DES3.new(self.master_key, DES3.MODE_ECB)

        self.show_keys = show_keys
        self.print_keys()
Esempio n. 4
0
    def translate_zpk(self, request):
        """
        Get response to FA command
        """
        response = OutgoingMessage(header=self.header)
        response.set_response_code('FB')
        response.set_error_code('00')

        zmk_under_lmk = request.get('ZMK')[1:33]
        if zmk_under_lmk:
            clear_zmk = self.cipher.decrypt(B2raw(zmk_under_lmk))
            self._debug_trace('Clear ZMK: {}'.format(raw2str(clear_zmk)))

            zmk_key_cipher = DES3.new(clear_zmk, DES3.MODE_ECB)

            zpk_under_zmk = request.get('ZPK')[1:33]
            if zpk_under_zmk:
                clear_zpk = zmk_key_cipher.decrypt(B2raw(zpk_under_zmk))
                self._debug_trace('Clear ZPK: {}'.format(raw2str(clear_zpk)))

                zpk_under_lmk = self.cipher.encrypt(clear_zpk)

                response.set('ZPK under LMK', b'U' + raw2B(zpk_under_lmk))
                response.set('Key Check Value', key_CV(raw2B(zpk_under_lmk),
                                                       6))
                response.set_error_code('00')

            else:
                self._debug_trace('ERROR: Invalid ZPK')
                response.set_error_code('01')

        else:
            self._debug_trace('ERROR: Invalid ZMK')
            response.set_error_code('01')

        return response
Esempio n. 5
0
    def get_encrypted_pin(self, clear_pin, card_number):
        """
        Get PIN block in ISO 0 format, encrypted with the terminal key
        """
        if not self.terminal_key:
            print('Terminal key is not set')
            return ''

        if self.pinblock_format == '01':
            try:
                pinblock = bytes.fromhex(get_pinblock(clear_pin, card_number))
                #print('PIN block: {}'.format(raw2str(pinblock)))
            except TypeError:
                return ''

            encrypted_pinblock = self.tpk_cipher.encrypt(pinblock)
            return raw2str(encrypted_pinblock)

        else:
            print('Unsupported PIN Block format')
            return ''
Esempio n. 6
0
    def generate_key_a0(self, request):
        """
        Get response to A0 command
        """
        response = OutgoingMessage(header=self.header)
        response.set_response_code('A1')
        response.set_error_code('00')

        new_clear_key = modify_key_parity(bytes(os.urandom(16)))
        self._debug_trace('Generated key: {}'.format(raw2str(new_clear_key)))
        new_key_under_lmk = self.cipher.encrypt(new_clear_key)
        response.set('Key under LMK', b'U' + raw2B(new_key_under_lmk))

        zmk_under_lmk = request.get('ZMK/TMK')[1:33]
        if zmk_under_lmk:
            clear_zmk = self.cipher.decrypt(B2raw(zmk_under_lmk))
            zmk_key_cipher = DES3.new(clear_zmk, DES3.MODE_ECB)
            new_key_under_zmk = zmk_key_cipher.encrypt(new_clear_key)

            response.set('Key under ZMK', b'U' + raw2B(new_key_under_zmk))
            response.set('Key Check Value', key_CV(raw2B(new_clear_key), 6))

        return response
Esempio n. 7
0
    def set_terminal_key(self, encrypted_key):
        """
        Change the terminal key. The encrypted_key is a hex string.
        encrypted_key is expected to be encrypted under master key
        """
        if encrypted_key:
            try:
                new_key = bytes.fromhex(encrypted_key)
                if len(self.terminal_key) != len(new_key):
                    # The keys must have equal length
                    return False

                self.terminal_key = self.tmk_cipher.decrypt(new_key)
                self.store_terminal_key(raw2str(self.terminal_key))

                self.tpk_cipher = DES3.new(self.terminal_key, DES3.MODE_ECB)
                self.print_keys()
                return True

            except ValueError:
                return False

        return False
Esempio n. 8
0
 def test_raw2str(self):
     self.assertEqual(raw2str(b'\xdf\x12g\xee\xdc\xba\x98v'),
                      'DF1267EEDCBA9876')
Esempio n. 9
0
 def print_keys(self):
     if self.show_keys:
         print('  Master key: {}'.format(raw2str(self.master_key)))
         print('Terminal key: {}'.format(raw2str(self.terminal_key)))
Esempio n. 10
0
 def get_terminal_key(self):
     """
     Get string representation of terminal key (needed mostly for debugging purposes)
     """
     return raw2str(self.terminal_key)