def command_KQ(cmdObj): """ ARQC (or TC/AAC) Verification and/or ARPC Generation. """ """ Command Pattern: request: Message header + 'KQ' + Mode Flag + Scheme ID + MK-AC + Primary Account Number + Application Transaction Counter + Unpredictable Number + Transaction Data Length + Transaction Data + Delimiter(;) + ARQC + Authorization Response Code + End message delimiter + Message Trailer response: Message header + 'KR' + Error code + ARPC + End Message delimiter + Message Trailer """ if len(cmdObj.MK_AC.value) != 32: raise ValueError('MK-AC length error') if cmdObj.MK_AC.scheme == '': MK_AC = decryptKeyUnderLMK('MK-AC', unhexlify(cmdObj.MK_AC.value)) else: MK_AC = decryptKeyUnderLMK('MK-AC', unhexlify(cmdObj.MK_AC.value), cmdObj.MK_AC.scheme) # Transaction Data最后有一个分隔符 sessionKey = icSessionKey(icKeyDerivation(MK_AC, hexlify(cmdObj.PAN.value), ''), cmdObj.ATC.value) resp_cd = '00' if cmdObj.ModeFlag.value == '0' or cmdObj.ModeFlag.value == '1': block = padDataBlock(cmdObj.TransactionData.value) ac = calcMAC(sessionKey, block, '\x00'*8) if ac == cmdObj.ARQC.value: resp_cd = '00' else: resp_cd = '01' respObj = CommandObj() respObj.ResponseCode = DataVariable(resp_cd) if cmdObj.ModeFlag.value == '1' or cmdObj.ModeFlag.value == '2': k = pyDes.triple_des(sessionKey) arpc = k.encrypt(blockXOR(cmdObj.ARQC.value, cmdObj.ARC.value+'\x00\x00\x00\x00\x00\x00')) respObj.ARPC = DataVariable(arpc) else: respObj.ARPC = DataVariable('') return respObj
def command_DA(cmdObj): """ Verify a PIN from a local ATM (or PIN pad etc.) using the IBM 3624 method. """ """ Command Pattern: request: Message header + 'EA' + TPK + PVK + Max PIN Length + PIN Block + PIN Block Format Code + Check length + Account Number + Decimalization Table + PIN Validation data + Offset + End message delimiter + Message Trailer response: Message header + 'EB' + Error code + End Message delimiter + Message Trailer """ TPK = decryptKeyUnderLMK('TPK', unhexlify(cmdObj.TPK.value), cmdObj.TPK.scheme) tpk = KeyScheme(TPK) pinblock = tpk.decrypt(unhexlify(cmdObj.PINBlock.value)) enteredPIN = extractPINFromPINBlock(pinblock, cmdObj.AccountNumber.value, cmdObj.PINBlockFormatCode.value) if (len(enterdPIN) > string.atoi(cmdObj.MaxPINLength.value)): raise ValueError('invalid pin length') PVK = decryptKeyUnderLMK('PVK', unhexlify(cmdObj.PVK.value), cmdObj.PVK.scheme) derivedPIN = genPINUsingIBMMetheod(PVK, cmdObj.AccountNumber.value, cmdObj.PINValidationData.value, cmdObj.DecimalizationTable.value) print "PIN=", derivedPIN finalPIN = genFinalPIN(derivedPIN, cmdObj.Offset.value) respObj = CommandObj() if (enteredPIN == finalPIN): respObj.ResponseCode = DataVariable('00') else: respObj.ResponseCode = DataVariable('01') return respObj
def command_A0(cmdObj): """ To generate a key and optionally encrypt key under ZMK for transmission.""" """ Command Pattern: request: Message header + 'A0' + Mode + Key Type + Key Scheme LMK + ZMK + Key Scheme ZMK + Atalla Variant + End message delimiter + Message Trailer response: Message header + 'A1' + Error code + Key under LMK + Key under ZMK + Check Value + End Message delimiter + Message Trailer """ clearKey = genRandomKey(Configure.CFG_KEY_LENGTH / 2) keyType = Configure.KeyTypeTable[cmdObj.KeyType.value] cipherKeyUnderLMK = encryptKeyUnderLMK(keyType, clearKey, cmdObj.KeySchemeLMK.value) if cmdObj.Mode.value == '1': ZMK = decryptKeyUnderLMK('ZMK', unhexlify(cmdObj.ZMK.value), cmdObj.ZMK.scheme) zmkScheme = KeyScheme(ZMK, cmdObj.KeySchemeZMK.value) cipherKeyUnderZMK = zmkScheme.encrypt(clearKey) key = KeyScheme(clearKey) kcv = hexlify(key.encrypt("\0\0\0\0\0\0\0\0")).upper() respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.KeyUnderLMK = KeyVariable( hexlify(cipherKeyUnderLMK).upper(), cmdObj.KeySchemeLMK.value) if cmdObj.Mode.value == '1': respObj.KeyUnderZMK = KeyVariable( hexlify(cipherKeyUnderZMK).upper(), cmdObj.KeySchemeZMK.value) else: respObj.KeyUnderZMK = DataVariable('') respObj.CheckValue = DataVariable(kcv[:6]) return respObj
def command_IA(cmdObj): """ Generate a random PIN key and return it to the Host encrypted under a ZMK for transmission to another party and under the LMK for storage on the Host database.""" """ Command Pattern: request: Message header + 'IA' + ZMK + Atalla Variant + Delimiter + Key Scheme ZMK + Key Scheme LMK + Key Check Value Type + End message delimiter + Message Trailer response: Message header + 'IB' + Error code + ZPK under ZMK + ZPK under LMK + Check Value + End Message delimiter + Message Trailer """ (schemeZMK, schemeLMK, kcvLength) = extractKeySchemeAndKcvLength(cmdObj) clearZPK = genRandomKey(Configure.CFG_KEY_LENGTH / 2) ZMK = decryptKeyUnderLMK('ZMK', unhexlify(cmdObj.ZMK.value), cmdObj.ZMK.scheme) cipherZPKUnderLMK = encryptKeyUnderLMK('ZPK', clearZPK, schemeLMK) zmkScheme = KeyScheme(ZMK, schemeZMK) cipherZPKUnderZMK = zmkScheme.encrypt(clearZPK) zpk = KeyScheme(clearZPK) kcv = hexlify(zpk.encrypt("\0\0\0\0\0\0\0\0")).upper() respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.ZPKUnderZMK = KeyVariable( hexlify(cipherZPKUnderZMK).upper(), schemeZMK) respObj.ZPKUnderLMK = KeyVariable( hexlify(cipherZPKUnderLMK).upper(), schemeLMK) respObj.CheckValue = DataVariable(kcv[:kcvLength]) return respObj
def command_MQ(cmdObj): """ Generate a MAC (MAB) for a large message. """ """ Command Pattern: request: Message header + 'MQ' + Message Block Number + TAK + IV + Message Length + Message Block + End message delimiter + Message Trailer response: Message header + 'MR' + Error code + MAB + End Message delimiter + Message Trailer """ TAK = decryptKeyUnderLMK('TAK', unhexlify(cmdObj.TAK.value), cmdObj.TAK.scheme) if (cmdObj.MessageBlockNumber.value == '0'): # The only block. mac = calcMAC(TAK, cmdObj.MessageBlock.value, "\0\0\0\0\0\0\0\0") elif (cmdObj.MessageBlockNumber.value == '1'): # The first block. mac = calcMAC(TAK, cmdObj.MessageBlock.value, "\0\0\0\0\0\0\0\0") elif (cmdObj.MessageBlockNumber.value == '2'): # A middle block. mac = calcMAC(TAK, cmdObj.MessageBlock.value, unhexlify(cmdObj.IV.value)) elif (cmdObj.MessageBlockNumber.value == '3'): # The last block. mac = calcMAC(TAK, cmdObj.MessageBlock.value, unhexlify(cmdObj.IV.value)) else: raise ValueError('invalid message block number [' + cmdObj.MessageBlockNumber.value + ']') respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.MAB = DataVariable(string.upper(hexlify(mac))) return respObj
def command_FE(cmdObj): """ Translate a TMK, TPK or PVK from encryption under the LMK to encryption under a ZMK. """ """ Command Pattern: request: Message header + 'FE' + ZMK + TMK_TPK_PVK + Atalla Variant + Delimiter + Key Scheme ZMK + Key Scheme LMK + Key Check Value Type + End message delimiter + Message Trailer response: Message header + 'FF' + Error code + TMK_TPK_PVK + Check Value + End Message delimiter + Message Trailer """ (schemeZMK, schemeLMK, kcvLength) = extractKeySchemeAndKcvLength(cmdObj) ZMK = decryptKeyUnderLMK('ZMK', unhexlify(cmdObj.ZMK.value), cmdObj.ZMK.scheme) clearTMK_TPK_PVK = decryptKeyUnderLMK('PVK', unhexlify(cmdObj.TMK_TPK_PVK.value), cmdObj.TMK_TPK_PVK.scheme) zmkScheme = KeyScheme(ZMK, schemeZMK) cipherTMK_TPK_PVK = zmkScheme.encrypt(clearTMK_TPK_PVK) tmk_tpk_pvk = KeyScheme(clearTMK_TPK_PVK) kcv = hexlify(tmk_tpk_pvk.encrypt("\0\0\0\0\0\0\0\0")).upper() respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.TMK_TPK_PVK = KeyVariable( hexlify(cipherTMK_TPK_PVK).upper(), schemeZMK) respObj.CheckValue = DataVariable(kcv[:kcvLength]) return respObj
def command_JE(cmdObj): """ Translate a PIN from encryption under a ZPK to encryption under the LMK. """ """ Command Pattern: request: Message header + 'JE' + ZPK + PIN Block + PIN Block Format Code + Account Number + End message delimiter + Message Trailer response: Message header + 'JF' + Error code + PIN + End Message delimiter + Message Trailer """ respObj = CommandObj() ZPK = decryptKeyUnderLMK('ZPK', unhexlify(cmdObj.ZPK.value), cmdObj.ZPK.scheme) zpk = KeyScheme(ZPK) pinblock = zpk.decrypt(unhexlify(cmdObj.PINBlock.value)) (clearPIN, rslt) = extrackPINFromPINBlock(pinblock, cmdObj.AccountNumber.value, cmdObj.PINBlockFormatCode.value) if rslt != '00': respObj.ResponseCode = DataVariable(rslt) return respObj print "clearPIN=", clearPIN if (len(clearPIN) < 4) or (len(clearPIN) > 12): respObj.ResponseCode = DataVariable('24') return respObj cipherPIN = encryptPINUnderLMK(clearPIN, cmdObj.AccountNumber.value) respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.PIN = DataVariable(cipherPIN) return respObj
def command_KU(cmdObj): """ Generate Secure Message with Integrity and Optional Confidentiality and PIN Change """ """ Command Pattern: request: Message header + 'KU' + Mode Flag + Scheme ID + MK-SMI + Primary Account Number + Integrity Session Data + Plaintext Data Length + Plaintext Data + Delimiter(;) + MK-SMC + TK + Confidentiality Session Data + Offset + Cipher Data Length + Cipher Data + Delimiter(;) + Source PIN Encryption Key Type + Source PIN Encryption Key + Source PIN Block Format + Destination PIN Block Format + Primary Account Number + MK-AC + End message delimiter + Message Trailer response: Message header + 'KV' + Error code + ARPC + End Message delimiter + Message Trailer """ if len(cmdObj.MK_SMI.value) != 32: raise ValueError('MK-SMI length error') if cmdObj.MK_SMI.scheme == '': MK_SMI = decryptKeyUnderLMK('MK-SMI', unhexlify(cmdObj.MK_SMI.value)) else: MK_SMI = decryptKeyUnderLMK('MK-SMI', unhexlify(cmdObj.MK_SMI.value), cmdObj.MK_SMI.scheme) # Plain Data最后有一个分隔符 atc = cmdObj.IntegritySessionData.value[-2:] sessionKey = icSessionKey(icKeyDerivation(MK_SMI, hexlify(cmdObj.PAN.value), ''), atc) block = padDataBlock(cmdObj.PlainData.value) mac = calcMAC(sessionKey, block, '\x00'*8) respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.MAC = DataVariable(mac) return respObj
def command_HA(cmdObj): """ Generate a random key, and encrypt it under a TMK (TPK or PVK) and under LMK pair 16-17. """ """ Command Pattern: request: Message header + 'HA' + TMK + Atalla Variant + Delimiter + Key Scheme TMK + Key Scheme LMK + Key Check Value Type + End message delimiter + Message Trailer response: Message header + 'HB' + Error code + ZPK under ZMK + ZPK under LMK + Check Value + End Message delimiter + Message Trailer """ (schemeTMK, schemeLMK, kcvLength) = extractTMKSchemeAndKcvLength(cmdObj) clearZPK = genRandomKey(Configure.CFG_KEY_LENGTH / 2) TMK = decryptKeyUnderLMK('TMK', unhexlify(cmdObj.TMK.value), cmdObj.TMK.scheme) cipherTAKUnderLMK = encryptKeyUnderLMK('TAK', clearTAK, schemeLMK) tmkScheme = KeyScheme(TMK, schemeTMK) cipherTAKUnderTMK = tmkScheme.encrypt(clearTAK) tak = KeyScheme(clearTAK) kcv = hexlify(tak.encrypt("\0\0\0\0\0\0\0\0")).upper() respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.TAKUnderTMK = KeyVariable( hexlify(cipherTAKUnderTMK).upper(), schemeTMK) respObj.TAKUnderLMK = KeyVariable( hexlify(cipherTAKUnderLMK).upper(), schemeLMK) respObj.CheckValue = DataVariable(kcv[:kcvLength]) return respObj
def command_CC(cmdObj): """ Translate a PIN block from encryption under one ZPK to encryption under another ZPK and from one format to another. If the same ZPK is defined, only the PIN block is translated, and if the same PIN block format is defined, only the key is translated. """ """ Command Pattern: request: Message header + 'CC' + Source ZPK + Destination ZPK + Maximum PIN Length + Source PIN Block + Source PIN Block Format + Destination PIN Block Format + Account Number + End message delimiter + Message Trailer response: Message header + 'CD' + Error code + PIN Length + Destination PIN Block + Destination PIN Block Format + End Message delimiter + Message Trailer """ SourceZPK = decryptKeyUnderLMK('ZPK', unhexlify(cmdObj.SourceZPK.value), cmdObj.SourceZPK.scheme) src_zpk = KeyScheme(SourceZPK) DestinationZPK = decryptKeyUnderLMK('ZPK', unhexlify(cmdObj.DestinationZPK.value), cmdObj.DestinationZPK.scheme) dst_zpk = KeyScheme(DestinationZPK) src_pinblock = src_zpk.decrypt(unhexlify(cmdObj.SourcePINBlock.value)) (clearPIN, rlt) = extrackPINFromPINBlock(src_pinblock, cmdObj.AccountNumber.value, cmdObj.SourcePINBlockFormat.value) print "clearPIN=" + clearPIN dst_pinblock = genPINBlock(clearPIN, cmdObj.AccountNumber.value, cmdObj.DestinationPINBlockFormat.value) dst_pinblock = hexlify(dst_zpk.encrypt(dst_pinblock)) respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.PINLength = DataVariable("%02d" % len(clearPIN)) respObj.DestinationPINBlock = DataVariable(string.upper(dst_pinblock)) respObj.DestinationPINBlockFormat = DataVariable( cmdObj.DestinationPINBlockFormat.value) return respObj
def command_FI(cmdObj): """ Generate a ZEK or ZAK. """ """ Command Pattern: request: Message header + 'FI' + Flag + ZMK + Atalla Variant + Delimiter + Key Scheme ZMK + Key Scheme LMK + Key Check Value Type + End message delimiter + Message Trailer response: Message header + 'FI' + Error code + ZEK/ZAK under ZMK + ZEK/ZAK under LMK + Check Value + End Message delimiter + Message Trailer """ if cmdObj.Flag == '0': keyType = 'ZEK' elif cmdObj.Flag == '1': keyType = 'ZAK' else: raise ValueError('ZEK/ZAK Flag error') (schemeZMK, schemeLMK, kcvLength) = extractKeySchemeAndKcvLength(cmdObj) clearZEK_ZAK = genRandomKey(Configure.CFG_KEY_LENGTH / 2) ZMK = decryptKeyUnderLMK('ZMK', unhexlify(cmdObj.ZMK.value), cmdObj.ZMK.scheme) cipherKeyUnderLMK = encryptKeyUnderLMK(keyType, clearZEK_ZAK, schemeLMK) zmkScheme = KeyScheme(ZMK, schemeZMK) cipherKeyUnderZMK = zmkScheme.encrypt(clearZEK_ZAK) zek_zak = KeyScheme(clearZEK_ZAK) kcv = hexlify(zek_zak.encrypt("\0\0\0\0\0\0\0\0")).upper() respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.ZEKZAKUnderZMK = KeyVariable( hexlify(cipherKeyUnderZMK).upper(), schemeZMK) respObj.ZEKZAKUnderLMK = KeyVariable( hexlify(cipherKeyUnderLMK).upper(), schemeLMK) respObj.CheckValue = DataVariable(kcv[:kcvLength]) return respObj
def command_FG(cmdObj): """ Generate a random PIN key and return it to the Host encrypted under a ZMK for transmission to another party and under the LMK for storage on the Host database.""" """ Command Pattern: request: Message header + 'FG' + ZMK + Atalla Variant + Delimiter + Key Scheme ZMK + Key Scheme LMK + Key Check Value Type + End message delimiter + Message Trailer response: Message header + 'FH' + Error code + first PVK under ZMK + second PVK under LMK + Check Value + End Message delimiter + Message Trailer """ (schemeZMK, schemeLMK, kcvLength) = extractKeySchemeAndKcvLength(cmdObj) clearPVK1 = genRandomKey(Configure.CFG_KEY_LENGTH / 2) clearPVK2 = genRandomKey(Configure.CFG_KEY_LENGTH / 2) ZMK = decryptKeyUnderLMK('ZMK', unhexlify(cmdObj.ZMK.value), cmdObj.ZMK.scheme) cipherPVKUnderLMK = encryptKeyUnderLMK('PVK', clearPVK2, schemeLMK) zmkScheme = KeyScheme(ZMK, schemeZMK) cipherPVKUnderZMK = zmkScheme.encrypt(clearPVK1) pvk1 = KeyScheme(clearPVK1) kcv = hexlify(pvk1.encrypt("\0\0\0\0\0\0\0\0")).upper() pvk2 = KeyScheme(clearPVK2) kcv = hexlify(pvk2.encrypt("\0\0\0\0\0\0\0\0")).upper() respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.PVKUnderZMK = KeyVariable( hexlify(cipherPVKUnderZMK).upper(), schemeZMK) respObj.PVKUnderLMK = KeyVariable( hexlify(cipherPVKUnderLMK).upper(), schemeLMK) if (kcvLength == Configure.CFG_KCV_LENGTH): respObj.CheckValue = DataVariable(kcv1 + kcv2) else: respObj.CheckValue = DataVariable(kcv1[:kcvLength]) return respObj
def command_CY(cmdObj): """ Verify a VISA CVV. """ """ Command Pattern: request: Message header + 'CW' + CVK_A + CVK_B + CVV + Primary Account Number + Delimiter(;) + Expiration Date + Service Code + End message delimiter + Message Trailer response: Message header + 'CX' + Error code + CVV + End Message delimiter + Message Trailer """ if len(cmdObj.CVK_AB.value) != 32: raise ValueError('CVK length error') if cmdObj.CVK_AB.scheme == '': CVK_A = decryptKeyUnderLMK('CVK', unhexlify(cmdObj.CVK_AB.value[:16])) CVK_B = decryptKeyUnderLMK('CVK', unhexlify(cmdObj.CVK_AB.value[16:])) else: CVK = decryptKeyUnderLMK('CVK', unhexlify(cmdObj.CVK_AB.value), cmdObj.CVK_AB.scheme) CVK_A = CVK[:8] CVK_B = CVK[8:] # Primary Account Number最后有一个分隔符 CVV = genCVV(cmdObj.PrimaryAccountNumber.value[:-1], cmdObj.ExpirationDate.value, cmdObj.ServiceCode.value, CVK_A, CVK_B) respObj = CommandObj() if (CVV == cmdObj.CVV.value): respObj.ResponseCode = DataVariable('00') else: respObj.ResponseCode = DataVariable('01') return respObj
def command_NG(cmdObj): """ Decrypted an encrypted PIN and return a reference number. """ """ Command Pattern: request: Message header + 'NG' + Account Number + PIN + End message delimiter + Message Trailer response: Message header + 'NH' + Error code + PIN + End Message delimiter + Message Trailer """ PIN = decryptPINUnderLMK(cmdObj.PIN.value, cmdObj.AccountNumber.value) respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.PIN = DataVariable(PIN) return respObj
def command_BA(cmdObj): """ Encrypt a clear text PIN. """ """ Command Pattern: request: Message header + 'NG' + PIN + Account Number + End message delimiter + Message Trailer response: Message header + 'NH' + Error code + PIN + End Message delimiter + Message Trailer """ PIN = encryptPINUnderLMK(cmdObj.PIN.value, cmdObj.AccountNumber.value) respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.PIN = DataVariable(PIN) return respObj
def command_MS(cmdObj): """ To generate a MAB for a large message using either a TAK or a ZAK. If the key is single length use ANSI X9.9 MAC generation or if the key is double length use ANSI X9.19 MAC generation. """ """ Command Pattern: request: Message header + 'MS' + Message Block Number + Key Type + Key Length + Message Length + Key + IV + Message Length + Message Block + End message delimiter + Message Trailer response: Message header + 'MT' + Error code + MAB + End Message delimiter + Message Trailer """ if cmdObj.KeyType.value == '0': KeyType = 'TAK' elif cmdObj.KeyType.value == '1': KeyType = 'ZAK' else: raise ValueError('invalid key type [' + cmdObj.KeyType.value + ']') KEY = decryptKeyUnderLMK(KeyType, unhexlify(cmdObj.Key.value), cmdObj.Key.scheme) if cmdObj.KeyLength.value == '0': keyLength = 8 elif cmdObj.KeyLength.value == '1': keyLength = 16 else: raise ValueError('invalid key length [' + cmdObj.KeyLength.value + ']') if len(KEY) != keyLength: raise ValueError('key length error') if cmdObj.MessageType.value == '0': messageBlock = cmdObj.MessageBlock.value elif cmdObj.MessageType.value == '1': messageBlock = unhexlify(cmdObj.MessageBlock.value) else: raise ValueError('invalid message type [' + cmdObj.MessageType.value + ']') if (cmdObj.MessageBlockNumber.value == '0'): # The only block. mac = calcMAC(KEY, messageBlock, "\0\0\0\0\0\0\0\0") elif (cmdObj.MessageBlockNumber.value == '1'): # The first block. mac = calcMAC(KEY, messageBlock, "\0\0\0\0\0\0\0\0") elif (cmdObj.MessageBlockNumber.value == '2'): # A middle block. mac = calcMAC(KEY, messageBlock, unhexlify(cmdObj.IV.value)) elif (cmdObj.MessageBlockNumber.value == '3'): # The last block. mac = calcMAC(KEY, messageBlock, unhexlify(cmdObj.IV.value)) else: raise ValueError('invalid message block number [' + cmdObj.MessageBlockNumber.value + ']') respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.MAB = DataVariable(string.upper(hexlify(mac))) return respObj
def command_MA(cmdObj): """ Generate a MAC on given data. """ """ Command Pattern: request: Message header + 'MA' + TAK + Data + End message delimiter + Message Trailer response: Message header + 'MB' + Error code + MAC + End Message delimiter + Message Trailer """ TAK = decryptKeyUnderLMK('TAK', unhexlify(cmdObj.TAK.value), cmdObj.TAK.scheme) mac = calcMAC(TAK, cmdObj.Data.value, "\0\0\0\0\0\0\0\0") respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.MAC = DataVariable(string.upper(hexlify(mac))[:8]) return respObj
def command_EE(cmdObj): """ Derive a PIN Using IBM Method """ """ Command Pattern: request: Message header + 'EE' + PVK + Offset + Check length + Account Number + Decimalization Table + PIN Validation data + End message delimiter + Message Trailer response: Message header + 'EF' + Error code + PIN + End Message delimiter + Message Trailer """ PVK = decryptKeyUnderLMK('PVK', unhexlify(cmdObj.PVK.value), cmdObj.PVK.scheme) PIN = genPINUsingIBMMetheod(PVK, cmdObj.AccountNumber.value, cmdObj.PINValidationData.value, cmdObj.DecimalizationTable.value) finalPIN = genFinalPIN(PIN, cmdObj.Offset.value) cypherPIN = encryptPINUnderLMK(finalPIN, cmdObj.AccountNumber.value) respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.PIN = DataVariable(cypherPIN) return respObj
def command_JC(cmdObj): """ Translate a PIN from encryption under a TPK to encryption under the LMK. """ """ Command Pattern: request: Message header + 'JC' + TPK + PIN Block + PIN Block Format Code + Account Number + End message delimiter + Message Trailer response: Message header + 'JD' + Error code + PIN + End Message delimiter + Message Trailer """ TPK = decryptKeyUnderLMK('TPK', unhexlify(cmdObj.TPK.value), cmdObj.TPK.scheme) tpk = KeyScheme(TPK) pinblock = tpk.decrypt(unhexlify(cmdObj.PINBlock.value)) clearPIN = extrackPINFromPINBlock(pinblock, cmdObj.AccountNumber.value, cmdObj.PINBlockFormatCode.value) cipherPIN = encryptPINUnderLMK(clearPIN, cmdObj.AccountNumber.value) respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.PIN = DataVariable(cipherPIN) return respObj
def command_MC(cmdObj): """ Verify a MAC and. """ """ Command Pattern: request: Message header + 'MC' + TAK + MAC + Data + End message delimiter + Message Trailer response: Message header + 'MD' + Error code + End Message delimiter + Message Trailer """ TAK = decryptKeyUnderLMK('TAK', unhexlify(cmdObj.TAK.value), cmdObj.TAK.scheme) mac = calcMAC(TAK, cmdObj.Data.value, "\0\0\0\0\0\0\0\0") finalMAC = string.upper(hexlify(mac))[:8] respObj = CommandObj() if cmdObj.MAC.value == finalMAC: respObj.ResponseCode = DataVariable('00') else: # УÑéʧ°Ü respObj.ResponseCode = DataVariable('01') return respObj
def command_DE(cmdObj): """ Generate a PIN offset using the IBM method. """ """ Command Pattern: request: Message header + 'EE' + PVK + PIN + Check length + Account Number + Decimalization Table + PIN Validation data + End message delimiter + Message Trailer response: Message header + 'EF' + Error code + Offset + End Message delimiter + Message Trailer """ PVK = decryptKeyUnderLMK('PVK', unhexlify(cmdObj.PVK.value), cmdObj.PVK.scheme) PIN = genPINUsingIBMMetheod(PVK, cmdObj.AccountNumber.value, cmdObj.PINValidationData.value, cmdObj.DecimalizationTable.value) print "PIN=", PIN clearPIN = decryptPINUnderLMK(cmdObj.PIN.value, cmdObj.AccountNumber.value) Offset = genOffset(PIN, clearPIN) respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.Offset = DataVariable(Offset) return respObj
def command_ME(cmdObj): """ Verify a MAC and, if successful, generate a MAC on the same data with adifferent key. """ """ Command Pattern: request: Message header + 'ME' + Source TAK + Destiniation TAK + MAC + Data + End message delimiter + Message Trailer response: Message header + 'MF' + Error code + MAC + End Message delimiter + Message Trailer """ SourceTAK = decryptKeyUnderLMK('TAK', unhexlify(cmdObj.SourceTAK.value), cmdObj.SourceTAK.scheme) DestinationTAK = decryptKeyUnderLMK('TAK', unhexlify(cmdObj.DestinationTAK.value), cmdObj.DestinationTAK.scheme) mac = calcMAC(SourceTAK, cmdObj.Data.value, "\0\0\0\0\0\0\0\0") finalMAC = string.upper(hexlify(mac))[:8] respObj = CommandObj() if cmdObj.MAC.value == finalMAC: respObj.ResponseCode = DataVariable('00') mac = calcMAC(DestinationTAK, cmdObj.Data.value, "\0\0\0\0\0\0\0\0") respObj.MAC = DataVariable(string.upper(hexlify(mac))[:8]) else: # УÑéʧ°Ü²»·µ»ØMAC respObj.ResponseCode = DataVariable('01') respObj.MAC = DataVariable('00000000') return respObj
def command_EA(cmdObj): """ Verify a PIN from interchange using the IBM 3624 method. """ """ Command Pattern: request: Message header + 'EA' + ZPK + PVK + Max PIN Length + PIN Block + PIN Block Format Code + Check length + Account Number + Decimalization Table + PIN Validation data + Offset + End message delimiter + Message Trailer response: Message header + 'EB' + Error code + End Message delimiter + Message Trailer """ respObj = CommandObj() ZPK = decryptKeyUnderLMK('ZPK', unhexlify(cmdObj.ZPK.value), cmdObj.ZPK.scheme) zpk = KeyScheme(ZPK) pinblock = zpk.decrypt(unhexlify(cmdObj.PINBlock.value)) (enteredPIN, rslt) = extrackPINFromPINBlock(pinblock, cmdObj.AccountNumber.value, cmdObj.PINBlockFormatCode.value) if rslt != '00': respObj.ResponseCode = DataVariable(rslt) return respObj print "enteredPIN=", enteredPIN if (len(enteredPIN) < string.atoi(cmdObj.CheckLength.value)) or ( len(enteredPIN) > string.atoi(cmdObj.MaxPINLength.value)): respObj.ResponseCode = DataVariable('24') return respObj PVK = decryptKeyUnderLMK('PVK', unhexlify(cmdObj.PVK.value), cmdObj.PVK.scheme) derivedPIN = genPINUsingIBMMetheod(PVK, cmdObj.AccountNumber.value, cmdObj.PINValidationData.value, cmdObj.DecimalizationTable.value) print "PIN=", derivedPIN finalPIN = genFinalPIN(derivedPIN, cmdObj.Offset.value) if (enteredPIN == finalPIN): respObj.ResponseCode = DataVariable('00') else: respObj.ResponseCode = DataVariable('01') return respObj
def command_MI(cmdObj): """ Translate a TAK from encryption under a ZMK to encryption under the LMK. Used to receive a key from another party. """ """ Command Pattern: request: Message header + 'MI' + ZMK + TAK + Atalla Variant + Delimiter + Key Scheme ZMK + Key Scheme LMK + Key Check Value Type + End message delimiter + Message Trailer response: Message header + 'MJ' + Error code + TAK + Check Value + End Message delimiter + Message Trailer """ (schemeZMK, schemeLMK, kcvLength) = extractKeySchemeAndKcvLength(cmdObj) ZMK = decryptKeyUnderLMK('ZMK', unhexlify(cmdObj.ZMK.value), cmdObj.ZMK.scheme) takScheme = KeyScheme(ZMK, cmdObj.TAK.scheme) clearTAK = takScheme.decrypt(unhexlify(cmdObj.TAK.value)) cipherTAK = encryptKeyUnderLMK('TAK', clearTAK, schemeLMK) tak = KeyScheme(clearTAK) kcv = hexlify(tak.encrypt("\0\0\0\0\0\0\0\0")).upper() respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.TAK = KeyVariable(hexlify(cipherTAK).upper(), schemeLMK) respObj.CheckValue = DataVariable(kcv[:kcvLength]) return respObj
def command_AG(cmdObj): """ Translate a TAK from encryption under the LMK to encryption under a TMK. Used to send a key to a terminal. """ """ Command Pattern: request: Message header + 'AG' + TMK + TAK + Atalla Variant + Delimiter + Key Scheme TMK + Key Scheme LMK + Key Check Value Type + End message delimiter + Message Trailer response: Message header + 'AH' + Error code + TAK + Check Value + End Message delimiter + Message Trailer """ (schemeTMK, schemeLMK, kcvLength) = extractTMKSchemeAndKcvLength(cmdObj) TMK = decryptKeyUnderLMK('TMK', unhexlify(cmdObj.TMK.value), cmdObj.TMK.scheme) clearTAK = decryptKeyUnderLMK('TAK', unhexlify(cmdObj.TAK.value), cmdObj.TAK.scheme) tmkScheme = KeyScheme(TMK, schemeTMK) cipherTAK = tmkScheme.encrypt(clearTAK) tak = KeyScheme(clearTAK) kcv = hexlify(tak.encrypt("\0\0\0\0\0\0\0\0")).upper() respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.TAK = KeyVariable(hexlify(cipherTAK).upper(), schemeTMK) respObj.CheckValue = DataVariable(kcv[:kcvLength]) return respObj
def command_GC(cmdObj): """ Translate a ZPK from encryption under the LMK to encryption under a ZMK. Used to transmit a ZPK to another party. """ """ Command Pattern: request: Message header + 'GC' + ZMK + ZPK + Atalla Variant + Delimiter + Key Scheme ZMK + Key Scheme LMK + Key Check Value Type + End message delimiter + Message Trailer response: Message header + 'GD' + Error code + ZPK + Check Value + End Message delimiter + Message Trailer """ (schemeZMK, schemeLMK, kcvLength) = extractKeySchemeAndKcvLength(cmdObj) ZMK = decryptKeyUnderLMK('ZMK', unhexlify(cmdObj.ZMK.value), cmdObj.ZMK.scheme) clearZPK = decryptKeyUnderLMK('ZPK', unhexlify(cmdObj.ZPK.value), cmdObj.ZPK.scheme) zmkScheme = KeyScheme(ZMK, schemeZMK) cipherZPK = zmkScheme.encrypt(clearZPK) zpk = KeyScheme(clearZPK) kcv = hexlify(zpk.encrypt("\0\0\0\0\0\0\0\0")).upper() respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.ZPK = KeyVariable(hexlify(cipherZPK).upper(), schemeZMK) respObj.CheckValue = DataVariable(kcv[:kcvLength]) return respObj
def command_A6(cmdObj): """ To import a key encrypted under a ZMK. """ """ Command Pattern: request: Message header + 'A6' + Key Type + ZMK + Key + Key Scheme LMK + Atalla Variant + End message delimiter + Message Trailer response: Message header + 'A7' + Error code + Key + Check Value + End Message delimiter + Message Trailer """ ZMK = decryptKeyUnderLMK('ZMK', unhexlify(cmdObj.ZMK.value), cmdObj.ZMK.scheme) keyScheme = KeyScheme(ZMK, cmdObj.Key.scheme) clearKey = keyScheme.decrypt(unhexlify(cmdObj.Key.value)) keyType = Configure.KeyTypeTable[cmdObj.KeyType.value] cipherKey = encryptKeyUnderLMK(keyType, clearKey, cmdObj.KeySchemeLMK.value) key = KeyScheme(clearKey) kcv = hexlify(key.encrypt("\0\0\0\0\0\0\0\0")).upper() respObj = CommandObj() respObj.ResponseCode = DataVariable('00') respObj.Key = KeyVariable( hexlify(cipherKey).upper(), cmdObj.KeySchemeLMK.value) respObj.CheckValue = DataVariable(kcv[:6]) return respObj
def GenCardInfo(mp, cardno, expiry, offset): keyConfig = GetKeyConfig(cardno) AccountNumber = cardno[-13:-1] # generate pin command = mp.command_hash['EE'] obj = Command.CommandObj() obj.MessageHeader = ' ' obj.Code = DataVariable('EE') obj.PVK = KeyVariable(keyConfig.PVK) obj.Offset = DataVariable(offset[:6] + 'FFFFFF') obj.CheckLength = DataVariable('06') obj.AccountNumber = DataVariable(AccountNumber) obj.DecimalizationTable = DataVariable('1234567890123456') obj.PINValidationData = DataVariable(AccountNumber[:-1] + 'N') message = command.pack(obj) # print message resp = mp.ProcessMessage(message) # print resp command = mp.command_hash['EF'] pinResp = command.unpack(resp) # print pinResp.PIN command = mp.command_hash['NG'] obj = Command.CommandObj() obj.MessageHeader = ' ' obj.Code = DataVariable('NG') obj.PIN = pinResp.PIN obj.AccountNumber = DataVariable(AccountNumber) message = command.pack(obj) # print message resp = mp.ProcessMessage(message) command = mp.command_hash['NH'] # print resp pinResp = command.unpack(resp) # generate cvv command = mp.command_hash['CW'] obj = Command.CommandObj() obj.MessageHeader = ' ' obj.Code = DataVariable('CW') obj.CVK_AB = KeyVariable(keyConfig.CVK_A + keyConfig.CVK_B) obj.PrimaryAccountNumber = DataVariable(cardno + ';') obj.ExpirationDate = DataVariable(expiry) obj.ServiceCode = DataVariable('106') message = command.pack(obj) # print message resp = mp.ProcessMessage(message) # print resp command = mp.command_hash['CX'] cvvResp = command.unpack(resp) # print cvvResp.CVV return (pinResp.PIN, cvvResp.CVV)