2016-04-20 15 views
2

Ich bin neu in der Java-Karte Programmierung. Ich habe ein Beispiel für die AES-Verschlüsselungsmethode für Java-Karten gesehen und konnte das Applet erstellen und installieren. Wenn ich versuche, mit dem Applet zu kommunizieren, wird eine 6F00 Fehlermeldung zurückgegeben. Was mache ich falsch?Java-Karte Verschlüsselung mit AES-Returns 6F00

Hier ist eine Probe von meinem Code:

private void SendData(APDU apdu) 
{ 

    aesKeyTrial= (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false); 
    byte[] outBuffer; 
    outBuffer = new byte[16]; 
    byte[] trialKey; 
    trialKey = new byte[16]; 
    byte[] input = {(byte)0x44,(byte)0x22,(byte)0x33,(byte)0x44,(byte)0x55,(byte)0x66,(byte)0x77,(byte)0x88,(byte)0x99,0x10,(byte)0xA2, 0x35, (byte)0x5E,0x15,0x16,0x14}; 
    byte[] key = {0x2d, 0x2a, 0x2d, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x41, 0x43, 0x4f, 0x44, 0x45, 0x2d, 0x2a, 0x2d}; 
    byte[] buffer = apdu.getBuffer(); 
    short len = (short) input.length; 


    aesKeyTrial.setKey(trialKey,(short)0); 
    if(len<=0||len%16!=0) 
    { 
     ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); 
    } 
    aesCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false); 
    aesCipher.init(aesKeyTrial, Cipher.MODE_ENCRYPT); 
    aesCipher.doFinal(input, ISO7816.OFFSET_CDATA, len, outBuffer, (short)0); 
    Util.arrayCopyNonAtomic(input, (short)0, buffer, (short)0, (short)len); 
    apdu.setOutgoing(); 
    apdu.setOutgoingLength(len); 
    apdu.sendBytes((short) 0, (short)len); 
} 

Der, den ich zu verschlüsseln bin versucht "input".

+0

0x6F00 ist eine Art wie 'RuntimeException'. Es könnte sich um einen Fehler in Ihrem Applet handeln. Führen Sie Ihr Applet auf einem Simulator aus, um zu sehen, was passiert. – erickson

+0

Hallo Erickson. Ich habe bereits herausgefunden, was mit meinem Code passiert. Scheint, dass ich die Funktion doFinal falsch verstanden habe. Ich ändere die Eingabevariablen in doFinal (Eingabe, (kurz) 0, len, Puffer, (kurz) 0). – Jujumancer

+0

HectorIrvinPunzalan, Sie sollten Ihre Frage mit diesen Informationen beantworten oder @erickson bitten, dies für Sie zu tun. Fragen mit Antworten helfen anderen Menschen in der Gemeinschaft: Fragen mit Antworten * in den Kommentaren * sind für andere normalerweise nicht nützlich. Ich bin froh, dass du dein Problem gelöst hast! –

Antwort

3

Wie Sie in Ihrer Antwort, sagte, das Problem des Codes ist, dass Sie falsche Parameter an die doFinal (byte[] inBuff, short inOffset, short inLength,byte[] outBuff, short outOffset) Methode übergeben.

Aber der Beispielcode, den Sie verwenden, scheint wirklich schlecht. Es gibt Gründe, die ich es schlecht schreibe:

1- Es verwendete dynamische Variablen in einer Methode, die so oft aufgerufen wird. Dynamische Variablen sind diejenigen, die mit dem Schlüsselwort new erstellt wurden. Diese Variablen werden im EEPROM zugewiesen. Das Schreiben im EEPROM ist eher langsam als RAM und es hat auch eine begrenzte Lösch-Schreib-Operationen, bevor es wear out, so ist es sehr empfehlenswert, RAM anstelle von EEPROM zu verwenden, falls Sie die Daten nicht zwischen verschiedenen CAD (Card Leser) Sitzungen. Und da es in Java Card auch keinen obligatorischen/automatischen Garbage Collector gibt, sollten Sie nicht verschiedene dynamische Variablen repetitiv definieren, sondern stattdessen ein globales verwenden (Klassenvariable oder Instanzvariable anstelle von lokalen Variablen).

2- Als int Datentyp in Javacards optional ist, müssen Sie versuchen, short und byte so viel wie möglich zu verwenden, und Sie müssen auch alle Werte auf diese Art werfen mit/ohne Vorzeichen Probleme zu verhindern.

Schließlich biete ich Ihnen eine weiterentwickelte Version des Programms:

package soQusetion; 

import javacard.framework.*; 
import javacard.security.AESKey; 
import javacard.security.KeyBuilder; 
import javacardx.crypto.Cipher; 

public class SOQ1 extends Applet { 

    Cipher aesCipher; 
    AESKey aesKey; 

    //Two different types of memory for different usage. each one has 16 (= 0x10) byte capacity. 
    private byte[] volatileMem; 
    private byte[] nonVolatileMem; 

    //INS value for APDU command 
    public static final byte INS_SET_KEY = 0x10; 
    public static final byte INS_ENCRYPT = 0x20; 
    public static final byte INS_DECRYPT = 0x30; 

    public static void install(byte[] bArray, short bOffset, byte bLength) { 
     new SOQ1(); 
    } 

    protected SOQ1() { 
     volatileMem = JCSystem.makeTransientByteArray((short) 0x10, JCSystem.CLEAR_ON_DESELECT); 
     nonVolatileMem = new byte[(short) 0x10]; 
     aesCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, false); 
     aesKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false); 
     register(); 
    } 

    public void process(APDU apdu) { 
     if (selectingApplet()) { 
      return; 
     } 
     byte[] buffer = apdu.getBuffer(); 
     apdu.setIncomingAndReceive(); 

     if (buffer[ISO7816.OFFSET_LC] != (byte) 0x10) { 
      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); 
     } 

     switch (buffer[ISO7816.OFFSET_INS]) { 
      case INS_SET_KEY: 
       aesKey.setKey(buffer, ISO7816.OFFSET_CDATA); 
       break; 
      case INS_ENCRYPT: 
       aesCipher.init(aesKey, Cipher.MODE_ENCRYPT); 
       aesCipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short) 0x10, volatileMem, (short) 0x00); 
       Util.arrayCopyNonAtomic(volatileMem, (short) 0x00, buffer, (short) 0x00, (short) 0x10); 
       apdu.setOutgoingAndSend((short) 0x00, (short) 0x10); 
       break; 
      case INS_DECRYPT: 
       aesCipher.init(aesKey, Cipher.MODE_DECRYPT); 
       aesCipher.doFinal(buffer, ISO7816.OFFSET_CDATA, (short) 0x10, volatileMem, (short) 0x00); 
       Util.arrayCopyNonAtomic(volatileMem, (short) 0x00, buffer, (short) 0x00, (short) 0x10); 
       apdu.setOutgoingAndSend((short) 0x00, (short) 0x10); 
       break; 
      default: 
       ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); 
     } 

    } 
} 

Es wie unten funktioniert:

Select Applet begin... 
Select Applet successful. 
//Loading AES Key APDU Command 
Send: 00 10 00 00 10 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 00 
Recv: 90 00 
//Encrypt APDU Command 
Send: 00 20 00 00 10 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 00 
Recv: 62 F6 79 BE 2B F0 D9 31 64 1E 03 9C A3 40 1B B2 90 00 
//Decrypt APDU Command 
Send: 00 30 00 00 10 62 F6 79 BE 2B F0 D9 31 64 1E 03 9C A3 40 1B B2 00 
Recv: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 90 00 

Jeder Vorschlag, das obige Programm effizienter zu machen, ist mir willkommen.

+0

Danke für die Bereitstellung eines entwickelten Codes. Wird deinen Code studieren und daraus lernen. Ich schätze die Hilfe! Vielen Dank! – Jujumancer

+0

Rückgabewert für Laden des AES-Schlüssel-APDU-Befehls: 'CLA: 00, INS: 0a, P1: 00, P2: 00, Lc: 17, 00, 0b, 16, 21, 2c, 37, 42, 4d, 58, 63 , 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 00, Le: 00, SW1: 69, SW2: 99', Irgendeine Idee warum? – Niyojan

+0

Und wählen Sie das Applet? \ – Niyojan

2

Hallo Ich habe herausgefunden, was mein Fehler war oder was ist falsch mit meinem Code. Ich habe die Funktion doFinal falsch verstanden und es vermasselt, was auf der Karte installiert werden soll.

Hier ist der neue und sauberen Code:

Cipher aesCipher; 
    AESKey aesKeyTrial; 
    aesKeyTrial= (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_128, false); 
    byte[] buffer = apdu.getBuffer(); 
    byte[] aesKey; 
    aesKey = new byte[16]; 
    byte[] input = {(byte)0x11,(byte)0x22,(byte)0x33,(byte)0x44,(byte)0x55,(byte)0x66,(byte)0x77,(byte)0x88,(byte)0x99,0x10,(byte)0xA2, 0x35, (byte)0x5E,0x15,0x16,0x14}; 
    byte[] key = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26}; 

    short len = (short) input.length; 
    if (len <= 0 || len % 16 != 0) 
    { 
     ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); 
    } 

    aesKeyTrial.setKey(key,(short)0); 
    aesCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, false); 
    aesCipher.init(aesKeyTrial, Cipher.MODE_ENCRYPT); 
    aesCipher.doFinal(input, (short)0, len, buffer, (short)0); 
    apdu.setOutgoingAndSend((short)0, len);