Daha önce yazı dizimizin ilk parçasında ECB modunda AES şifrelemeyi tanımış ve bu işlemi yapabileceğimiz kodumuzu yazmıştık. Şimdi bir adım ileri giderek AES ile CBC modunda daha güvenli bir şifreleme yapacağız.

Bu tip şifreleme için Key ile beraber bir Initialization Vector (IV) gerekiyor. Bu IV karmaşık (random) ve AES-256 için 16 byte uzunluğunda olmalı.

Daha önce yaptığımız gibi bu keylerimizi de yaratmak için openssl’den faydalanacağız. Ve işte gerekli olan komut:

$ openssl enc -aes-256-cbc -P -md sha256

Benim ürettiğim key aşağıdaki gibi oldu:

key=031487DD008A7C76AC510287C17FDABA09556F63737A8838CC9BFE275CBBB096
iv=37FBF113FF6B3D8E86706F87D9146EF8

Daha önce yaptığımız gibi bu ürettiğimiz key ve IV verilerini şifreleme ve çözme sırasında kullanacağız. Detaypara fazla girmiyorum çünkü bir önceki yazımızda benzeri üzerinde ayrıntılı olarak değinmiştik. Lafı kısa tutup direk kodu yazmak için kolları sıvıyorum =)

Aşağıda şifreleme için kullanacağımız en basit hali ile kod bloğu.

// Keyimizi byte dizisine çevirelim.
byte[] keyBytes = hexStringToByteArray("031487DD008A7C76AC510287C17FDABA09556F63737A8838CC9BFE275CBBB096");
// IVmizi byte dizisine çevirelim.
byte[] ivBytes = hexStringToByteArray("37FBF113FF6B3D8E86706F87D9146EF8");

// Key ve IV için objelerimizi yaratalım.
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

// Şifreleyeceğimiz string
String plainText = "Hello AES =)";
// String güzel ancak bize byte lazım..
byte[] plainBytes = plainText.getBytes("UTF-8");

// Şifreleme objemizi yaratalım..
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// ve şifreleme için hazırlayalım..
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

// Sonunda şifrelenmiş byte dizimiz
byte[] cipherBytes = cipher.doFinal(plainBytes);

// Base64 olarak encode ederek istediğimiz gibi kullanabiliriz.
String cipherText = Base64.encodeToString(cipherBytes, Base64.DEFAULT);

Ve bu şekilde tekrar çözüyoruz.

// Keyimizi byte dizisine çevirelim.
byte[] keyBytes = hexStringToByteArray("031487DD008A7C76AC510287C17FDABA09556F63737A8838CC9BFE275CBBB096");
// IVmizi byte dizisine çevirelim.
byte[] ivBytes = hexStringToByteArray("37FBF113FF6B3D8E86706F87D9146EF8");

// Key ve IV için objelerimizi yaratalım.
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

// Çözeceğimiz Base64 string
String cipherText = "Lw+163WC9L1w3nJXkKPKGg==";
// String güzel ancak bize yine byte lazım..
byte[] cipherBytes = Base64.decode(cipherText, Base64.DEFAULT);

// Şifreleme objemizi yaratalım..
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// ve çözme için hazırlayalım..
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

// Sonunda şifrelenmiş byte dizimiz
byte[] plainBytes = cipher.doFinal(cipherBytes);
String plainText = new String(plainBytes, "UTF-8");

Gördüğünüz gibi kodda küçük ancak etkili değişiklikler yaparak çok daha güvenli bir şifreleme yapabiliyoruz. Çalışan kodun ekran görüntüsü aşağıdaki gibi.

Image

Kaynak kodlar (GitHub)

AES ile inceleyeceğim modlar bunlardı. Şunu belirtmem gerekir ki geri dönüştürülebilir hiçbir şifrelenmiş veri güvende değildir. Bu yüzden dönüştürülmesi gerekmeyen verileri Hash olarak saklamanız daha yerinde olacaktır. SHA-2 gibi bir hash algoritması denemenizi öneririm.

Şifreleme konusunda ilerleyen günlerde RSA şifreleme için yeni bir 2 seri hazırlayacağım. Mutlaka takip edin.