How to encrypt and decrypt the json string in android using key? - android

I am currently working on a drawing based project , i had stored the values as on json format and store in file , but i want encrypt the json by using the key and decrypt the json the by same key.

Stringify your json using String resultString = JSON.stringify() and encrypt your resultString using the following method
public class EncryptUtils {
public static SecretKey generateKey(String mySecret)
throws NoSuchAlgorithmException, InvalidKeySpecException
{
return secret = new SecretKeySpec(mySecret.getBytes(), "AES");
}
public static byte[] encryptMsg(String message, SecretKey secret)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException
{
/* Encrypt the message. */
Cipher cipher = null;
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] cipherText = cipher.doFinal(message.getBytes("UTF-8"));
return cipherText;
}
public static String decryptMsg(byte[] cipherText, SecretKey secret)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidParameterSpecException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException
{
/* Decrypt the message, given derived encContentValues and initialization vector. */
Cipher cipher = null;
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret);
String decryptString = new String(cipher.doFinal(cipherText), "UTF-8");
return decryptString;
}
}
String mySecret="mySecretKeyString";
String secretKey = EncryptUtils.generateKey(mySecret);
String encryptedStr = EncryptUtils.encryptMsg(jsonResultString, secretKey));
String decryptedStr = EncryptUtils.decryptMsg(encryptedStr.getBytes("UTF-8"), secretKey));
finally you could get the JSON data using following method
try {
JSONObject obj = new JSONObject(decryptedString);
Log.d("My App", obj.toString());
} catch (Throwable t) {
Log.e("My App", "Could not parse malformed JSON: \"" + json + "\"");
}

Do not use this as some kind of security measurement.
The encryption mechanism in this post is a One-time pad, which means that the secret key can be easily recovered by an attacker using 2 encrypted messages. XOR 2 encrypted messages and you get the key. That simple!
public class EncryptUtils {
public static final String DEFAULT_ENCODING = "UTF-8";
static BASE64Encoder enc = new BASE64Encoder();
static BASE64Decoder dec = new BASE64Decoder();
public static String base64encode(String text) {
try {
return enc.encode(text.getBytes(DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
return null;
}
}//base64encode
public static String base64decode(String text) {
try {
return new String(dec.decodeBuffer(text), DEFAULT_ENCODING);
} catch (IOException e) {
return null;
}
}//base64decode
public static void main(String[] args) {
String txt = "some text to be encrypted";
String key = "key phrase used for XOR-ing";
System.out.println(txt + " XOR-ed to: " + (txt = xorMessage(txt, key)));
String encoded = base64encode(txt);
System.out.println(" is encoded to: " + encoded + " and that is decoding to: " + (txt = base64decode(encoded)));
System.out.print("XOR-ing back to original: " + xorMessage(txt, key));
}
public static String xorMessage(String message, String key) {
try {
if (message == null || key == null) return null;
char[] keys = key.toCharArray();
char[] mesg = message.toCharArray();
int ml = mesg.length;
int kl = keys.length;
char[] newmsg = new char[ml];
for (int i = 0; i < ml; i++) {
newmsg[i] = (char)(mesg[i] ^ keys[i % kl]);
}//for i
return new String(newmsg);
} catch (Exception e) {
return null;
}
}//xorMessage
}

Related

AES Encryption of api string response returning extra characters at start

I am trying to decrypt API encrypted response. But the decryption process returning extra characters at the start and also missing a double-quoted characters of JSON format response key shown below:
private void setListener() {
btnDecode.setOnClickListener (new View.OnClickListener () {
#Override
public void onClick(View v) {
decodeCode();
}
});
}
private void decodeCode() {
String response = "bk/qo1fYH3aKseRNcXq6FLn2ScpSTZDyse4YINiQV34XTb2mOV95sB8uBemWl9p6XSGVYga+K6/n3LyJEgiyAmijL+y/ahb1h0ehv1Ejej+uVWN4yXWUr4TOFz+78iU5A9+znSQXIQIo8ti9Z+ALpvu4lqrDo2hZbF0OKDxxgOjLF28NSrNpVo9eThaH33vFmYZUZ1zFj281g8ahj6wf0MuL0Ev9bsI9AhX4eW0rJZSacW2/xZH81EPxcojerCzGnALxVGlE/MzxLSieUMWRkxKxQZ/Ux6EhiJy6kTkS4iku1Uk/qQJglj22eiIPROpNARts2lOo09PdsgJZb3DKm+j16FKfEC+fpLykXqQ5shtcW/tB0Qer+XFNBHGblDMYBaVzqahunvzHQKaSu2vF+A==";
try {
String responseResult = encryptUtils.decrypt (response, "1234567891123456");
txtDecode.setText (responseResult);
} catch (GeneralSecurityException e) {
e.printStackTrace ();
} catch (IOException e) {
e.printStackTrace ();
}
}
Here in return I am getting some extra characters before actual string. Also the Response key in which the complete response exist has invalid syntax i.e Response key start double-quote is missing. Decrypted string getting is:
J`#TBBKE#FQResponse":"{\"access_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IllhYm5lciIsIm5iZiI6MTU3MjUxNDI2MywiZXhwIjoxNTcyNTE2MDYzLCJpYXQiOjE1NzI1MTQyNjN9.w4cQcr4pT3hyGPW5MOS7QbWL64nvHBf97OJ8DQWDRRg\",\"badge_Id\":\"108817\"}","ResponseMessage":"Login Success"}
And this is my EncryptUtils class. In this I have tried NoPadding encryption also in decrypt method but didn't work for me:
public class EncryptUtils {
public String encrypt(String value, String key)
throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
{
byte[] value_bytes = value.getBytes("UTF-8");
byte[] key_bytes = getKeyBytes(key);
return Base64.encodeToString(encrypt(value_bytes, key_bytes, key_bytes), 0);
}
public byte[] encrypt(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2, byte[] paramArrayOfByte3)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
{
// setup AES cipher in CBC mode with PKCS #5 padding
Cipher localCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// encrypt
localCipher.init(1, new SecretKeySpec (paramArrayOfByte2, "AES"), new IvParameterSpec (paramArrayOfByte3));
return localCipher.doFinal(paramArrayOfByte1);
}
public String decrypt(String value, String key)
throws GeneralSecurityException, IOException
{
byte[] value_bytes = Base64.decode(value, 0);
byte[] key_bytes = getKeyBytes(key);
return new String(decrypt(value_bytes, key_bytes, key_bytes), "UTF-8");
}
public byte[] decrypt(byte[] ArrayOfByte1, byte[] ArrayOfByte2, byte[] ArrayOfByte3)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
{
// setup AES cipher in CBC mode with PKCS #5 padding
Cipher localCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// decrypt
localCipher.init(2, new SecretKeySpec(ArrayOfByte2, "AES"), new IvParameterSpec(ArrayOfByte3));
return localCipher.doFinal(ArrayOfByte1);
}
private byte[] getKeyBytes(String paramString)
throws UnsupportedEncodingException
{
byte[] arrayOfByte1 = new byte[16];
byte[] arrayOfByte2 = paramString.getBytes("UTF-8");
System.arraycopy(arrayOfByte2, 0, arrayOfByte1, 0, Math.min(arrayOfByte2.length, arrayOfByte1.length));
return arrayOfByte1;
}
}
Your assumption that the IV is a copy of the key appears to be incorrect. It appears that the IV is all zeros. You can confirm this by replacing this line in decrypt:
return new String(decrypt(value_bytes, key_bytes, key_bytes), "UTF-8");
with
return new String(decrypt(value_bytes, key_bytes, new byte[16]), "UTF-8");
The decryption result becomes
{"Status":true,"Response":"{\"access_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IllhYm5lciIsIm5iZiI6MTU3MjUxNDI2MywiZXhwIjoxNTcyNTE2MDYzLCJpYXQiOjE1NzI1MTQyNjN9.w4cQcr4pT3hyGPW5MOS7QbWL64nvHBf97OJ8DQWDRRg\",\"badge_Id\":\"108817\"}","ResponseMessage":"Login Success"}

How decrypt data that encrypted with RSA logarithm Android

I am currently developing an application that requires me to encrypt chatting messages. In addition, I managed to encrypt the data Using RSA algorithm but I am not able to decrypt it. below is a snapshots of my encryption and decryption code
RSA Class
public class RSA {
KeyPairGenerator kpg;
KeyPair kp;
PublicKey publicKey;
PrivateKey privateKey;
byte[] encryptedBytes, decryptedBytes;
Cipher cipher, cipher1;
String encrypted, decrypted;
//TODO:implementing Encryption method
public String Encrypt (String plain) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
kp = kpg.genKeyPair();
publicKey = kp.getPublic();
privateKey = kp.getPrivate();
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
encryptedBytes = cipher.doFinal(plain.getBytes());
encrypted = bytesToString(encryptedBytes);
return encrypted;
}
public String Decrypt (String result) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
cipher1=Cipher.getInstance("RSA");
cipher1.init(Cipher.DECRYPT_MODE, privateKey);
decryptedBytes = cipher1.doFinal(stringToBytes(result));
decrypted = new String(decryptedBytes);
return decrypted;
}
public String bytesToString(byte[] b) {
byte[] b2 = new byte[b.length + 1];
b2[0] = 1;
System.arraycopy(b, 0, b2, 1, b.length);
return new BigInteger(b2).toString(36);
}
public byte[] stringToBytes(String s) {
byte[] b2 = new BigInteger(s, 36).toByteArray();
return Arrays.copyOfRange(b2, 1, b2.length);
}
**Encrypt method **
private void PostMessages() {
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String key = dataSnapshot.getKey();
String input = mInputText.getText().toString();
String name = dataSnapshot.child("Name").getValue().toString();
if (!input.equals("")) {
final String MessagesText = mInputText.getText().toString();
final String TextMessages = MessagesText;
if (MessagesText==""){
Toast.makeText(MainChatActivity.this, "please write a message ",Toast.LENGTH_SHORT).show();
}else {
try {
DataEncrypte = EncrypteandDicrypye.Encrypt(TextMessages).toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
String messagngerSender = "Messages/" + Registerid + "/" + ChatUserKey;
String messangerReciverId = "Messages/" + ChatUserKey + "/" + Registerid;
final DatabaseReference MessagesId = UserMesages.child("Messages").
child(Registerid).child(ChatUserKey).push();
String messages_pushId = MessagesId.getKey();
//String EncrypteMessage = Encrypte.Encrypt(MessagesText).toString();
Map messagesTextBody = new HashMap();
messagesTextBody.put("Message",DataEncrypte);
messagesTextBody.put("Name", name);
messagesTextBody.put("Time", ServerValue.TIMESTAMP);
messagesTextBody.put("from",Registerid);
Map messageDetails = new HashMap();
messageDetails.put(messagngerSender + "/" + messages_pushId, messagesTextBody);
messageDetails.put(messangerReciverId + "/" + messages_pushId, messagesTextBody);
UserMesages.updateChildren(messageDetails, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
System.out.println("ChatError" + databaseError.getMessage().toString());
}
mInputText.setText("");
}
});
}
}
System.out.println("Data is exist " + dataSnapshot.child("User type").getValue().toString());
}
}
*For encrytion part every thing is working as expected *
**Decryption code **
For decrytion part i have call the decrypt method in OnbindView holder
RSA rsa = new RSA();
try {
String decryptedMessage = rsa.Decrypt(messages.getMessage());
holder.messagesText.setText(decryptedMessage.toString());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
holder.messageUser.setText(messages.getName());

pad block corrupted error on Android

Encryption is working fine. When I try to decrypt I receive error "pad block corrupted"(on c3des.doFinal). What am I doing wrong? I use web services (C#) and encryption and decryption is working fine.
public String encryptText(String plainText) throws Exception {
byte[] plaintext = plainText.getBytes("UTF-8");//input
byte[] tdesKeyData = "sdfsdgf3q453qdsg".getBytes("UTF-8");
Cipher c3des = Cipher.getInstance("DESede/ECB/PKCS7Padding");
SecretKeySpec myKey = new SecretKeySpec(tdesKeyData, "DESede");
c3des.init(Cipher.ENCRYPT_MODE, myKey);
byte[] cipherText = c3des.doFinal(plaintext);
String encryptedString = Base64.encodeToString(cipherText,
Base64.DEFAULT);
return encryptedString;
}
public String decrypt(String tekst) throws Exception {
byte[] tekst2 = tekst.getBytes("UTF-8");
byte[] tdesKeyData = "sdfsdgf3q453qdsg".getBytes("UTF-8");
Cipher c3des = Cipher.getInstance("DESede/ECB/PKCS7Padding");
SecretKeySpec myKey = new SecretKeySpec(tdesKeyData, "DESede");
String decryptedString="";
try {
c3des.init(Cipher.DECRYPT_MODE, myKey);
byte[] cipherText = c3des.doFinal(tekst2);
decryptedString = Base64.decode(cipherText, Base64.DEFAULT).toString();
}
catch(Exception e)
{
decryptedString=e.getMessage();
}
return decryptedString;
}

Android Encrypt/Decrypt ArrayList<LinkedHashMap> to String

So I'm using the code below for encrypting/decrypting string values that can be stored in the device preferences but I know need to add a method for encrypting/decrypting an ArrayList that can also be stored in the preferences as well (so I'm guessing the encryption needs to convert the arraylist to a string and then the decryption needs to convert that string back to the arraylist). Since I'm pretty new to Android/Java I'm having a hard time figuring out how to do this so any help would be appreciated.
public String encrypt(String key, String data) {
if (key == null || data == null)
return null;
try {
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes(charsetName));
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algorithm);
SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
byte[] dataBytes = data.getBytes(charsetName);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return Base64.encodeToString(cipher.doFinal(dataBytes), base64Mode);
} catch (Exception e) {
return null;
}
}
public String decrypt(String key, String data) {
if (key == null || data == null)
return null;
try {
byte[] dataBytes = Base64.decode(data, base64Mode);
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes(charsetName));
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algorithm);
SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] dataBytesDecrypted = (cipher.doFinal(dataBytes));
return new String(dataBytesDecrypted);
} catch (Exception e) {
return null;
}
}
Serialize the ArrayList<LinkedHashMap> to Json before sending the input to encrypt()
public static String ArrayListToString(ArrayList<LinkedHashMap> list) {
Gson serializer = new Gson();
return serializer.toJson(list);
}
then do deserializing after decrypting.
You need to reference Google-Gson in your project.

Android DES Decrypt badpaddingexception: pad block corrupted

First of all, I've reviewed all the entries on the forum, and I still can not find a solution to my problem.
I have to measure the time it takes to encode and decode a text with DES, and make a comparison with other algorithms.
When I run the code, I have this error: BadPaddingException: pad block corrupted. When I debug, the code fails in this line:
  byte [] plaintext = cipher.doFinal (cipherBytes);
I use class Base64 to encode/decode String <--> byte[]
Any idea?
thanks
private static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
private static int KEY_LENGTH = 64;
public static SecretKey deriveKeyDES() {
try {
long start = System.currentTimeMillis();
KeyGenerator kgen = KeyGenerator.getInstance("DES");
kgen.init(KEY_LENGTH);
SecretKey result = kgen.generateKey();
long elapsed = System.currentTimeMillis() - start;
return result;
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
public static String encrypt(String plaintext, SecretKey key) {
try {
long start = System.currentTimeMillis();
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));
long elapsed = System.currentTimeMillis() - start;
return toBase64(cipherText);
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static String toBase64(byte[] bytes) {
return Base64.encodeToString(bytes, Base64.NO_WRAP).trim();
}
public static String decrypt(String ciphertext, SecretKey key) {
try {
byte[] cipherBytes = fromBase64(ciphertext);
long start = System.currentTimeMillis();
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
cipher.update(cipherBytes);
// This is where I get exception
byte[] plaintext = cipher.doFinal(cipherBytes);
String plainrStr = new String(plaintext, "UTF-8").trim();
long elapsed = System.currentTimeMillis() - start;
return plainrStr;
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static byte[] fromBase64(String base64) {
return Base64.decode(base64, Base64.NO_WRAP);
}
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
cipher.update(cipherBytes);
// byte[] plaintext = cipher.doFinal(cipherBytes);
// ^-- You shouldn't pass cipherBytes twice.
// v-- instead use the parameter-less method:
byte[] plaintext = cipher.doFinal();
Padding exception occur when the last cipher text block does not compute to valid plain text. This would happen if last ciphertext block is corrupted or the key is incorrect. For CBC mode it would also happen if the second to last ciphertext was altered (but you are using ECB mode encryption).
In your case, the deriveKeyDES() is always generating a random key. Although we didn't get the actual calls to the security methods, I would presume you use a different key for encryption and decryption. In that case there is a very high chance that the resulting plain text does not contain valid padding bytes.
Rasmus answer certainly points to an error in your code, and it would screw up your timings and return a the plain text two times, but it would not remove the BadPaddingException.
I had the same problem in one source code, and IllegalBlockSizeException in another one.
Solved this two problems by return encoding data like:
public String encrypt(String input) {
try {
byte[] inputBytes = input.getBytes("UTF-8");
byte[] enc = encryptCipher.doFinal(inputBytes);
// and problem was in return encoding. That's how i fixed it
return Base64.encodeToString(enc,Base64.DEFAULT);
.....
}
}
Give u a code for decrypt:
public String decrypt(String input) {
try {
byte[] dec = Base64.decode(input.getBytes(), Base64.DEFAULT);
//here had exception
byte[] utf8 = decryptCipher.doFinal(dec);
return new String(utf8,"UTF8");
} catch (IOException | BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
I should submit, that had BadPaddingException and IllegalBlockSizeException
only in decrypt method byte[] utf8 = decryptCipher.doFinal(dec); (u had exeption in the same place: byte[] plaintext = cipher.doFinal(cipherBytes);), but real wrong is in encrypt method(return value)
That's why i recommend u to use that code in encrypt method:
return Base64.encodeToString(enc,Base64.DEFAULT);
P.S Tried to a give full answer on your question.

Categories

Resources