Java Card
Java Card é uma tecnologia que permite que pequenos aplicativos (applets) baseados em plataforma Java sejam executados com segurança em smart cards e dispositivos similares com limitações de processamento e armazenamento, como o Java Ring.
O Java Card é amplamente utilizado em cartões SIM (usados em celulares GSM) e em caixas eletrônicos. O primeiro Java Card foi apresentado em 1997 por várias empresas, incluindo uma divisão da extinta Schlumberger Limited (divididas em Axalto e Gemplus, que terminaram por se fundir).
Os produtos Java Card são baseados nas especificações da Plataforma Java Card desenvolvidas pela Sun Microsystems, e suas principais características são portabilidade e segurança.
Principais características
- Interoperabilidade: escreva uma vez e rode em qualquer cartão inteligente que seja Java Card;
- Seguro: além do ambiente de execução seguro herdado de J2SE, Java Card implementa diversas funções criptográficas, aproveitando as funções dos cartões inteligentes como tokens criptográficos;
- É Java! Aproveite seus conhecimentos J2SE para desenvolver para cartões inteligentes!
- Capacidade de múltiplos aplicativos no mesmo cartão inteligente: imagine poder ter no mesmo cartão serviços dos correios, banco, telefonia, vale-refeição, etc. Este tipo de ambiente proposto pela plataforma Java Card oferece isso possibilitando inúmeras oportunidades de negócio;
- Dinâmico: é possível instalar um novo applet que já foi distribuído. Imagine que se uma entidade precisar atualizar o serviço no cartão de seus clientes, não precisará mais enviar o mesmo novamente, na próxima vez que o cartão for inserido no terminal, a atualização será procedida;
- Compatível com padrões da indústria: toda a framework suporta a norma ISO 7816 que define diversos padrões sobre cartões inteligentes. Você tem celular GSM? Java Card suporta padrões relacionados a telecomunicações também de modo que hoje boa parte dos SIM Cards no Brasil são Java Cards.
Limitações
Segundo Zavadski(2009) uma das primeiras coisas que podemos pensar é como uma linguagem tão poderosa como Java pode executar num hardware tão limitado? Claro que se trata de uma versão enxuta de Java, o que conhecemos por subconjunto (subset) da linguagem. Veja abaixo a lista de recursos não suportados:
- Carga dinâmica de classes
- Security Manager
- Finalization
- Threads
- Cloning
- Controle de acesso nos pacotes
- Keywords: native, synchronized, transient, volatile, strictfp
- Classe: System
Processo de desenvolvimento
Primeiro você baixa o Sun Java Card Development Kit, prepara o ambiente (veja mais no nas referências no final do artigo) então você:
- Escreve o .java normalmente no seu editor preferido.
- Compila com javac
- Converte com a ferramenta Converter (Disponível no JCRE)
- Simula (opcional) com o JCWDE (Disponível no JCRE) ou C-JRE (Disponível no JCRE)
- Instala no cartão inteligente
Arquivo CAP
Em Java Card, o arquivo central não é o .class mas sim o .cap, resultado da conversão de um pacote de .class através da ferramenta Converter.
Java Card HelloWorld
Para finalizar, que tal um HelloWorld? Perceba que o exemplo usa valores hexadecimais (bytes) para enviar uma mensagem APDU (Application Protocol Data Unit) e que existem métodos como select(), install(), deselect(), process(). Estes métodos estão relacionados ao ciclo de atividade e vida de um applet.
/*
* Package: br.com.igormedeiros
* Filename: HelloWorldJC.java
* Class: HelloWorldJC
* Date: [[8 de maio]] de [[2005]] 14:55:52
*
*/
package br.com.igormedeiros;
import javacard.framework.*;
/**
*
* Class HelloWorldJC
*
*/
public class HelloWorldJC extends javacard.framework.Applet {
// CLA Byte
final static byte HELLO_CLA = (byte) 0xB0;
// Verify PIN
final static byte INS_HELLO = (byte) 0x20;
public static void install(byte[] bArray, short bOffset, byte bLength) {
(new HelloWorldJC()).register(
bArray,
(short) (bOffset + 1),
bArray[bOffset]);
}
// processa o comando APDU
public void process(APDU apdu) {
byte[] buffer = apdu.getBuffer();
if ((buffer[ISO7816.OFFSET_CLA] == 0)
&& (buffer[ISO7816.OFFSET_INS] == (byte) (0xA4)))
return;
// Validate the CLA byte
if (buffer[ISO7816.OFFSET_CLA] != HELLO_CLA)
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
// Select the apropriate instruction (Byte INS)
switch (buffer[ISO7816.OFFSET_INS]) {
case INS_HELLO :
getHello(apdu);
return;
default :
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
/**
* @param apdu
* @author Igor Medeiros
* Get user id attribute
*/
private void getHello(APDU apdu) {
// cadeia de bytes com a mensagem: "hello world Java Card"
byte[] hello =
{
'h',
'e',
'l',
'l',
'o',
' ',
'w',
'o',
'r',
'l',
'd',
' ',
'J',
'a',
'v',
'a',
' ',
'C',
'a',
'r',
'd' };
// informa ao JCRE que será enviado uma resposta
short le = apdu.setOutgoing();
short totalBytes = (short) hello.length;
// informa ao JCRE o tamanho da mensagem em bytes
apdu.setOutgoingLength(totalBytes);
// envia a mensgem para o host
apdu.sendBytesLong(hello, (short) 0, (short) hello.length);
}
}
Testando
Após enviar comando de select, envie o seguinte comando: B0 20 00 00
A saída será: 68 65 6C 6C 6F 20 77 6F 72 6C 64 20 4A 61 76 61 20 43 61 72 64 90 00