Does this smali class decrypt data? what encryption is it using? - java

Q: Does this smali class decrypt data? what encryption is it using?
I need help finding out what this code uses to decrypt the file text it receives?
the encrypted text prints out as expected in a jumbled mess, is there a way to manually decrypt the text using the information I need help understanding?
package utils;
import android.util.Log;
import com.crashlytics.android.Crashlytics;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.io.FileUtils;
public class EFileIO {
private static byte[] df(byte[] var0, byte[] var1) throws Exception {
SecretKeySpec var2 = new SecretKeySpec(var0, "AES");
Cipher var3 = Cipher.getInstance("AES");
var3.init(2, var2);
return var3.doFinal(var1);
}
private static byte[] ef(byte[] var0, byte[] var1) throws Exception {
SecretKeySpec var2 = new SecretKeySpec(var0, "AES");
Cipher var3 = Cipher.getInstance("AES");
var3.init(1, var2);
return var3.doFinal(var1);
}
private static byte[] gk(String var0) throws Exception {
byte[] var1 = var0.getBytes("UTF-8");
KeyGenerator var2 = KeyGenerator.getInstance("AES");
SecureRandom var3 = SecureRandom.getInstance("SHA1PRNG", "Crypto");
var3.setSeed(var1);
var2.init(128, var3);
return var2.generateKey().getEncoded();
}
public static String rf(File var0) {
String var1 = "";
String var3;
String var5;
try {
byte[] var2 = df(gk("AIzaSyDVQJ323-Th1pPJIcDrSt0KYFMTuLJR7Vw"), FileUtils.readFileToByteArray(var0));
var3 = new String(var2, "UTF-8");
} catch (Exception var4) {
Crashlytics.log(6, "EFILEIO.java", "rf, mf.getName(): " + var0.getName());
Crashlytics.logException(var4);
var4.printStackTrace();
var5 = var1;
return var5;
}
var5 = var3;
return var5;
}
public static void wr(StringBuilder var0, File var1) {
try {
FileOutputStream var3 = new FileOutputStream(var1);
BufferedOutputStream var2 = new BufferedOutputStream(var3);
byte[] var5 = ef(gk("AIzaSyDVQJ323-Th1pPJIcDrSt0KYFMTuLJR7Vw"), var0.toString().trim().getBytes("UTF-8"));
StringBuilder var6 = new StringBuilder();
Log.e("FileIo", var6.append("wr: content ").append(var5).toString());
var2.write(var5);
var2.flush();
var2.close();
} catch (Exception var4) {
Crashlytics.log(6, "EFILEIO.java", "wr, mf.getName(): " + var1.getName());
Crashlytics.logException(var4);
var4.printStackTrace();
}

The (short) answer to your question is YES.
Your class (method wr) is encrypting a String (wrapped in a StringBuilder) with a fixed key and saves the ciphertext to a file on the disc. Another method (rf) is reading the file with the ciphertext, decrypts it with the fixed key and prints the
decrypted / plaintext to the console.
These are the 5 methods in your class with a short description:
gk = generates a fixed 16 byte (128 bit) long key for AES en-/decryption
ef = encrypts a byte array with the generated key
df = decrypts a byte array with the generated key
wr = writes the encrypted byte array (using method ef) to a file on the disc
rf = reads the contents of a file to a byte array, decrypts it with method df and shows the decrypted text
The class uses the AES/ECB/PKCS5PADDING mode for encryption (I done the decryption manually on OpenJDK 11, so maybe the mode has another name with your crypto service provider on Android). The initialisation in methods ef + df with
"Cipher.getInstance("AES")" results in the "standard" ECB-PKCS5PADDING mode which is insecure and should be no longer used.
If you created a ciphertextfile "cipher.dat" you can use this simple program to decrypt the content and show it on the console (there is no proper exception handling...):
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class SimpleDecryption {
public static void main(String[] args) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, IOException, BadPaddingException, IllegalBlockSizeException {
System.out.println("Simple decryption method for\n" +
"https://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java");
String filename = "cipher.dat";
byte[] fixedKey = hexStringToByteArray("e409c02fb48745a14f5e1c03e3c6f0ca");
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
SecretKeySpec secretKeySpec = new SecretKeySpec(fixedKey, "AES");
aesCipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
System.out.println("decrypted text: " + new String(aesCipher.doFinal(Files.readAllBytes(Paths.get(filename))),"UTF-8"));
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i + 1), 16));
}
return data;
}
}
Sample output:
Simple decryption method for
https://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java
decrypted text: This text needs to get encrypted

Related

DES encryption error in Java (Illegal base64 character 20)

I am trying to make a little encryption/decryption software for my APCS-A final project. I have most of it done with various text ciphers and such, but I am trying to get DES encryption to work as like the big thing. I couldn't get it working in the main program so I created its own little thing to try to learn and test it first. I think I've gotten decently far, but I am getting stuck on an error that I can't figure out.
import java.util.Scanner;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.*;
import java.util.Base64;
public class BigETest
{
public static void main(String[]args) throws NoSuchAlgorithmException,NoSuchPaddingException,InvalidKeyException,IllegalBlockSizeException,BadPaddingException
{
Scanner kbd = new Scanner(System.in);
System.out.print("Enter text: ");
String t = kbd.nextLine();
String[] rets = en(t);
System.out.println("Encrypted: "+ rets[0]);
System.out.println("Key: " + rets[1]);
String dec = de(rets[0],rets[1]);
System.out.println("Decrypted: "+dec);
}
public static String[] en(String inText) throws BadPaddingException,IllegalBlockSizeException,InvalidKeyException,NoSuchPaddingException,NoSuchAlgorithmException
{
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
SecretKey key = keyGen.generateKey();
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] text = Base64.getUrlDecoder().decode(inText);
byte[] encryptedBytes = cipher.doFinal(text);
String encrypted = new String(Base64.getUrlEncoder().encodeToString(encryptedBytes));
byte[] rawKey = key.getEncoded();
String stringKey = new String(Base64.getUrlEncoder().encodeToString(rawKey));
String[] ret = {encrypted,stringKey};
return ret;
}
public static String de(String inText, String inKey) throws BadPaddingException,IllegalBlockSizeException,InvalidKeyException,NoSuchPaddingException,NoSuchAlgorithmException
{
byte[] keyB = Base64.getUrlDecoder().decode(inKey);
SecretKey key = new SecretKeySpec(keyB, "DES");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] text = Base64.getUrlDecoder().decode(inText);
byte[] fin = cipher.doFinal(text);
String dec = new String(Base64.getUrlEncoder().encodeToString(fin));
return dec;
}
}
The code works sometimes if the input is short and doesn't have spaces in it
Enter text: test
Encrypted: BOM9tFOUfWc=
Key: bq2ooSbc1n8=
Decrypted: test
but falls apart if the input is a bit longer
Enter text: BigTest
Encrypted: jme0nIAHXyA=
Key: 90UxVwetj2g=
Decrypted: BigTess=
And then gives me an error if there are any spaces
Enter text: bigger test
java.lang.IllegalArgumentException: Illegal base64 character 20
at java.base/java.util.Base64$Decoder.decode0(Base64.java:746)
at java.base/java.util.Base64$Decoder.decode(Base64.java:538)
at java.base/java.util.Base64$Decoder.decode(Base64.java:561)
at BigETest.en(BigETest.java:34)
at BigETest.main(BigETest.java:20)
I have tried changing things up and looked around both on here and just around anyplace I could find on Google for some answers, but nothing seems to be working. Any help would be greatly appreciated.

Node JS encryption code to Java encryption code

I'm trying to find the similar java code for the below Node JS code,
Node JS Code:
var crypto = require('crypto');
var mykey = crypto.createCipher('aes-128-ecb', 'XXXXXXXX00000000');
var mystr = mykey.update('HelloWorld', 'utf8', 'hex')
mystr += mykey.final('hex');
console.log(mystr);
Encryption Result: ce25d577457cf8113fa4d9eb16379529
Java Code:
public static String toHex(String arg) throws UnsupportedEncodingException {
return String.format("%x", new BigInteger(1, arg.getBytes("UTF-8")));
}
public static void main(String args[]) throws Exception{
byte[] key = "XXXXXXXX".getBytes();
String message = "HelloWorld";
try {
key = Arrays.copyOf(key, 16);
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte encstr[] = cipher.update(message.getBytes());
String encData = new String(encstr, "UTF-8");
encData = toHex(encData);
byte encstr2[] = cipher.doFinal();
String encData2 = new String(encstr2);
encData = encData + toHex(encData2);
System.out.println(encData);
} catch (NoSuchAlgorithmException nsae) {
throw new Exception("Invalid Java Version");
} catch (NoSuchPaddingException nse) {
throw new Exception("Invalid Key");
}
}
Encryption Result: 056efbfbdefbfbd7c7760efbfbdefbfbdefbfbd39262cefbfbdefbfbd5166
Taking up the comments of #Robert and #Topaco I wrote a simple decryption program that is working for the given password 'XXXXXXXX00000000'.
Please keep in mind that this progrsm is using UNSECURE AES ECB mode and UNSECURE MD5 hash algorithm.
The program does NOT provide any proper exception handling.
This is the result:
ciphertext Java: ce25d577457cf8113fa4d9eb16379529
ciphertext NodeJS: ce25d577457cf8113fa4d9eb16379529
My code:
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MainSo {
public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
System.out.println("https://stackoverflow.com/questions/63263081/node-js-encryption-code-to-java-encryption-code");
String plaintext = "HelloWorld";
String keyString = "XXXXXXXX00000000"; // 16 chars
byte[] key = keyString.getBytes(StandardCharsets.UTF_8);
// md5 hashing is unsecure !!
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] keyMd5 = md.digest(key);
// aes ecb mode encryption is unsecure
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyMd5, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
System.out.println("ciphertext Java: " + bytesToHex(ciphertext));
System.out.println("ciphertext NodeJS: " + "ce25d577457cf8113fa4d9eb16379529");
}
private static String bytesToHex(byte[] bytes) {
// service method for displaying a byte array as hex string
StringBuffer result = new StringBuffer();
for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
return result.toString();
}
}

How to encrypt and decrypt String with my passphrase in Java (Pc not mobile platform)? [duplicate]

This question already has answers here:
Java 256-bit AES Password-Based Encryption
(9 answers)
Closed 2 years ago.
I want to encrypt a string and then put it on a file. Also want to decrypt it when I want. I don’t need very strong security. I just want to make it harder to get my data others.
I tried several ways. Here are these.
Md5 Encryption:
How to hash a string in Android?
public static final String md5(final String toEncrypt) {
try {
final MessageDigest digest = MessageDigest.getInstance("md5");
digest.update(toEncrypt.getBytes());
final byte[] bytes = digest.digest();
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(String.format("%02X", bytes[i]));
}
return sb.toString().toLowerCase();
} catch (Exception exc) {
return ""; // Impossibru!
}
}
I tried this function and able to encrypt a string but I can’t decrypt data from it. So it is not the solution.
DES Encryption:
Encrypt and decrypt a String in java
Here passphrase is Auto generated. Is always passphrase will same on all time? Then where is my security. So it is not my solution too.
AES Encryption:
How do I encrypt/decrypt a string with another string as a password?
I also tried Aes from this link. Here key is also auto generated?
Is there any other way?
package com.example;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class StrongAES
{
public void run()
{
try
{
String text = "Hello World";
String key = "Bar12345Bar12345"; // 128 bit key
// Create key and cipher
Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
// encrypt the text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(text.getBytes());
System.err.println(new String(encrypted));
// decrypt the text
cipher.init(Cipher.DECRYPT_MODE, aesKey);
String decrypted = new String(cipher.doFinal(encrypted));
System.err.println(decrypted);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
StrongAES app = new StrongAES();
app.run();
}
}
package com.ezeon.util.gen;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.*;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
/*** Encryption and Decryption of String data; PBE(Password Based Encryption and Decryption)
* #author Vikram
*/
public class CryptoUtil
{
Cipher ecipher;
Cipher dcipher;
// 8-byte Salt
byte[] salt = {
(byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
(byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03
};
// Iteration count
int iterationCount = 19;
public CryptoUtil() {
}
/**
*
* #param secretKey Key used to encrypt data
* #param plainText Text input to be encrypted
* #return Returns encrypted text
* #throws java.security.NoSuchAlgorithmException
* #throws java.security.spec.InvalidKeySpecException
* #throws javax.crypto.NoSuchPaddingException
* #throws java.security.InvalidKeyException
* #throws java.security.InvalidAlgorithmParameterException
* #throws java.io.UnsupportedEncodingException
* #throws javax.crypto.IllegalBlockSizeException
* #throws javax.crypto.BadPaddingException
*
*/
public String encrypt(String secretKey, String plainText)
throws NoSuchAlgorithmException,
InvalidKeySpecException,
NoSuchPaddingException,
InvalidKeyException,
InvalidAlgorithmParameterException,
UnsupportedEncodingException,
IllegalBlockSizeException,
BadPaddingException {
//Key generation for enc and desc
KeySpec keySpec = new PBEKeySpec(secretKey.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
// Prepare the parameter to the ciphers
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
//Enc process
ecipher = Cipher.getInstance(key.getAlgorithm());
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
String charSet = "UTF-8";
byte[] in = plainText.getBytes(charSet);
byte[] out = ecipher.doFinal(in);
String encStr = new String(Base64.getEncoder().encode(out));
return encStr;
}
/**
* #param secretKey Key used to decrypt data
* #param encryptedText encrypted text input to decrypt
* #return Returns plain text after decryption
* #throws java.security.NoSuchAlgorithmException
* #throws java.security.spec.InvalidKeySpecException
* #throws javax.crypto.NoSuchPaddingException
* #throws java.security.InvalidKeyException
* #throws java.security.InvalidAlgorithmParameterException
* #throws java.io.UnsupportedEncodingException
* #throws javax.crypto.IllegalBlockSizeException
* #throws javax.crypto.BadPaddingException
*/
public String decrypt(String secretKey, String encryptedText)
throws NoSuchAlgorithmException,
InvalidKeySpecException,
NoSuchPaddingException,
InvalidKeyException,
InvalidAlgorithmParameterException,
UnsupportedEncodingException,
IllegalBlockSizeException,
BadPaddingException,
IOException {
//Key generation for enc and desc
KeySpec keySpec = new PBEKeySpec(secretKey.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
// Prepare the parameter to the ciphers
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
//Decryption process; same key will be used for decr
dcipher = Cipher.getInstance(key.getAlgorithm());
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
byte[] enc = Base64.getDecoder().decode(encryptedText);
byte[] utf8 = dcipher.doFinal(enc);
String charSet = "UTF-8";
String plainStr = new String(utf8, charSet);
return plainStr;
}
public static void main(String[] args) throws Exception {
CryptoUtil cryptoUtil=new CryptoUtil();
String key="ezeon8547";
String plain="This is an important message";
String enc=cryptoUtil.encrypt(key, plain);
System.out.println("Original text: "+plain);
System.out.println("Encrypted text: "+enc);
String plainAfter=cryptoUtil.decrypt(key, enc);
System.out.println("Original text after decryption: "+plainAfter);
}
}
I just want to add that if you want to somehow store the encrypted byte array as String and then retrieve it and decrypt it (often for obfuscation of database values) you can use this approach:
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class StrongAES
{
public void run()
{
try
{
String text = "Hello World";
String key = "Bar12345Bar12345"; // 128 bit key
// Create key and cipher
Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
// encrypt the text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(text.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b: encrypted) {
sb.append((char)b);
}
// the encrypted String
String enc = sb.toString();
System.out.println("encrypted:" + enc);
// now convert the string to byte array
// for decryption
byte[] bb = new byte[enc.length()];
for (int i=0; i<enc.length(); i++) {
bb[i] = (byte) enc.charAt(i);
}
// decrypt the text
cipher.init(Cipher.DECRYPT_MODE, aesKey);
String decrypted = new String(cipher.doFinal(bb));
System.err.println("decrypted:" + decrypted);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
StrongAES app = new StrongAES();
app.run();
}
}
My requirement was to keep the password in a config file in encrypted form and decrypt when the program runs. For this I used the jasypt library (jasypt-1.9.3.jar). This is a very good library and we can accomplish the task with just 4 lines of code.
First, after adding jar to my project I imported the below library.
import org.jasypt.util.text.AES256TextEncryptor;
Then I created the below method. I then called this method by passing the text which I need to encrypt in password parameter. Using aesEncryptor.encrypt method, I encrypted the password which is stored to the myEncryptedPassword variable.
public void EncryptPassword(String password)
{
AES256TextEncryptor aesEncryptor = new AES256TextEncryptor();
aesEncryptor.setPassword("mypassword");
String myEncryptedPassword = aesEncryptor.encrypt(password);
System.out.println(myEncryptedPassword );
}
You might have noticed the method setPassword method and the value mypassword is used in the above code. This is to make sure that no one can decrypt the password even if they use the encrypted password using the same library.
Now I can see the value in the myEncryptedPassword variable something like h9oJ4P5P8ToRy38wvK11PUQCBrT1oH/zbMWuMrbOlI0rfZrj+qSg6f/u0jctOs/ZUf9t3shiwnEt05/nq8bnag==. This is the encrypted password. Keep this value in the config file.
I then created the below method to decrypt the password to be used in my program. The value of passwordFromConfigFile is the encrypted text which I got from the EncryptPassword method. Note that you have to use the same password in the aesEncryptor.setPassword method that you used to encrypt the password.
public String DecryptPassword(String passwordFromConfigFile)
{
AES256TextEncryptor aesEncryptor = new AES256TextEncryptor();
aesEncryptor.setPassword("mypassword");
String decryptedPassword = aesEncryptor.decrypt(passwordFromConfigFile);
return decryptedPassword;
}
The variable decryptedPassword will now have the decrypted password value.
The code marked as the solution did not work for me. This was my solution.
/*
* http://www.java2s.com/Code/Java/Security/EncryptingaStringwithDES.htm
* https://stackoverflow.com/questions/23561104/how-to-encrypt-and-decrypt-string-with-my-passphrase-in-java-pc-not-mobile-plat
*/
package encryptiondemo;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
*
* #author zchumager
*/
public class EncryptionDemo {
Cipher ecipher;
Cipher dcipher;
EncryptionDemo(SecretKey key) throws Exception {
ecipher = Cipher.getInstance("AES");
dcipher = Cipher.getInstance("AES");
ecipher.init(Cipher.ENCRYPT_MODE, key);
dcipher.init(Cipher.DECRYPT_MODE, key);
}
public String encrypt(String str) throws Exception {
// Encode the string into bytes using utf-8
byte[] utf8 = str.getBytes("UTF8");
// Encrypt
byte[] enc = ecipher.doFinal(utf8);
// Encode bytes to base64 to get a string
return new sun.misc.BASE64Encoder().encode(enc);
}
public String decrypt(String str) throws Exception {
// Decode base64 to get bytes
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
byte[] utf8 = dcipher.doFinal(dec);
// Decode using utf-8
return new String(utf8, "UTF8");
}
public static void main(String args []) throws Exception
{
String data = "Don't tell anybody!";
String k = "Bar12345Bar12345";
//SecretKey key = KeyGenerator.getInstance("AES").generateKey();
SecretKey key = new SecretKeySpec(k.getBytes(), "AES");
EncryptionDemo encrypter = new EncryptionDemo(key);
System.out.println("Original String: " + data);
String encrypted = encrypter.encrypt(data);
System.out.println("Encrypted String: " + encrypted);
String decrypted = encrypter.decrypt(encrypted);
System.out.println("Decrypted String: " + decrypted);
}
}
Use This This Will work For sure
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class ProtectedConfigFile {
private static final char[] PASSWORD = "enfldsgbnlsngdlksdsgm".toCharArray();
private static final byte[] SALT = { (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12, (byte) 0xde, (byte) 0x33,
(byte) 0x10, (byte) 0x12, };
public static void main(String[] args) throws Exception {
String originalPassword = "Aman";
System.out.println("Original password: " + originalPassword);
String encryptedPassword = encrypt(originalPassword);
System.out.println("Encrypted password: " + encryptedPassword);
String decryptedPassword = decrypt(encryptedPassword);
System.out.println("Decrypted password: " + decryptedPassword);
}
private static String encrypt(String property) throws GeneralSecurityException, UnsupportedEncodingException {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
return base64Encode(pbeCipher.doFinal(property.getBytes("UTF-8")));
}
private static String base64Encode(byte[] bytes) {
// NB: This class is internal, and you probably should use another impl
return new BASE64Encoder().encode(bytes);
}
private static String decrypt(String property) throws GeneralSecurityException, IOException {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
}
private static byte[] base64Decode(String property) throws IOException {
// NB: This class is internal, and you probably should use another impl
return new BASE64Decoder().decodeBuffer(property);
}
}
Both Encrypt and Decrypt with AES and DES Algoritham ,This worked for me perfectly
GithubLink: Java Code For Encryption and Decryption
package decrypt;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/* Decrypt encrypted string into plain string with aes and Des algoritham*/
public class Decrypt {
public String decrypt(String str,String k) throws Exception {
// Decode base64 to get bytes
Cipher dcipher = Cipher.getInstance("AES");
Key aesKey = new SecretKeySpec(k.getBytes(), "AES");
dcipher.init(dcipher.DECRYPT_MODE, aesKey);
//System.out.println(aesKey);
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
byte[] utf8 = dcipher.doFinal(dec);
//System.out.println(utf8);
// Decode using utf-8
return new String(utf8, "UTF8");
}
public String encrypt(String str,String k) throws Exception {
Cipher ecipher = Cipher.getInstance("AES");
Key aeskey = new SecretKeySpec(k.getBytes(),"AES");
byte[] utf8 = str.getBytes("UTF8");
ecipher.init(ecipher.ENCRYPT_MODE, aeskey );
byte[] enc = ecipher.doFinal(utf8);
return new sun.misc.BASE64Encoder().encode(enc);
}
public String encrypt(String str,String k,String Algo) throws Exception {
Cipher ecipher = Cipher.getInstance(Algo);
Key aeskey = new SecretKeySpec(k.getBytes(),Algo);
byte[] utf8 = str.getBytes("UTF8");
ecipher.init(ecipher.ENCRYPT_MODE, aeskey );
byte[] enc = ecipher.doFinal(utf8);
return new sun.misc.BASE64Encoder().encode(enc);
}
public String decrypt(String str,String k,String Algo) throws Exception {
// Decode base64 to get bytes
Cipher dcipher = Cipher.getInstance(Algo);
Key aesKey = new SecretKeySpec(k.getBytes(), Algo);
dcipher.init(dcipher.DECRYPT_MODE, aesKey);
//System.out.println(aesKey);
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
byte[] utf8 = dcipher.doFinal(dec);
//System.out.println(utf8);
// Decode using utf-8
return new String(utf8, "UTF8");
}
public static void main(String args []) throws Exception
{
String original = "rakesh";
String data = "CfPcX0G+e7TLKKMyyvrvrQ==";
String k = "qertyuiopasdfghw"; //AES key length must be 16
String k1 = "qertyuio"; // DES key length must be 8
String data1 = "rakesh";
String data2 = "nAtvNq7uHKE=";
String Algo= "DES";
String Algo1= "AES";
Decrypt decrypter = new Decrypt();
System.out.println("Original String: " + original);
System.out.println("encrypted String in DES: " + decrypter.encrypt(data1,
k1,Algo));
System.out.println("Decrypted String in DES: " + decrypter.decrypt(data2,
k1,Algo));
System.out.println("encrypted String in AES: " + decrypter.encrypt(data1,
k,Algo1));
System.out.println("Decrypted String in AES: " + decrypter.decrypt(data,
k,Algo1));
}
}

sending rc4 encrypted api call in java

I am trying to make an api call in java using these steps:
json encode
RC4 encryption
base64 encoding
I am currently using the same system in php and its working correctly:
$enc_request = base64_encode(openssl_encrypt(json_encode($request_params), "rc4", $this->_app_key));
But when I use the same system in java, the results are not as expected. Here's my code:
//json encoding
JSONObject obj = new JSONObject();
obj.put("email", username);
obj.put("password", password);
obj.put("action", "login");
//function to encode base64
private String getBase64Encoded(String encryptedJsonString)
{
byte[] encoded = Base64.encodeBase64(encryptedJsonString.getBytes());
String encodedString = new String(encoded);
return encodedString;
}
//function to encrypt in RC4
private String getRC4EncryptedString2(String string, String key) throws Exception
{
Cipher cipher = Cipher.getInstance("RC4");
SecretKeySpec rc4Key = new SecretKeySpec(key.getBytes(), "RC4");
cipher.init(Cipher.ENCRYPT_MODE, rc4Key);
byte[] cipherText = cipher.update(string.getBytes());
return new String(cipherText);
}
I was able to identify the problem upto the RC4 encryption which is not returning the same result as the php version.
I've been battling this for 2 days now. I hope I have not missed any stupid thing because this should be straight-forward.
Thanks
You should use a byte[] not a String to hold intermediate byte array values. A String is for text, not raw data, and will attempt to decode the bytes as character data using your system's default character set (at least, the single-parameter String constructor will). Same with String.getBytes().
Just return cipherText directly from getRC4EncryptedString2(), and pass it directly to getBase64Encoded(). There's a reason those encoders operate on byte arrays, and that reason is not so that you can garble the data by applying a character encoding to it in between.
The same goes for the key you are passing to getRC4EncryptedString2(). At the bare minimum use String.getBytes("ISO-8859-1") or something (assuming that your key is actually text and not yet another garbled byte array). The no-parameter version of getBytes() returns the text encoded using your system's default character set, which is not guaranteed to be what you want.
That also all applies to the String you are returning from your base 64 encoder. I don't know what base 64 encoder you are using, but make sure you specify the character set to the String constructor. Most likely you will be OK, purely by coincidence, but you should always specify a character set when converting to/from String and raw bytes. And that, of course, assumes that your base 64 encoder returns text, rather than bytes in the range 0-63.
The general point here is you can't just convert back and forth from String to byte[]. A String is for text and it's representation as a byte[] depends on the character encoding.
I am able to achieve this using the following code. Hope this helps!
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.codec.DecoderException;
import org.bouncycastle.util.encoders.Hex;
import org.json.JSONException;
import org.json.JSONObject;
public class RC4Algo {
public static void main(String args[])throws IOException, NoSuchAlgorithmException, DecoderException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, JSONException
{
decryptRC4();
}
static String decryptRC4() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, JSONException{
//byte[] plainBytes = "testString".getBytes();
//json encoding
JSONObject obj = new JSONObject();
obj.put("email", "username");
obj.put("password", "password");
obj.put("action", "login");
byte [] plainBytes = obj.toString().getBytes();
String hashedKey = hashedData("thisismysecretkey");
//Generate a new key using KeyGenerator
/*KeyGenerator rc4KeyGenerator = KeyGenerator.getInstance("RC4");
SecretKey key = rc4KeyGenerator.generateKey();*/
Key key = new SecretKeySpec(Hex.decode(hashedKey), "RC4");
// Create Cipher instance and initialize it to encrytion mode
Cipher cipher = Cipher.getInstance("RC4"); // Transformation of the algorithm
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherBytes = cipher.doFinal(plainBytes);
String encoded = encodeBase64(cipherBytes);
String decoded = decodeBase64(encoded);
// Reinitialize the Cipher to decryption mode
cipher.init(Cipher.DECRYPT_MODE,key, cipher.getParameters());
byte[] plainBytesDecrypted = cipher.doFinal(Hex.decode(decoded));
System.out.println("Decrypted Data : "+new String(plainBytesDecrypted));
return new String(plainBytesDecrypted);
}
static String decodeBase64(String encodedData){
byte[] b = Base64.getDecoder().decode(encodedData);
String decodedData = DatatypeConverter.printHexBinary(b);
return decodedData;
}
static String encodeBase64(byte[] data){
byte[] b = Base64.getEncoder().encode(data);
String encodedData = new String(b);
/*String encodedData = DatatypeConverter.printHexBinary(b);*/
return encodedData;
}
static String hashedData(String key) throws NoSuchAlgorithmException{
String password = key;
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(password.getBytes());
byte byteData[] = md.digest();
//convert the byte to hex format method 1
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
//convert the byte to hex format method 2
StringBuffer hexString = new StringBuffer();
for (int i=0;i<byteData.length;i++) {
String hex=Integer.toHexString(0xff & byteData[i]);
if(hex.length()==1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
}
Output:

Why is the ciphertext 32 bytes long when encrypting 16 bytes with AES?

I use encryption AES algorithm, when i encrypt 16 byte(one block) the result is 32 byte.
Is this ok?
My source code that i used is:
package net.sf.andhsli.hotspotlogin;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* Usage:
* <pre>
* String crypto = SimpleCrypto.encrypt(masterpassword, cleartext)
* ...
* String cleartext = SimpleCrypto.decrypt(masterpassword, crypto)
* </pre>
* #author ferenc.hechler
*/
public class SimpleCrypto {
public static String encrypt(String seed, String cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
public static String decrypt(String seed, String encrypted) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static byte[] toByte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
public static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2*buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private final static String HEX = "0123456789ABCDEF";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
}
If you look at the specification section 5 then you can see that the input, output and state are all 128 bit. The only thing that varies is the size of the key: 128, 196 or 256 bits. So encrypting a 16 byte input state will yield a 16 byte output state.
Are you sure you aren't mixing it up with the length in hexadecimal notation or similar? If it is in hexadecimal notation then it's correct because for each byte two characters are needed to represent it: 00-FF (for the range 0-255). So, for example, 16 bytes would be encoded as 32 characters in hexadecimal notation.
Another way you can test if the encryption is correct is by doing the equivalent decryption, see if it matches the plaintext input string.
Anyway, it does the correct thing. Here's a test:
public static void main(String[] args) {
try {
String plaintext = "Hello world", key = "test";
String ciphertext = encrypt(key, plaintext);
String plaintext2 = decrypt(key, ciphertext);
System.out.println("Encrypting '" + plaintext +
"' yields: (" + ciphertext.length() + ") " + ciphertext);
System.out.println("Decrypting it yields: " + plaintext2);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
Which yields:
Encrypting 'Hello world' yields: (32)
5B68978D821FCA6022D4B90081F76B4F
Decrypting it yields: Hello world
AES defaults to ECB mode encryption with PKCS#7 compatible padding mode (for all providers observed so far). ECB and CBC mode encryption require padding if the input is not precisely a multiple of the blocksize in size, with 16 being the block size of AES in bytes.
Unfortunately there might be no way for the unpadding mechanism to distinguish between padding and data; the data itself may represent valid padding. So for 16 bytes of input you will get another 16 bytes of padding. Padding modes that are deterministic such as PKCS#7 always pad with 1 up to [blocksize] bytes.
If you look at int output = cipher.getOutputSize(16); you will get back 32 bytes. Use "AES/ECB/NoPadding" during decipher to see the padding bytes (e.g. 4D61617274656E20426F64657765732110101010101010101010101010101010).
You are better off when you fully specify the algorithm. Previously most developers would go for "AES/CBC/PKCS5Padding" but nowadays "AES/GCM/NoPadding" should probably be used because it offers message authentication and integrity. Otherwise you will keep guessing which mode is actually used.
Note that using ECB mode is not safe as an attacker can retrieve information from the cipher text; identical blocks of plain text encode to identical blocks of cipher text.
package com.cipher;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Encrypt {
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
// TODO Auto-generated method stub
String s="You are doing encryption at deep level";
SecureRandom sr=SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(s.getBytes());
byte[] k=new byte[128/8];
sr.nextBytes(k);
SecretKeySpec spec=new SecretKeySpec(k,"AES");
byte[] iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
IvParameterSpec ivs=new IvParameterSpec(iv);
Cipher cps=Cipher.getInstance("AES/CBC/PKCS5Padding");
cps.init(Cipher.ENCRYPT_MODE,spec,ivs);
byte[] iv2=cps.doFinal(s.getBytes());
System.out.println("En"+iv2);
Cipher cpr=Cipher.getInstance("AES/CBC/PKCS5Padding");
cpr.init(Cipher.DECRYPT_MODE, spec,ivs);
byte[] iv3=cpr.doFinal(iv2);
String ds=new String(iv3);
System.out.println(ds);
}
}

Categories