I have a java card applet that implements encryption and decryption using RSA PKCS#1 with key CRT (Chinese Remainder Theorem) 1024. Here some of my code below:
Constructor:
private CryptoApplet() {
generateKeyPair();
cipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
outputByte = new byte[256];
outputByte2 = new byte[117];
outBuff = new byte[128];
outBuff2 = new byte[117];
}
Encrypt function (java card):
private void encrypt(APDU apdu) {
byte[] buffer = apdu.getBuffer();
short lc = apdu.getIncomingLength();
short dataOffset = apdu.getOffsetCdata();
short blocksize = 117;
short inOffset = (short) 0;
short outOffset = (short) 0;
if (!pubKey.isInitialized() || pubKey == null) {
ISOException.throwIt(STORAGE_KU_NOT_INITIALIZED);
}
cipher.init(pubKey, Cipher.MODE_ENCRYPT);
short dataLeft = lc;
while (dataLeft > 0) {
if (dataLeft < blocksize)
blocksize = dataLeft;
outOffset = cipher.doFinal(buffer, (short) dataOffset, (short) blocksize, outBuff, (short) 0);
Util.arrayCopy(outBuff,(short) 0,outputByte,inOffset,(short) outOffset);
inOffset += outOffset;
dataOffset += blocksize;
dataLeft -= blocksize;
}
apdu.setOutgoingAndSend((short) 0, (short) outputByte.length);
}
Decrypt function (java card):
private void decrypt(APDU apdu) {
byte[] buffer = apdu.getBuffer();
short lc = apdu.getIncomingLength();
short dataOffset = apdu.getOffsetCdata();
short blocksize = 128;
short inOffset = (short) 0;
short outOffset = (short) 0;
cipher.init((RSAPrivateCrtKey) keys.getPrivate(), Cipher.MODE_DECRYPT);
short dataLeft = lc;
while (dataLeft > 0) {
if (dataLeft < blocksize)
blocksize = dataLeft;
outOffset = cipher.doFinal(buffer, (short) dataOffset, (short) blocksize, outBuff2, (short) 0);
Util.arrayCopy(outBuff2,(short) 0,outputByte2,inOffset,(short) outOffset);
inOffset += outOffset;
dataOffset += blocksize;
dataLeft -= blocksize;
}
apdu.setOutgoingAndSend((short) 0, (short) outputByte2.length);
}
The decrypt and encrypt function called from python code below (using package pyscard) and it works fine for encrypt. But, it got an error (response sw1 = 6F and sw2 = 00) everytime I try to call decrypt function.
Encrypt caller (python/pyscard) (function 0x41):
#! /usr/bin/env python
from smartcard.System import readers
from smartcard.util import *
import struct
# define the APDUs used in this script
f_input = open('4x6.JPG','rb')
list_input = list(bytearray(f_input.read()))
f_input.close()
SELECT = [0x00, 0xA4, 0x04, 0x00, 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00]
# get all the available readers
r = readers()
print "Available readers:", r
reader = r[0]
print "Using:", reader
connection = reader.createConnection()
connection.connect()
data, sw1, sw2 = connection.transmit(SELECT)
print data
print "Select Applet: %02X %02X" % (sw1, sw2)
COMMAND = [0x80, 0x41, 0x00, 0x00, 0x00]
list_output = []
lengthCommandData = 234
amountSendAPDU = len(list_input)/lengthCommandData
left = len(list_input) % lengthCommandData
if (left > 0):
amountSendAPDU += 1
for b in range(amountSendAPDU):
DATA_COMMAND = list_input[b*lengthCommandData:(b+1)*lengthCommandData]
lengthData = len(DATA_COMMAND)
tmp = lengthData/117
left = lengthData%117
if (left > 0):
tmp += 1
lengthResp = tmp*128
LE = [ord(c) for c in struct.pack("!H",lengthResp)]
LE = [0x00] + LE
LC = [ord(c) for c in struct.pack("!H",lengthData)]
data, sw1, sw2 = connection.transmit(COMMAND + LC + DATA_COMMAND + LE)
list_output = list_output + data
f_encrypted = open('4x6.enc','wb')
f_encrypted.write(bytearray(list_output))
f_encrypted.close()
Decrypt caller (python/pyscard) (function 0x42):
#! /usr/bin/env python
from smartcard.System import readers
from smartcard.util import *
import struct
# define the APDUs used in this script
f_input = open('4x6.enc','rb')
list_input = list(bytearray(f_input.read()))
f_input.close()
SELECT = [0x00, 0xA4, 0x04, 0x00, 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00]
# get all the available readers
r = readers()
print "Available readers:", r
reader = r[0]
print "Using:", reader
connection = reader.createConnection()
connection.connect()
data, sw1, sw2 = connection.transmit(SELECT)
print data
print "Select Applet: %02X %02X" % (sw1, sw2)
COMMAND = [0x80, 0x42, 0x00, 0x00, 0x00]
list_output = []
lengthCommandData = 128
amountSendAPDU = len(list_input)/lengthCommandData
left = len(list_input) % lengthCommandData
if (left > 0):
amountSendAPDU += 1
for b in range(amountSendAPDU):
DATA_COMMAND = list_input[b*lengthCommandData:(b+1)*lengthCommandData]
lengthData = len(DATA_COMMAND)
tmp = lengthData/128
left = lengthData%128
if (left > 0):
tmp += 1
lengthResp = tmp*117
LE = [ord(c) for c in struct.pack("!H",lengthResp)]
LE = [0x00] + LE
LC = [ord(c) for c in struct.pack("!H",lengthData)]
data, sw1, sw2 = connection.transmit(COMMAND + LC + DATA_COMMAND + LE)
list_output = list_output + data
print "%02X %02X" % (sw1, sw2)
f_encrypted = open('output.JPG','wb')
f_encrypted.write(bytearray(list_output))
f_encrypted.close()
The question:
- As I tried to find the problem, I found the problem is on cipher.doFinal() in decrypt function (java card). But I still don't know the cause of the error in cipher.doFinal(). Can someone help me to fix this decrypt problem?
- I tried to use extended applet, but I can't pass the data more than 255 bytes in python/pyscard. Can someone help me and guide me how to pass the data from python/pyscard with length more than 255 bytes?
- What is the maximum size of the data that can be send through APDU? As far as I know, extended APDU can receive 65535 bytes data, but when I tried to send 59904 bytes data from python/pyscard, it gives me error like:
error 3:
Traceback (most recent call last):
File "encrypt.py", line 58, in <module>
data, sw1, sw2 = connection.transmit(COMMAND + LC + DATA_COMMAND + LE)
File "C:\Users\X\Anaconda\lib\site-packages\smartcard\CardConnectionDecorat
or.py", line 82, in transmit
return self.component.transmit(bytes, protocol)
File "C:\Users\X\Anaconda\lib\site-packages\smartcard\CardConnection.py", l
ine 144, in transmit
data, sw1, sw2 = self.doTransmit(bytes, protocol)
File "C:\Users\X\Anaconda\lib\site-packages\smartcard\pcsc\PCSCCardConnecti
on.py", line 205, in doTransmit
SCardGetErrorMessage(hresult))
smartcard.Exceptions.CardConnectionException: Failed to transmit with protocol T
1. The data area passed to a system call is too small.
Thank you and sorry for the long question, newbie here.