git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@12 f711b948-2313-0410-aaa9-d29f33439f0bhenryk_github
parent
85c11acfcd
commit
0fa0e7c415
@ -0,0 +1,71 @@ |
||||
import sys, binascii, utils, random |
||||
from Crypto.Cipher import DES3 |
||||
|
||||
iv = '\x00' * 8 |
||||
PADDING = '\x80' + '\x00' * 7 |
||||
|
||||
def verify_card_cryptogram(session_key, host_challenge, |
||||
card_challenge, card_cryptogram): |
||||
message = host_challenge + card_challenge |
||||
expected = calculate_MAC(session_key, message, iv) |
||||
|
||||
print >>sys.stderr, "Original: %s" % binascii.b2a_hex(card_cryptogram) |
||||
print >>sys.stderr, "Expected: %s" % binascii.b2a_hex(expected) |
||||
|
||||
return card_cryptogram == expected |
||||
|
||||
def calculate_host_cryptogram(session_key, card_challenge, |
||||
host_challenge): |
||||
message = card_challenge + host_challenge |
||||
return calculate_MAC(session_key, message, iv) |
||||
|
||||
def calculate_MAC(session_key, message, iv): |
||||
print >>sys.stderr, "Doing MAC for: %s" % utils.hexdump(message, indent = 17) |
||||
|
||||
cipher = DES3.new(session_key, DES3.MODE_CBC, iv) |
||||
block_count = len(message) / cipher.block_size |
||||
for i in range(block_count): |
||||
cipher.encrypt(message[i*cipher.block_size:(i+1)*cipher.block_size]) |
||||
|
||||
last_block_length = len(message) % cipher.block_size |
||||
last_block = (message[len(message)-last_block_length:]+PADDING)[:cipher.block_size] |
||||
|
||||
return cipher.encrypt( last_block ) |
||||
|
||||
def get_derivation_data(host_challenge, card_challenge): |
||||
return card_challenge[4:8] + host_challenge[:4] + \ |
||||
card_challenge[:4] + host_challenge[4:8] |
||||
|
||||
def get_session_key(auth_key, host_challenge, card_challenge): |
||||
cipher = DES3.new(auth_key, DES3.MODE_ECB) |
||||
return cipher.encrypt(get_derivation_data(host_challenge, card_challenge)) |
||||
|
||||
def generate_host_challenge(): |
||||
random.seed() |
||||
return "".join([chr(random.randint(0,255)) for e in range(8)]) |
||||
|
||||
def andstring(string1, string2): |
||||
if len(string1) != len(string2): |
||||
raise ValueError, "string1 and string2 must be of equal length" |
||||
result = [] |
||||
for i in range(len(string1)): |
||||
result.append( chr(ord(string1[i]) & ord(string2[i])) ) |
||||
return "".join(result) |
||||
|
||||
if __name__ == "__main__": |
||||
default_key = binascii.a2b_hex("404142434445464748494A4B4C4D4E4F") |
||||
|
||||
host_chal = binascii.a2b_hex("".join("89 45 19 BF BC 1A 5B D8".split())) |
||||
card_chal = binascii.a2b_hex("".join("27 4D B7 EA CA 66 CE 44".split())) |
||||
card_crypto = binascii.a2b_hex("".join("8A D4 A9 2D 9B 6B 24 E0".split())) |
||||
|
||||
session_key = get_session_key(default_key, host_chal, card_chal) |
||||
print "Session-Key: ", utils.hexdump(session_key) |
||||
|
||||
print verify_card_cryptogram(session_key, host_chal, card_chal, card_crypto) |
||||
|
||||
host_crypto = calculate_host_cryptogram(session_key, card_chal, host_chal) |
||||
print "Host-Crypto: ", utils.hexdump( host_crypto ) |
||||
|
||||
external_authenticate = binascii.a2b_hex("".join("84 82 01 00 10".split())) + host_crypto |
||||
print utils.hexdump(calculate_MAC(session_key, external_authenticate, iv)) |
@ -0,0 +1,73 @@ |
||||
#!/usr/bin/env python |
||||
# -*- coding: iso-8859-1 -*- |
||||
|
||||
import pycsc, utils, cards, os, readline, re, binascii, sys |
||||
|
||||
histfile = os.path.join(os.environ["HOME"], ".cyberflex-shell.history") |
||||
try: |
||||
readline.read_history_file(histfile) |
||||
except IOError: |
||||
pass |
||||
import atexit |
||||
atexit.register(readline.write_history_file, histfile) |
||||
del os, histfile |
||||
|
||||
readline.parse_and_bind("tab: complete") |
||||
|
||||
|
||||
readerName = pycsc.listReader()[0] |
||||
newState = pycsc.getStatusChange(ReaderStates=[{'Reader': readerName, 'CurrentState':pycsc.SCARD_STATE_UNAWARE}]) |
||||
|
||||
print "Cyberflex shell" |
||||
print "Using reader: %s" % readerName |
||||
print "Card present: %s" % ((newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT) and "yes" or "no") |
||||
|
||||
if not newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT: |
||||
print "Please insert card ..." |
||||
|
||||
while not newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT \ |
||||
or newState[0]['EventState'] & pycsc.SCARD_STATE_MUTE: |
||||
|
||||
newState = pycsc.getStatusChange(ReaderStates=[{'Reader': readerName, 'CurrentState':newState[0]['EventState']}]) |
||||
|
||||
if newState[0]['EventState'] & pycsc.SCARD_STATE_MUTE: |
||||
print "Card is mute, please retry ..." |
||||
|
||||
print "Card present: %s" % ((newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT) and "yes" or "no") |
||||
|
||||
print "ATR: %s" % utils.hexdump(newState[0]['Atr'], short = True) |
||||
card_class = cards.find_class(newState[0]['Atr']) |
||||
|
||||
card = card_class() |
||||
|
||||
line = "" |
||||
apduregex = re.compile(r'^\s*([0-9a-f]{2}\s*){4,}$', re.I) |
||||
while line != "exit": |
||||
try: |
||||
line = raw_input("%s > " % card.get_prompt()) |
||||
except EOFError: |
||||
print |
||||
break |
||||
|
||||
if line.strip() == "": |
||||
continue |
||||
|
||||
parts = line.split() |
||||
cmd = parts[0] |
||||
if card.COMMANDS.has_key(cmd.lower()): |
||||
cmdspec = card.COMMANDS[cmd.lower()] |
||||
try: |
||||
cmdspec[0](card, *parts[1:]) |
||||
except Exception: |
||||
exctype, value = sys.exc_info()[:2] |
||||
print "%s: %s" % (exctype, value) |
||||
|
||||
elif apduregex.match(line): |
||||
## Might be an APDU |
||||
apdu = binascii.a2b_hex("".join(line.split())) |
||||
try: |
||||
response = card.send_apdu(apdu) |
||||
print utils.hexdump(response) |
||||
except Exception: |
||||
exctype, value = sys.exc_info()[:2] |
||||
print "%s: %s" % (exctype, value) |
Loading…
Reference in new issue