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"?>
|
||||
<!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>
|
||||
|
|
|
@ -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