Java: How implement AES with 128 bits with CFB and No Padding - java

could someone give me any lead to this problem ?
I need to know how to encrypt and decrypt with AES with at least 128 bits with CFB and No Padding.
Some code or links will be very appreciated. (i already look on google, but no lucky tough).
UPDATE:
Works fine!
public byte[] crypt() {
byte[] crypt = null;
try {
final Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding", "SunJCE");
final SecretKey skeySpec = KeyGenerator.getInstance("AES").generateKey();
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
crypt = cipher.doFinal(new byte[]{0, 1, 2, 3});
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return crypt;
}
Returns null .. why ?
public String decrypt(byte[] text) {
byte[] crypt = null;
String plainText = null;
try {
final Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding", "SunJCE");
final SecretKey skeySpec = KeyGenerator.getInstance("AES").generateKey();
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
crypt = cipher.doFinal(text);
plainText = new String(crypt);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return plainText;
}
Best regards,
Valter Henrique.

Give this a go:
final Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding", "SunJCE");
final SecretKey skeySpec = KeyGenerator.getInstance("AES")
.generateKey();
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
System.out.println(Arrays.toString(cipher.doFinal(new byte[] { 0, 1, 2,
3 })));

Related

Java - AES CBC Algorithum different way to generating SecretKeySpec

I am trying to implement AES CBC 256 algorithm. And after studying online and checking few code samples I realise that there are two different ways to retrive SecretKeySpec and both results in different encrypted message.
private static SecretKeySpec getSecretKeySpec(String secretKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
String salt = "a";
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
return new SecretKeySpec(tmp.getEncoded(), "AES");
}
// private static SecretKeySpec getSecretKeySpec(String secretKey) throws NoSuchAlgorithmException {
//
// MessageDigest digest = MessageDigest.getInstance("SHA-256");
// digest.update(secretKey.getBytes(StandardCharsets.UTF_8));
// byte[] keyBytes = new byte[32];
// System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
// return new SecretKeySpec(keyBytes, "AES");
// }
public static String encrypt(String strToEncrypt, String secret)
{
try
{
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeySpec secretKeySpec = getSecretKeySpec(secret);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec);
return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes(StandardCharsets.UTF_8)));
}
catch (Exception e)
{
System.out.println("Error while encrypting: " + e.toString());
}
return null;
}
Would some please let me know which one is the correct implemention of AES CBC 256 bit encryption?
AES & CBC don't specify anything about how you derive the key. Any 128, 192 and 256 bit key are valid. Using an actual key derivation function like PBKDF2WithHmacSHA256 is preferable than a single pass to SHA-256 to slow down brute force attack, but otherwise, they both generate valid key.

BadPaddingExeception whilst decrypting AES256

Currently having issues with the decryption of an AES hash.
When i encrypt using AES256 i get the following result (After base64 encoding)
07sKQfb9dN86XAMxFmVKHQAAAAAAAAAAAAAAAAAAAAA=
I believe my issue is with the AAAAAAAA etc. for some reason I think anyway the padding isn't being removed during decryption.
My code
public String encrypt(String key, String initVector, String value) throws Exception {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"), 0, initVector.getBytes().length);
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), 0, key.getBytes().length, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = new byte[32];
cipher.doFinal(value.getBytes(), 0, value.getBytes().length, encrypted, 0);
System.out.println("Base64: " + Base64.encode(encrypted));
System.out.println("Hex: " + bytesToHex(encrypted));
return Base64.encode(encrypted);
}
public String decrypt(String key, String initVector, String encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"), 0, initVector.getBytes().length);
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), 0, key.getBytes().length, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] decrypted = new byte[64];
cipher.doFinal(Base64.decode(encrypted), 0, Base64.decode(encrypted).length, decrypted, 0);
return new String(decrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
What i am expecting when i encode base64 07sKQfb9dN86XAMxFmVKHQ=
String i am encrypting: Test
Secret key: password12345678password12345678
byte[] decrypted = new byte[64];
you created a 64 byte array but the decrypted value may be shorter (Java doesn't use zero string terminator unlike C does). So you should not make assumption over the parameter length
try using
encrypted = cipher.doFinal(value.getBytes());
and
decrypted = cipher.doFinal(Base64.decode(encrypted));

AES/CFB decryption

i am trying to decrypt using AES/CFB mode by using below code,
final static public String ENCRYPT_KEY = "4EBB854BC67649A99376A7B90089CFF1";
final static public String IVKEY = "ECE7D4111337A511F81CBF2E3E42D105";
private static String deCrypt(String key, String initVector, String encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skSpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skSpec, iv);
byte[] original = cipher.doFinal(encrypted.getBytes());
return new String(original);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
and throw below error,
Wrong IV length: must be 16 bytes long.
Above ENCRYPT_KEY and IVKEY are valid one. can any one help in that ?
You're calling "ECE7D4111337A511F81CBF2E3E42D105".getBytes("UTF-8"); which will result in byte[] of size 32, not to mention a completely wrong IV.
You need to parse the String into a byte[] instead, for example by borrowing the DatatypeConverter from javax.xml.bind.
IvParameterSpec iv = new IvParameterSpec(
javax.xml.bind.DatatypeConverter.parseHexBinary(initVector));

javax.crypto.BadPaddingException: pad block corrupted

I'm trying to encrypt something, and decrypt it. I'm failing on the decryption - I get the exception above. I tried changing ctLength and ptLength, but to no avail. What am I doing wrong?
I'm trying to encrypt: 0 0 0 0 0 0 0 0
private Cipher encrypt(byte[] input)
{
try
{
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
// encryption pass
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
ctLength += cipher.doFinal(cipherText, ctLength);
FileOutputStream fs = new FileOutputStream(savedScoresFileName);
fs.write(cipherText);
return cipher;
}
catch (Exception e)
{
Log.e("encrtypt", "Exception", e);
}
return null;
}
private String decrypt()
{
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
byte[] cipherText = new byte[32];
FileInputStream fl = new FileInputStream(savedScoresFileName);
fl.read(cipherText);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] plainText = new byte[cipher.getOutputSize(32)];
int ptLength = cipher.update(cipherText, 0, 32, plainText, 0);
ptLength += cipher.doFinal(plainText, ptLength);
return new String(plainText).substring(0, ptLength);
}
catch (Exception e)
{
Log.e("decrypt", "Exception", e);
}
return null;
}
This code was copied from this, which worked.
Your code has a number of issues, but your problem is caused by your file reading code and your strange method of performing the encryption and decryption.
Don't use the update() method, just use doFinal() and correct your file writing/reading code. E.g. your decryption method should look something like:
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
// Here you need to accurately and correctly read your file into a byte
// array. Either Google for a decent solution (there are many out there)
// or use an existing implementation, such as Apache Commons commons-io.
// Your existing effort is buggy and doesn't close its resources.
byte[] cipherText = FileUtils.readFileToByteArray(new File(savedScoresFileName));
cipher.init(Cipher.DECRYPT_MODE, key);
// Just one call to doFinal
byte[] plainText = cipher.doFinal(cipherText);
// Note: don't do this. If you create a string from a byte array,
// PLEASE pass a charset otherwise your result is platform dependent.
return new String(plainText);
} catch (Exception e) {
e.printStackTrace();
}

AES 128 encryption in Android and .Net with custom key and IV

I have a password string in my android application. I need to the send the password through the .net web service (i.e. end with .aspx) using the SOAP web service. Before sending the password i need to encrypt the password with AES 128 encryption with the custom key and IV.
They have a encrypt/decrypt tool in .net with the custom key and Iv. The tool ask a custom key with 16 digit and IV 8 digit. If give the string it generate the encrypting string. example
Example:
Key : 1234567812345678
IV : 12345678
String : android
Encrypted string : oZu5E7GgZ83Z3yoK4y8Utg==
I didn't have any idea how to do this in android. Need help.
A complete example may help you:
The encrypt/decrypt functions, using IV
public static byte[] encrypt(byte[] data, byte[] key, byte[] ivs) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
byte[] finalIvs = new byte[16];
int len = ivs.length > 16 ? 16 : ivs.length;
System.arraycopy(ivs, 0, finalIvs, 0, len);
IvParameterSpec ivps = new IvParameterSpec(finalIvs);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivps);
return cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] decrypt(byte[] data, byte[] key, byte[] ivs) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
byte[] finalIvs = new byte[16];
int len = ivs.length > 16 ? 16 : ivs.length;
System.arraycopy(ivs, 0, finalIvs, 0, len);
IvParameterSpec ivps = new IvParameterSpec(finalIvs);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivps);
return cipher.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
You can use it as below :
String dataToEncryptDecrypt = "android";
String encryptionDecryptionKey = "1234567812345678";
String ivs = "12345678";
byte[] encryptedData = encrypt(dataToEncryptDecrypt.getBytes(), encryptionDecryptionKey.getBytes(),
ivs.getBytes());
// here you will get the encrypted bytes. Now you can use Base64 encoding on these bytes, before sending to your web-service
byte[] decryptedData = decrypt(encryptedData, encryptionDecryptionKey.getBytes(), ivs.getBytes());
System.out.println(new String(decryptedData));
I don't know the details of AES algorithm in use(ie mode & padding method), bit it should be roughly like this:
public static byte[] encrypt(byte[] data, byte[] key) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/ZeroBytePadding");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
byte[] empty = new byte[16]; // For better security you should use a random 16 byte key!!!
IvParameterSpec ivps = new IvParameterSpec(empty);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivps);
return cipher.doFinal(data);
} catch (Exception e) {
// ...
}
return null;
}
Function above could be used like this:
String data = "android";
String key = "1234567812345678";
byte encrypted = encrypt(data.getbytes("UTF-8"), key.getbytes("UTF-8"));

Categories

Resources