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:
henryk 2005-09-29 03:39:27 +00:00
parent 85c11acfcd
commit 0fa0e7c415
3 changed files with 167 additions and 1 deletions

71
crypto_utils.py Normal file
View File

@ -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))

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-3.5.dtd">
<!-- 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 -->
<Project version="3.5">
<Description></Description>
@ -12,6 +12,28 @@
<Source>
<Name>utils.py</Name>
</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>
<Forms>
</Forms>

73
cyberflex-shell.py Executable file
View File

@ -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)