7 Nisan 2009 Salı

Rsa ile Veri Şifrelenmesi ve Çözümlenmesi

Merhaba arkadaşlar;

Öncelikle uzun bir süre bekledikten sonra beklediğim javacard tools(Jcs Suit ) elimize ulaştı. Her nekadar gümrükten ürünümüzü almak ne kadar zor olsada başardık.
Ortamımız hakkında konuşacak olursak gerçekten kullanım olarak çok rahat. En azında verdiğiniz paranın boşuna olmadığını anlıyorsunuz. Özellikle Eclipse JCDE ile applet geliştirmeye çalışanlar ne kadar çok boş zaman harcadıklarını bilirler.
Neyse fazla uzatmadan RSA ileşifreleme ve çözümleme yapan bir applet örneğimizi vermek istiyorum.

/**
*
*/
package rsa;

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


/**
* @author afaruk
*
*/
public class Rsa extends Applet {


RSAPrivateKey rsa_PrivateKey;
RSAPublicKey rsa_PublicKey;
KeyPair rsa_KeyPair;
Cipher cipherRSA;
final short dataOffset = (short) ISO7816.OFFSET_CDATA;

/**
* In the constructor we create an instance of the applet.
* If this operation could be performed, the registered method
* of the base class is called to register this
* applet instance with the JCRE.
* @param buffer the array containing installation parameters.
* @param offset the starting offset in buffer.
* @param length the length in bytes of the parameter data in buffer.
* The maximum value of length is 32.
*/
public Rsa(byte[] array, short offset, byte length) {

//generate own rsa_keypair
//rsa_KeyPair = new KeyPair( KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_2048 );

rsa_KeyPair = new KeyPair( KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048 );


rsa_KeyPair.genKeyPair();
rsa_PublicKey = (RSAPublicKey) rsa_KeyPair.getPublic();
//rsa_PrivateCrtKey = (RSAPrivateCrtKey) rsa_KeyPair.getPrivate();
rsa_PrivateKey = (RSAPrivateKey) rsa_KeyPair.getPrivate();
cipherRSA = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);


// Length of the buffer array is coded in the first byte of the buffer.
register(array, (short) (offset + 1), array[offset]);
}

/**
* Static method invoked by the JCRE (JavaCard Runtime Environment)
* to instantiate an applet instance and register it with the JCRE.

* We only instantiate the applet in this method.
* @param buffer the array containing installation parameters.
* @param offset the starting offset in buffer.
* @param length the length in bytes of the parameter data in buffer.
* The maximum value of length is 32.
*/
public static void install(byte[] buffer, short offset, byte length) {
new Rsa(buffer, offset, length);
}

/* (non-Javadoc)
* @see javacard.framework.Applet#process(javacard.framework.APDU)
*/
public void process(APDU apdu) throws ISOException {
// TODO Auto-generated method stub
if (selectingApplet())
{
return;
}
byte[] buf = apdu.getBuffer();


if (buf[ISO7816.OFFSET_CLA] != 0) ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);

if (buf[ISO7816.OFFSET_INS] != (byte) (0xAA)) ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);

switch (buf[ISO7816.OFFSET_P1])
{
case (byte) 0x01:
encryptRSA(apdu);
return;
case (byte) 0x02:
decryptRSA(apdu);
return;
default:
ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
}
}

private void encryptRSA(APDU apdu)
{
byte a[] = apdu.getBuffer();
short byteRead = (short) (apdu.setIncomingAndReceive());
cipherRSA.init(rsa_PrivateKey, Cipher.MODE_ENCRYPT);
short cyphertext = cipherRSA.doFinal(a, (short) dataOffset, byteRead, a, (short) dataOffset);

// Send results
apdu.setOutgoing();
apdu.setOutgoingLength((short) cyphertext);
apdu.sendBytesLong(a, (short) dataOffset, (short) cyphertext);

}

private void decryptRSA(APDU apdu)
{
byte a[] = apdu.getBuffer();

short byteRead = (short) (apdu.setIncomingAndReceive());
cipherRSA.init(rsa_PublicKey, Cipher.MODE_DECRYPT);
short textlenth = cipherRSA.doFinal(a, (short) dataOffset, byteRead, a, (short) dataOffset);

// Send results
apdu.setOutgoing();
apdu.setOutgoingLength((short) textlenth );
apdu.sendBytesLong(a, (short) dataOffset, (short) textlenth );

}

}


Örneğimizden biraz bahsedecek olursak;

Yapıcı medotumuzun içerisinde şifreleme ve çözümleme için kullanılacak anahtarlar yaratılmaktadır.

rsa_KeyPair.genKeyPair();

Komutu ile biz RSA de kullanılacak anahtar ikilemesini elde ediyoruz gibi bir durum söz konusu.

rsa_PublicKey = (RSAPublicKey) rsa_KeyPair.getPublic();
rsa_PrivateKey = (RSAPrivateKey) rsa_KeyPair.getPrivate();

ilede şifrelemede ve çözümlemede kullanacağımız anahtarları elde ediyoruz.

Son olarakta şifreleme işlemleri için RSA algoritmasının kullanılacağını belirtiyoruz.

cipherRSA = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);

Şifreleme ve çözümleme metodlarını incelediğimizde iki metodunda birbirine çok yakın olduğunu sadece bir tane parametrenin değişik olduğunu görmekteyiz.

Şifreleme işlemi için ;

cipherRSA.init(rsa_PrivateKey, Cipher.MODE_ENCRYPT);

Satırı ile private key kullanılarak şifreleme yapacağımızı belirtiyoruz. Burada özellikle yapacağımız işlemin şifreleme olduğunu MODE_ENCRYPT ile belirtiyoruz. Şifrelenmiş veriyi çömek için ise sadece bu parametreyi değiştirdiğimi görebilmektesiniz.

short cyphertext = cipherRSA.doFinal(a, (short) dataOffset, byteRead, a, (short) dataOffset);

Daha sonra "a " adlı dizi içerisindeki verileri dataOffset ' den başlayarak byteRead kadarını şifreliyoruz ve aynı dizi üzerine yadırıyoruz.

Umarım faydalı olmuştur.