26 Ocak 2018 Cuma

AES

Kullanım
Her şey Cipher nesnesine dayanır.

1. Cipher.getInstance () ile AES cipher nesnesini yarat

2.Cipher.init() ile cipher nesnesini ilklendir.
2.1 Key
Key bilgisi SecretKeySpec nesnesi ile geçilir. Bazı kodlarda SecretKeySpec nesnesini üretmek için KeyGenerator kullanılıyor. Yani key ürettiriliyor.
KeyGenerator -> SecretKeySpec(SecretKey arayüzünden kalıtır) -> Cipher.init()
Örnek
Elimizde key verisi olsun.
byte[] key = ...;
Şöyle yaparız.
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

Bazı kodlarda ise
PBEKeySpec -> SecretKeyFactory -> SecretKey -> Cipher.init() şeklinde yapılıyor.
Örnek
Şöyle yaparız. Aslında SecretKey nesnesi direkte Cipher nesnesine geçilebilir.


int PASSWORD_ITERATIONS = 65536; // vs brute force
int KEY_LENGTH          = 256;

char[]     pass                = "password".toCharArray();
byte[]     salt                = "salt".toCharArray (); 


SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(pass, salt, PASSWORD_ITERATIONS, KEY_LENGTH);

SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec sKeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");//Gereksiz ?

2.2 IV
Örnek
Şöyle yaparız. Blok büyüklüğü 16 byte yani 128 bit kabul ediliyor.
SecureRandom sr = new SecureRandom();
byte[] byteIV = new byte[16];
sr.nextBytes(byteIV);

IvParameterSpec IV  = new IvParameterSpec(byteIV);
IV'yi kendimiz sağlarsak şöyle yaparız. 
byte[] initVector = ...;
byte[] secretKey = ...;
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE new SecretKeySpec(secretKey, "AES"),
  new IvParameterSpec(initVector));
Eğer IV'yi sağlamazsak bir tane IV üretilir. Açıklaması şöyle
If you don't specify an initialisation vector, and one is required with the block mode you're using, then a random IV will be allocated.
Daha sona cipher.getIV() ile IV alınır ve karşı tarafa şifrelenmiş veriden önce gönderilir. Böylece karşı taraf cipher.init (...) çağrısına bu veriyi geçer ve veriyi açabilir.

İlklendirmede AES 256 bit kullanırsak "InvalidKeyException : Illegal key size" hatası alırsak
Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy'i kurmak gerekir.

3. Cipher.doFinal () ile veriyi şifrele.
Bu kısım zaten bilindik :)

AES/ECB
Şöyle yaparız. ECB modunda ilklendirir.
Cipher cipher = Cipher.getInstance("AES");
AES/CBC
Örnek - NoPadding
Şöyle yaparız. Verinin blok büyüklüğünde olması gerekir.
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
Yoksa açma esnasında şu exception fırlatılır
javax.crypto.BadPaddingException: Given final block not properly padded
Örnek - PKC5Padding
Veriyi gerekiyorsa 8 byte blok olacak şekilde padler. PKC7Padding ise parametriktir ve 1- 255 arasında bir blok büyüklüğüne padleyebilir.

AES 16 byte'lık bloklar halinde çalıştığı için aslında bu kullanım biraz hatalı.

Şöyle yaparız
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
Şifreleme için şöyle yaparız. IV için rastgele byte'lar oluşturulur. Key için kullanılan byte'lar kullanılmaz. Şifreleme yapıldıktan sonra IV + salt + şifreli veri gönderilir.
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
// AES-256
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 65536, 256);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] key = f.generateSecret(spec).getEncoded();

byte[] ivBytes = new byte[16];
random.nextBytes(ivBytes);
IvParameterSpec iv = new IvParameterSpec(ivBytes);

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] encValue = c.doFinal(valueToEnc.getBytes());

byte[] finalCiphertext = new byte[encValue.length+2*16];
System.arraycopy(ivBytes, 0, finalCiphertext, 0, 16);
System.arraycopy(salt, 0, finalCiphertext, 16, 16);
System.arraycopy(encValue, 0, finalCiphertext, 32, encValue.length);

return finalCiphertext;
AES/CTR
Örnek
Şöyle yaparız.
String CIPHER_ALGORITHM = "AES/CTR/NoPadding";
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
AES/GCM
Şöyle yaparız.
Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding");
Java tag çıktısını şifrelenmiş verinin sonuna ekler.

Hiç yorum yok:

Yorum Gönder