Android use CFB - java

I'm trying to encode my String with AES and CFB. If im doing this
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
, it works fine. But if i'm using "AES/CFB/NoPadding" instead of "AES", then the same String with the same password is different. Here is my Code:
SecretKeySpec key = new SecretKeySpec(cryptPassword.getBytes(), "AES");
byte[] cryptByte = cryptString.getBytes("UTF8");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] hans = cipher.doFinal(cryptByte);
cryptString = Base64.encodeToString(hans,Base64.DEFAULT);
Can someone help me?
Thanks a lot!!!

Assuming that the question is about the difference of Cipher.getInstance("AES") and Cipher.getInstance("AES/CFB/NoPadding"):
For Oracle JDK the default mode/padding when you do not specify them in the transformation string is "ECB/PKCS5Padding", meaning that Cipher.getInstance("AES") is the same as Cipher.getInstance("AES/ECB/PKCS5Padding").
The result of encoding some data with AES/ECB/PKCS5Padding is predictably different from encoding the same data with AES/CFB/NoPadding.
To minimize the confusion you should always specify the full transformation with explicit mode and padding values.

Related

Java AES encryption issue

Every time the encryption values changed by using AES, let anyone investigate the below code and let me know the issue
code:
private static final String secretKeys = "58BA833E57A51CBF9BF8BAB696BF9"
public static String encrypt() throws Exception {
byte[] salt = new byte[16];
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
PBEKeySpec pbeKeySpec = new PBEKeySpec(secretKeys.getChars(),salt,1000, 256);
Key secretKey = factory.generateSecret(pbeKeySpec);
byte[] key = new byte[32];
byte[] iv = new byte[16];
SecretKeySpec secret = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] result = cipher.doFinal("welcome".getBytes("UTF-8"));
String s = Base64.getEncoder().encodeToString(result);
return s
}
Output
first time I got the below-encrypted string
CZRIP35M4CnJtuDQ6YpmaQ==
The second time I got the below-encrypted string
/fylTjohAZDsnCaHhiZo3A==
I have three questions:
why the encrypted string not a constant?
how can I set the Blocksize? ( AES.BlockSize = 128;)
How can I set the padding mode? (AES.Padding = PaddingMode.PKCS7;)
For the first question, #Freiheit already answered this.
Long story short, based on the iv (initilization vector) which acts as a salt and will be different for each encryption.
Having that said, encrypting the same plain text will result in different encrypted text, but the decryption (if necessary) will result back into the same plain text.
IV is helpful to make the encryption predictable.
Having stored the same password for 2 different users in a database will have different values, but will be the same password.
With the current cipher configured, you already have 128 block size. You can read more about the different cypher transformation here. You can also find more information of the block sizes for different algorithms here
You just need to change the Cipher.getInstance() to AES/CBC/PKCS7Padding
1) the encrypted text is always different because the Cipher initialization is providing it's own IV since you are not providing one. You need to provide the IV you've "computed" in order to have a consistent output. Remember you never want to use an IV more than once for whatever this code is ultimately intended to do.
2) The keysize can be 128, 192 or 256 but the blocksize is always 128.
3) Java only provides PKCS5, but there is no difference in the implementation for AES. see what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding
As was already pointed out there are several problems with the code provided such as the first lines not actually doing anything and the key and iv both being uninitialized. I would additionally suggest you use SecureRandom to initialize your key and iv. If you plan on using only a single AES key, this can be computed once and placed in the code or configuration file instead of running PBKDF2 every time.
Only adding to the answer provided by #micker, you need to invoke another version of Cipher.init(); one that takes the IV into account:
...
byte[] iv = new byte[16];
IvParameterSpec ivSpec = new IvParameterSpec(iv); // <= Wrap your IV bytes here.
SecretKeySpec secret = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec); // <= Add IV here.
...
That being said, the implementation suffers from a slew of other issues (key being all zeroes, IV being all zeroes, first 4 line don't do anything for you (as #JBNizet pointed out)). I hope you are only using it to study how Java's encryption mechanics works.

Different cipher using AES in java stored function in Oracle and on desktop

I have an trouble, that I can't resolve for a long time. I make AES cipher with the same code in Oracle java stored function and on Desktop:
String keyAlg = "AES";
String cipherAlg = "AES/ECB/PKCS5Padding";
byte[] data = new byte[]{14,23,3,45,62};
byte[] pswdBytes = new byte[]{1,2,3,4,6};
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] hash = digest.digest(pswdBytes);
Key key = new SecretKeySpec(hash , keyAlg);
Cipher cipher = Cipher.getInstance(cipherAlg);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = cipher.doFinal(data);
Different outputs:
B38D52118300A8F56A712080616C351B – in Oracle
B38D52118374A8F56A712080616C351B – on PC
Can you explain where I've made mistake or have not properly set anything.
And if I try to decrypt cipher text, I catch exception with 'Oracle cipher text', and all is Ok with cipher text from PC.
P.S.: Oracle version: Oracle DB 11g Enterprise 11.2.0.4.0,
jdk1.6.0_43
So, I've found answer for my question, when i've tried to cipher data in Oracle 12, there are similar results like as on PC. So I think it's a problem with Oracle 11.

How can i encrypt and decrypt images in java android [duplicate]

I want to encrypt file and store it in SD card. I want to decrypt that encrypted file and store it in SD card again. I have tried to encrypt file by opening it as file stream and encrypt it but it is not working. I want some idea on how to do this.
Use a CipherOutputStream or CipherInputStream with a Cipher and your FileInputStream / FileOutputStream.
I would suggest something like Cipher.getInstance("AES/CBC/PKCS5Padding") for creating the Cipher class. CBC mode is secure and does not have the vulnerabilities of ECB mode for non-random plaintexts. It should be present in any generic cryptographic library, ensuring high compatibility.
Don't forget to use a Initialization Vector (IV) generated by a secure random generator if you want to encrypt multiple files with the same key. You can prefix the plain IV at the start of the ciphertext. It is always exactly one block (16 bytes) in size.
If you want to use a password, please make sure you do use a good key derivation mechanism (look up password based encryption or password based key derivation). PBKDF2 is the most commonly used Password Based Key Derivation scheme and it is present in most Java runtimes, including Android. Note that SHA-1 is a bit outdated hash function, but it should be fine in PBKDF2, and does currently present the most compatible option.
Always specify the character encoding when encoding/decoding strings, or you'll be in trouble when the platform encoding differs from the previous one. In other words, don't use String.getBytes() but use String.getBytes(StandardCharsets.UTF_8).
To make it more secure, please add cryptographic integrity and authenticity by adding a secure checksum (MAC or HMAC) over the ciphertext and IV, preferably using a different key. Without an authentication tag the ciphertext may be changed in such a way that the change cannot be detected.
Be warned that CipherInputStream may not report BadPaddingException, this includes BadPaddingException generated for authenticated ciphers such as GCM. This would make the streams incompatible and insecure for these kind of authenticated ciphers.
I had a similar problem and for encrypt/decrypt i came up with this solution:
public static byte[] generateKey(String password) throws Exception
{
byte[] keyStart = password.getBytes("UTF-8");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
sr.setSeed(keyStart);
kgen.init(128, sr);
SecretKey skey = kgen.generateKey();
return skey.getEncoded();
}
public static byte[] encodeFile(byte[] key, byte[] fileData) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(fileData);
return encrypted;
}
public static byte[] decodeFile(byte[] key, byte[] fileData) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(fileData);
return decrypted;
}
To save a encrypted file to sd do:
File file = new File(Environment.getExternalStorageDirectory() + File.separator + "your_folder_on_sd", "file_name");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] yourKey = generateKey("password");
byte[] filesBytes = encodeFile(yourKey, yourByteArrayContainigDataToEncrypt);
bos.write(fileBytes);
bos.flush();
bos.close();
To decode a file use:
byte[] yourKey = generateKey("password");
byte[] decodedData = decodeFile(yourKey, bytesOfYourFile);
For reading in a file to a byte Array there a different way out there. A Example: http://examples.javacodegeeks.com/core-java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/
You could use java-aes-crypto or Facebook's Conceal
java-aes-crypto
Quoting from the repo
A simple Android class for encrypting & decrypting strings, aiming to
avoid the classic mistakes that most such classes suffer from.
Facebook's conceal
Quoting from the repo
Conceal provides easy Android APIs for performing fast encryption and
authentication of data

Java simple helloworld AES encryption decryption [duplicate]

This question already has answers here:
UTF-8 byte[] to String
(11 answers)
Closed 8 years ago.
I got a code snippet from another SO question and modified it a bit but I can't seem to get it to work. Can anyone figure out why? it's currently printing [B#405e70bc or similar values. All I'm trying to do is store a password in an encrypted form just for the sole purpose of keeping it away from curious eyes, is there a better way to do that?
String secret = "1234567812345678";
Key key = new SecretKeySpec(secret.getBytes(), "AES");
// Encrypt
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedData = cipher.doFinal("helloworld".getBytes());
// Decrypt
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedData = cipher.doFinal(encryptedData);
System.out.println(decryptedData.toString());
There is nothing wrong with your encryption / decryption logic. The problem is with you calling .toString() on a byte [].
Use this output statement instead:
System.out.println(new String(decryptedData));
Thanks Alexander.
This worked
String secret = "1234567812345678";
Key key = new SecretKeySpec(secret.getBytes(), "AES");
// Encrypt
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedData = cipher.doFinal("helloworld".getBytes());
// Decrypt
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedData = cipher.doFinal(encryptedData);
System.out.println(new String(decryptedData, "UTF-8"));
Please don't use this for anything critical. The standard Java AES code makes use of a fixed-length block cipher which can result in identical encrypted byte data. The upshot is a gradual leakage of plaintext information.
You should look into Cipher Block Chaining and Initialisation Vectors if you want your code to be more robust. http://www.javamex.com/tutorials/cryptography/block_modes.shtml
It may be overkill for your needs, but just thought i'd mention it.

AES -256 decryption

I have an encrypted email id for unsubscribing from abcde.test.com.
for ex : https://abcde.test.com/Forms/unSubscribe.jsp?n=2&rid=00028e7353d9c4eca480a579e10ef09b&eid=588876054d458e62779be9345f399252cac7346ad8c464b8ed0bdfbff3512dd96a5b4190c5d71c30c90c34ff39e544aa
This is encrypted in aes-256.where eid="encrypted message" and rid when combined with keysize,and keystr (like "6a6b663472346c38736873346569727538346234333534376635333962353666") forms the encoded key.
Now I want to decrypt this message.
can any one help me decrypting it?
Try the following using Java SE and Apache Commons. Please note that you haven't indicated the mode or padding for your cipher (just "AES"), so you might need to make some adjustments.
// decode the key string into bytes (using Apache Commons)
byte[] keyBytes = Hex.decodeHex(keystr.toCharArray());
// create a representation of the key
SecretKeySpec spec = new SecretKeySpec(keyBytes, "AES");
// turn the key spec into a usable key
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("AES");
SecretKey key = keyFactory.generateSecret(spec);
// use a cipher to decrypt the eid
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] plainText = cipher.doFinal(hex.decodeHex(eid.toCharArray())); // decode from Hex again
I don't know what type eid represents, so turning that into something concrete is up to you, but here's an example:
String eid = new String(plainText, "ASCII");

Categories