Gereksinimler ve Geliştirme Ortamı Kurulumu
Java Card uygulaması geliştirmek için standart bir IDE'den ziyade, Java Card Development Kit (JCDK) araçlarına ihtiyacınız vardır. 2026 yılı itibarıyla en güncel sürüm olan Java Card 3.1 ve üzeri sürümlerle çalışmak, modern güvenlik standartlarına uyum sağlamak açısından kritiktir.
- Java Development Kit (JDK): En az JDK 17 veya 21 sürümü.
- Java Card Development Kit: Oracle tarafından sağlanan resmi SDK.
- Eclipse veya IntelliJ IDEA: Java Card eklentileri ile yapılandırılmış bir IDE.
- Java Card Simulator: Fiziksel kart olmadan kodunuzu test etmek için gerekli sanal ortam.
Kurulum aşamasında, JAVA_HOME ve JC_HOME ortam değişkenlerini sisteminize tanımlamanız gerekir. Bu, derleyicinin Java Card kütüphanelerine erişebilmesi için zorunludur.
Java Card Uygulama Mimarisi: Applet Nedir?
Java Card uygulamalarına "Applet" denir. Her applet, javacard.framework.Applet sınıfından türetilir. Bir applet, kartın işletim sistemi tarafından yönetilen bir yaşam döngüsüne sahiptir. Kartın içine yüklendiğinde install() metodu çağrılır ve uygulama aktif hale gelir.
Aşağıdaki kod örneği, temel bir Java Card applet iskeletini göstermektedir:
package com.egitim.kart;
import javacard.framework.*;
public class BasitApplet extends Applet {
protected BasitApplet() {
register(); // Applet'i kart işletim sistemine kaydeder
}
public static void install(byte[] bArray, short bOffset, byte bLength) {
new BasitApplet();
}
public void process(APDU apdu) {
// Kartın aldığı komutlar burada işlenir
}
}
Bu kodda register() metodu, applet'in kartta bir AID (Application Identifier) ile tanımlanmasını sağlar. process() metodu ise kartın dış dünya (okuyucu) ile iletişim kurduğu ana giriş noktasıdır.
APDU Komutları ile İletişim Kurma
Akıllı kartlar ve okuyucular arasındaki iletişim APDU (Application Protocol Data Unit) protokolü ile yapılır. APDU komutları "Command APDU" ve "Response APDU" olarak ikiye ayrılır. Geliştirici olarak, gelen APDU nesnesinden veriyi okumalı ve uygun yanıtı dönmelisiniz.
Aşağıdaki örnek, bir komutun nasıl işleneceğini ve basit bir veri dönüşünün nasıl yapılacağını gösterir:
public void process(APDU apdu) {
byte[] buffer = apdu.getBuffer();
// CLA ve INS byte'larını kontrol et
if (selectingApplet()) return;
if (buffer[ISO7816.OFFSET_INS] == (byte) 0x10) {
// 0x10 komutu geldiğinde "Merhaba" yanıtı dön
byte[] mesaj = {'M', 'e', 'r', 'h', 'a', 'b', 'a'};
Util.arrayCopy(mesaj, (short) 0, buffer, (short) 0, (short) mesaj.length);
apdu.setOutgoingAndSend((short) 0, (short) mesaj.length);
}
}
Burada ISO7816.OFFSET_INS, gelen komutun türünü belirten byte'ı temsil eder. Util.arrayCopy ise Java Card'ın kısıtlı bellek yapısında güvenli dizi kopyalama işlemi yapar.
Java Card Güvenliği ve Şifreleme
Java Card uygulamalarında güvenlik en önemli konudur. Kart üzerinde verileri saklarken veya iletirken şifreleme algoritmalarını kullanmalısınız. Java Card, javacard.security paketi ile DES, AES ve RSA gibi standartları destekler.
Kritik Uyarı: Kart üzerindeki verileri asla açık metin (plaintext) olarak saklamayın. Bellek kısıtları nedeniyle ağır şifreleme yöntemlerinden kaçının ve her zaman
KeyBuildersınıfını kullanarak anahtarları güvenli bir şekilde oluşturun.
// AES anahtarı oluşturma örneği
AESKey aesKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_128, false);
// Anahtarın içeriğini yükleyin
aesKey.setKey(anahtarDizisi, (short) 0);
TRANSIENT anahtarlar, kartın gücü kesildiğinde veya uygulama seçimi değiştiğinde bellekten silinir. Bu, hassas verilerin kart üzerinde kalıcı olmaması için kritik bir güvenlik önlemidir.
Java Card Uygulama Geliştirme Yöntemleri Karşılaştırması
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Simülatör Tabanlı | Hızlı test, maliyetsiz | Donanım kısıtlarını tam yansıtmaz |
| Fiziksel Kart (JCOP) | Gerçek performans ve güvenlik | Yükleme süreci ve maliyet |
Uygulama Testi ve Hata Ayıklama
Java Card uygulamanızı yazdıktan sonra, SDK ile gelen cref (C-based Reference Implementation) veya jcwde (Java Card Workstation Development Environment) kullanarak test etmelisiniz. Kodunuzda hata ayıklamak için ISOException kullanarak karttan hata kodları döndürebilirsiniz.
if (inputData == null) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
}
SW_WRONG_DATA gibi standart hata kodları, okuyucunun hatanın kaynağını anlamasına yardımcı olur. Geliştirme aşamasında her zaman APDU loglarını inceleyerek gelen byte dizilerini kontrol edin.
Sıkça Sorulan Sorular
Java Card uygulaması neden normal Java'dan daha yavaştır?
Java Card, çok kısıtlı RAM ve EEPROM/Flash belleğe sahiptir. Ayrıca, güvenlik kontrolleri ve APDU işleme protokolü, standart Java uygulamalarından daha fazla işlemci döngüsü harcar.
Fiziksel kart olmadan uygulama geliştirebilir miyim?
Evet, Java Card SDK içerisinde bulunan simülatörler sayesinde uygulamanızın mantığını ve APDU komutlarını fiziksel bir karta ihtiyaç duymadan geliştirebilir ve test edebilirsiniz.
Java Card'da veritabanı kullanabilir miyim?
Hayır, Java Card'da geleneksel anlamda bir veritabanı yoktur. Veriler EEPROM veya Flash bellek üzerinde byte dizileri (byte arrays) olarak saklanır.
Applet'i karta nasıl yüklerim?
Uygulamanızı derledikten sonra oluşan .cap dosyasını, kart yönetim araçları (GlobalPlatform standartlarına uygun araçlar) kullanarak karta "yükleme" (load) ve "kurulum" (install) komutlarıyla gönderebilirsiniz.
Java Card 3.1 sürümü neden önemli?
Java Card 3.1, modern şifreleme algoritmalarına daha iyi destek verir ve daha karmaşık IoT cihazları ile uyumlu çalışabilmesi için genişletilmiş API setleri sunar.
Java Card Uygulamalarında Bellek Yönetimi ve Optimizasyon Stratejileri
Java Card platformunda kısıtlı bellek (RAM ve EEPROM/Flash) kullanımı, uygulama geliştirme sürecinin en kritik noktasıdır. Standart Java'nın aksine, Java Card'da Garbage Collector (çöp toplayıcı) mekanizması ya hiç yoktur ya da çok sınırlı çalışır. Bu nedenle, nesne oluşturma işlemlerini minimuma indirmeli ve statik bellek tahsisine odaklanmalısınız.
Bellek Verimliliği İçin İpuçları
- Nesne Oluşturma:
newanahtar kelimesiniinstall()metodu dışında kullanmaktan kaçının. Çalışma zamanında (runtime) nesne oluşturmak,MemoryLimitExceptionhatalarına yol açar. - Geçici Bellek (Transient Memory): Verilerin karttan çıkarıldığında silinmesini istiyorsanız veya sık güncellenen verilerle çalışıyorsanız,
JCSystem.makeTransientByteArray()metodunu kullanarak RAM üzerinde yer ayırın. - Dizi İşlemleri:
System.arraycopy()metodunu kullanarak dizi kopyalama işlemlerini optimize edin.
// Örnek: Transient (geçici) bellek kullanımı
public class AppletOptimizer extends Applet {
private byte[] transientBuffer;
protected AppletOptimizer() {
// RAM üzerinde 32 baytlık geçici alan oluşturur
transientBuffer = JCSystem.makeTransientByteArray((short) 32, JCSystem.CLEAR_ON_DESELECT);
}
}
İleri Seviye APDU İşleme: Zincirleme (Chaining) ve Büyük Veri Transferi
Standart APDU komutları maksimum 255 bayt veri taşıyabilir. Ancak, biyometrik veriler veya büyük sertifikalar gibi daha büyük veri bloklarını karta göndermeniz gerektiğinde "APDU Chaining" mekanizmasını kullanmanız gerekir. Bu yöntem, verinin parçalar halinde gönderilip kart üzerinde birleştirilmesini sağlar.
Zincirleme Mantığı ile Veri Alımı
İstemci tarafında veriyi parçalara bölerken, APDU başlığındaki P1 parametresini kullanarak verinin devamının gelip gelmediğini kontrol edebilirsiniz. Aşağıdaki kod, gelen veriyi bir buffer üzerinde nasıl birleştirebileceğinizi gösterir:
public void process(APDU apdu) {
byte[] buffer = apdu.getBuffer();
// P1 parametresi 0x01 ise veri devam ediyor demektir
byte p1 = buffer[ISO7816.OFFSET_P1];
short bytesRead = apdu.setIncomingAndReceive();
// Gelen veriyi birleştirme mantığı
Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA,
dataStore, offset, bytesRead);
if (p1 == 0x01) {
// Daha fazla veri bekleniyor, cevap gönderme
return;
} else {
// Tüm veri alındı, işlemi tamamla
apdu.setOutgoingAndSend((short) 0, (short) 0);
}
}
Güvenlik Notu
Büyük verileri işlerken, dataStore dizisinin boyutunun kartın toplam EEPROM kapasitesini aşmadığından emin olun. Ayrıca, her parça gönderiminde verinin bütünlüğünü sağlamak için MAC (Message Authentication Code) veya dijital imza kontrolü yapılması, saldırganların veri paketlerini manipüle etmesini engeller.
Sonuç
Java ile Java Card kullanarak akıllı kart uygulaması geliştirmek, donanım seviyesinde güvenliğin temellerini anlamanızı sağlar. Bu rehberde; applet yapısını, APDU iletişimini ve temel güvenlik prensiplerini inceledik. Bir sonraki adım olarak, GlobalPlatform spesifikasyonlarını inceleyerek kart üzerinde uygulama yönetimi (loading/installing) süreçlerini daha derinlemesine araştırmanızı öneririm.
Yasal Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanacağınız uygulamaların, ilgili güvenlik standartlarına (EMV, FIPS vb.) uygunluğu ve bağımsız denetimden geçmesi zorunludur. Kodların yanlış kullanımı veri kaybına veya donanım kilitlenmesine neden olabilir.


Yorumlar (0)
Yorum Yaz