basic functions working
git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@12 f711b948-2313-0410-aaa9-d29f33439f0b
This commit is contained in:
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))
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE Project SYSTEM "Project-3.5.dtd">
|
<!DOCTYPE Project SYSTEM "Project-3.5.dtd">
|
||||||
<!-- Project file for project cyberflex-shell -->
|
<!-- Project file for project cyberflex-shell -->
|
||||||
<!-- Saved: 2005-09-27, 15:23:49 -->
|
<!-- Saved: 2005-09-29, 05:37:58 -->
|
||||||
<!-- Copyright (C) 2005 Henryk Plötz, henryk@ploetzli.ch -->
|
<!-- Copyright (C) 2005 Henryk Plötz, henryk@ploetzli.ch -->
|
||||||
<Project version="3.5">
|
<Project version="3.5">
|
||||||
<Description></Description>
|
<Description></Description>
|
||||||
|
@ -12,6 +12,28 @@
|
||||||
<Source>
|
<Source>
|
||||||
<Name>utils.py</Name>
|
<Name>utils.py</Name>
|
||||||
</Source>
|
</Source>
|
||||||
|
<Source>
|
||||||
|
<Name>crypto_utils.py</Name>
|
||||||
|
</Source>
|
||||||
|
<Source>
|
||||||
|
<Name>cyberflex-shell.py</Name>
|
||||||
|
</Source>
|
||||||
|
<Source>
|
||||||
|
<Dir>cards</Dir>
|
||||||
|
<Name>cyberflex_card.py</Name>
|
||||||
|
</Source>
|
||||||
|
<Source>
|
||||||
|
<Dir>cards</Dir>
|
||||||
|
<Name>generic_card.py</Name>
|
||||||
|
</Source>
|
||||||
|
<Source>
|
||||||
|
<Dir>cards</Dir>
|
||||||
|
<Name>java_card.py</Name>
|
||||||
|
</Source>
|
||||||
|
<Source>
|
||||||
|
<Dir>cards</Dir>
|
||||||
|
<Name>__init__.py</Name>
|
||||||
|
</Source>
|
||||||
</Sources>
|
</Sources>
|
||||||
<Forms>
|
<Forms>
|
||||||
</Forms>
|
</Forms>
|
||||||
|
|
|
@ -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