I have an Android app that is sending data to a Java server. I'm encrypting the data with the following function:
public String encryptRSA(String text)
{
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] utf8 = text.getBytes("UTF-8");
byte[] enc = cipher.doFinal(utf8);
return new String(Base64.encodeBase64(enc), "UTF-8");
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
and decrypting with this one:
public String decryptRSA(String text)
{
try {
final Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dec = Base64.decodeBase64(text);
byte[] utf8 = cipher.doFinal(dec);
return Base64.encodeBase64String(utf8);
}
catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
When I used them in the server, everything was working perfectly. The encryption/decryption was working, giving the right results. The problem happens when I try to decrypt in the server the information coming from the app.
(I've checked already and it's encrypting with the correct public key)
I wanted to encrypt this: iIXobbUgyc7Di3/CWBjRJw==. In my app, I get this:
eq6c+uRLLsEq8k/Dbz9cbR/hqV7Nzy7miyUhXjPS4gGbq//wxy4P37a+tFW+C8RUyx+6QodkRbhjmPp0d3ZKYmuF0JKcPP/CEBGnvcHCWnkLPL++fuZ1ded9tBF1HU30kuD8ZH/WYuLBlq6izhQ1k3GdBx5m5lxdYFESoEuu2ToiH7PwaT3huwsZRed9YhbG/y+nMUEOXIUgMwJNBqXF1nb8+ws9l664CnwzsW9F6SwXCNQgfbt2ONpiLvOc6JgXk3SNHPRZDupmn2PquRChJvBGdESCklmnME0Kw7in7vuvbaRJtIvSfOm4r9Xb5Jf6DDFEspJjSmeznNwjsDdDAw==
In my server, I get this:
zxdx/OJW7lJh9GMdUIzmgPn57UTbVpPcEPFxOtKK2wVO0nw8u1RR2arT3XCxuh6EnmbzY345rBPt/jg1UcQVcqCRFQPrw/ldfT5xK1IK5yiLrtnKzRXxyQiEQypcAPuIL4CYrgr4Yk7WdTahugyPTiTxOin2J1D7LMJjHy0cRgTIqsN1uncHNNcjD912i5wGFwrFAiGzsm+kbQm3h5RMRrsFUiGj74YPkS3DcfKkvnwQ+B3FIu+BvTNvuahCSpCFUWPdheuZ0GJYVzluBJw+wUFqqgTF3vePiyrfhnX/y6J1JumOESSR1vWRDnTCtgkSRoo6Y9a2sOgysXq6guRlCA==
Obviously, when I decrypt I get a completely different value from the initial one.
Any ideas on how I can solve this?
Thank you so much!
Replace
return Base64.encodeBase64String(utf8);
with
return new String(utf8, "UTF-8");
in your decryptRSA, if you wan't it to return what was passed to encryptRSA in the first place. This reverses what byte[] utf8 = text.getBytes("UTF-8"); did in encryptRSA.
Related
In this code, this line is causing an exception:
clearText = c.doFinal(Base64.decode(encryptedText, Base64.DEFAULT));
javax.crypto.BadPaddingException: pad block corrupted
I got the code from:
http://www.techrepublic.com/blog/software-engineer/attention-android-developers-keep-user-data-safe/
Any ideas?
private String decrypt (String encryptedText) {
byte[] clearText = null;
try {
SecretKeySpec ks = new SecretKeySpec(getKey(), "AES");
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.DECRYPT_MODE, ks);
clearText = c.doFinal(Base64.decode(encryptedText, Base64.DEFAULT));
return new String(clearText, "UTF-8");
} catch (Exception e) {
return null;
}
}
Details: I am encrypting it on the android as well
owlstead's advice was helpful, but for this case when using the code in
Attention Android developers: Keep user data safe
http://www.techrepublic.com/blog/software-engineer/attention-android-developers-keep-user-data-safe/
I made some changes to the code that might be helpful for other people in the future. I completely deleted the getkey method.
private static String seed;
/**
* Encrypts the text.
* #param clearText The text you want to encrypt
* #return Encrypted data if successful, or null if unsucessful
*/
protected String encrypt(String clearText) {
byte[] encryptedText = null;
try {
byte[] keyData = seed.getBytes();
SecretKey ks = new SecretKeySpec(keyData, "AES");
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE, ks);
encryptedText = c.doFinal(clearText.getBytes("UTF-8"));
return Base64.encodeToString(encryptedText, Base64.DEFAULT);
} catch (Exception e) {
return null;
}
}
/**
* Decrypts the text
* #param encryptedText The text you want to encrypt
* #return Decrypted data if successful, or null if unsucessful
*/
protected String decrypt (String encryptedText) {
byte[] clearText = null;
try {
byte[] keyData = seed.getBytes();
SecretKey ks = new SecretKeySpec(keyData, "AES");
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.DECRYPT_MODE, ks);
clearText = c.doFinal(Base64.decode(encryptedText, Base64.DEFAULT));
return new String(clearText, "UTF-8");
} catch (Exception e) {
return null;
}
}
Java + Android + Encryption + Exception means just one thing normally, somebody is using the SecureRandom class again as a key derivation function. This fails when the SecureRandom implementation of "SHA1PRNG" does not behave as the one in Sun's implementation in Java SE. Especially if the seed is added to the state of the random number generator instead of the seed being used as a starting point of the PRNG.
Basically, simply use SecretKey aesKey = new SecretKeySpec(byte[] keyData, "AES") instead, or - if you start off with a password - try and generate the key using PBKDF2.
For me, the problem is in getKey()
Make sure that two invocation of getKey() return the same value.
I used new SecureRandom(password.getBytes()) to generate key. It worked on Windows, but on Android, it returned different value for different call.
I Reffred From this : https://androidfreetutorial.wordpress.com/2017/03/14/android-encryptiondecryption-with-aes-algorithm/
Change to "AES" From "AES/ECB/PKCS7Padding";
I have an issue with the decryption in the following code. I have a encrypted string being sent to setData(). I am trying to decrypt the encrypted string(data). The error I keep getting is
javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
byte[] data;
String key = "tkg96827pco74510";
byte[] encryptedOut;
String decryptedOut;
Key aesKey;
Cipher cipher;
public void setData(String dataIn){
this.data = dataIn.getBytes();
try {
aesKey = new SecretKeySpec(key.getBytes(), "AES");
cipher = Cipher.getInstance("AES");
}catch(Exception e){
System.out.println("SET DATA ERROR - " + e);
}
}
public void encrypt() {
try{
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
encryptedOut = cipher.doFinal(data);
}catch(Exception e){
System.out.println(e);
}
}
public void decrypt(){
try {
cipher.init(Cipher.DECRYPT_MODE, aesKey);
decryptedOut = new String(cipher.doFinal(data));
}catch(Exception e){
System.out.println("Decrypt Error: " + e);
}
}
public byte[] getEncrypted() {
return encryptedOut;
}
public String getDecrypted(){
return decryptedOut;
}
The problem is caused by this line :
decryptedOut = new String(cipher.doFinal(data));
Here you are passing original data to decrypt. But you should pass encryptedOut here.
So the solution would be :
decryptedOut = new String(cipher.doFinal(encryptedOut));
and yes, Please pass some encoding mechanism to convert String to byteArray and vice-versa like "UTF-8".
So the correct line would be :
decryptedOut = new String(cipher.doFinal(encryptedOut),"UTF-8");
Given you have done conversion to bytes like this :
this.data = dataIn.getBytes("UTF-8");
The problem is here:
public String getDecrypted()
and here:
decryptedOut = new String(cipher.doFinal(data));
String is not a container for binary data. You need to encode the cipher text somehow before you put it into a String. For example, base64-encoding.
I am working on a wp8 app that requires encryption and decryption. Actually I need a way to encrypt some data using AES. I already have the key(as a string). I need a c# equivalent for the below java code can somebody help?
public static String encryptWithAES(String payload, String aesKey) {
byte[] raw = aesKey.getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES/ECB/PKCS5Padding");
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted;
encrypted = cipher.doFinal(payload.getBytes());
cipher = null;
return Base64.encodeToString(encrypted, Base64.DEFAULT);
} catch (Exception e) {
System.out.println("Error in encryptWithAES!!!");
e.printStackTrace();
}
return null;
}
Here is what i did :
public static byte[] EncryptWithAES(string dataToEncrypt, String Key)
{
byte[] encryptedData;
byte[] keyBytes = System.Text.Encoding.UTF8.GetBytes(Key);
using (AesManaged aesEnc = new AesManaged())
{
aesEnc.Key = keyBytes;
aesEnc.IV = new byte[16];
//Create encryptor for converting
ICryptoTransform encryptor = aesEnc.CreateEncryptor(aesEnc.Key, aesEnc.IV);
using (MemoryStream memStream = new MemoryStream())
{
using (CryptoStream crypStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter srmWriter= new StreamWriter(crypStream))
{
srmWriter.Write(dataToEncrypt);
}
encryptedData = memStream.ToArray();
}
}
}
return encryptedData;
}
The error I am getting is where i set the key: ie aesEnc.Key= keyBytes;
Your C# code works fine. You write, "The error I am getting is where i set the key: ie aesEnc.Key= keyBytes;" but you don't mention what the error is. I would guess you are getting a Cryptographic Exception with message, "Specified key is not a valid size for this algorithm."
As an experiment, try this:
byte[] output = EncryptWithAES("Hello", Encoding.UTF8.GetString(new byte[16]));
or
byte[] output = EncryptWithAES("Hello", Encoding.UTF8.GetString(new byte[32]));
and see if you still get that error setting the key. That is, make sure your key string produces an array of either 16 or 32 bytes.
I have an application developed on BlackBerry JDE 5.0.0 that encrypts a String using DES algorithm with ECB mode. After the encryption, the result is encoded by base64 encoding. But whenever I compare the result that i get from my encryption method with the result that i get on the online encryptor engine, it always give different result on the several last character. I tried to decrypt the result that i get form my encryption method with the online encriptor engine and it looks like the result is not the valid one. So how can I fix that different result on the several last character?
Here my encryption method code:
public String encryptDESECB(String text) throws MessageTooLongException
{
byte[] input = text.getBytes();
byte[] output = new byte[8];
byte[] uid = null;
uid = "431654625bd37673e3b00359676154074a04666a".getBytes();
DESKey key = new DESKey(uid);
try {
DESEncryptorEngine engine = new DESEncryptorEngine(key);
engine.encrypt(input, 0, output, 0);
String x= BasicAuth.encode(new String(output));
System.out.println("AFTER ENCODE"+x);
return new String(x);
} catch (CryptoTokenException e) {
return "NULL";
} catch (CryptoUnsupportedOperationException e) {
return "NULL";
}
}
The String that i want to encrypt is "00123456"
The Result that i get from my encryption method is:YnF2BWFV/8w=
The Result that i get from online encryptor engine (http://www.tools4noobs.com/online_tools/encrypt/) : YnF2BWFV9sw=
The Result that i get from android (With the same encryption algorithm & Method) : YnF2BWFV9sw=
Here's the code on Android:
public static String encryptDesECB(String data) {
try {
DESKeySpec keySpec = newDESKeySpec("431654625bd37673e3b00359676154074a04666a".getBytes("UTF8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);
// ENCODE plainTextPassword String
byte[] cleartext = data.getBytes("UTF8");
Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
Logger.log(Log.INFO, new String(cipher.doFinal(cleartext)));
String encrypedPwd = Base64.encodeToString(cipher.doFinal(cleartext), Base64.DEFAULT);
Logger.log(Log.INFO, encrypedPwd);
return encrypedPwd;
} catch (Exception e) {
Logger.log(e);
return null;
}
}
Can anyone help me with this?
This is most likely caused by padding, as DES works with 8 byte blocks.
For more information check out this link:
http://www.tero.co.uk/des/explain.php#Padding
As long as you can properly decrypt the content you'll be fine.
I found my mistake. It turn out my BasicAuth Class isn't the correct one for encoding the encrypted string. Now I'm using the correct one Base64 Class for the encoding, and it turn out fine.
I am currently writing a program in Java that will accept strings from PHP and either encrypt or decrypt them depending on need. The mechanism of encryption is AES-256 and I am using the BouncyCastle API to do it. To ensure that there are fewer problems in transferring the data back and forth, I use Base64 to encode the strings. The problem I am experiencing is that randomly, I cannot decrypt a string-some string can be decrypted ok, others cannot. I found a great article here at stackoverflow I thought could help here.
But I could not really see how it could fit my circumstances (I am not an encryption expert). Here's my current code. Thanks for your help.
class AES {
private final BlockCipher AESCipher = new AESEngine();
private PaddedBufferedBlockCipher pbbc;
private KeyParameter key;
AES()
{
init();
}
private void init()
{
try
{
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256);
SecretKey sk = kg.generateKey();
key=new KeyParameter(sk.getEncoded());
pbbc=new PaddedBufferedBlockCipher(AESCipher, new PKCS7Padding());
}
catch (Exception e)
{
//Take care of later
}
}
private byte[] processing(byte[] input, boolean encrypt)
throws DataLengthException, InvalidCipherTextException {
pbbc.init(encrypt, key);
byte[] output = new byte[pbbc.getOutputSize(input.length)];
int bytesWrittenOut = pbbc.processBytes(
input, 0, input.length, output, 0);
pbbc.doFinal(output, bytesWrittenOut);
return output;
}
private byte[] _encrypt(byte[] input)
throws DataLengthException, InvalidCipherTextException {
return processing(input, true);
}
private byte[] _decrypt(byte[] input)
throws DataLengthException, InvalidCipherTextException {
return processing(input, false);
}
public String Encrypt(String input)
{
try
{
byte[] ba = input.getBytes("UTF-8");
byte[] encr = _encrypt(ba);
byte[] encryptedByteValue = new Base64().encode(encr);
String encryptedValue = new String(encryptedByteValue);
return encryptedValue;//+" and decrypted is "+Decrypt(encryptedValue);
}
catch (Exception e)
{
return "ENCRYPT_ERROR "+e.getMessage();
}
}
public String Decrypt(String input)
{
try
{
byte[] decodedValue = new Base64().decode(input.getBytes());
byte[] retr = _decrypt(decodedValue);
return new String(retr, "UTF-8").replaceAll("\\u0000", "");
}
catch (Exception e)
{
return "DECRYPT_ERROR "+e.getMessage();
}
}
I figured out what the problem is, and it was two fold. This is what I wound up doing:
1) I was using cURL to communicate strings between Java and PHP and encoding encrypted text as Base64. Since the plus sign is valid in Base64 and not handled by cURL (at least by older versions), I would have mangled strings, thus leading to the error. I switched to hex encoding.
2) I had to remove carriage return (\r\n) characters from strings that went into the Java layer.
Hope this helps someone.