AES with CBC Mode Block Cipher - java

import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
class CryptAES {
static final String cipher_type = "AES/CBC/PKCS5Padding";
public static void main(String[] args) {
String key = args[0];
String iv = args[1];
String data = args[2];
byte[] enc = encode(key, iv, data.getBytes());
byte[] dec = decode(key, iv, enc);
for (int i = 0; i < enc.length; i++) {
System.out.printf("%02x", enc[i]);
}
System.out.println();
System.out.println(new String(dec));
}
public static byte[] encode(String skey, String iv, byte[] data) {
return process(Cipher.ENCRYPT_MODE, skey, iv, data);
}
public static byte[] decode(String skey, String iv, byte[] data) {
return process(Cipher.DECRYPT_MODE, skey, iv, data);
}
private static byte[] process(int mode, String skey, String iv, byte[] data) {
SecretKeySpec key = new SecretKeySpec(skey.getBytes(), "AES");
AlgorithmParameterSpec param = new IvParameterSpec(iv.getBytes());
try {
Cipher cipher = Cipher.getInstance(cipher_type);
cipher.init(mode, key, param);
return cipher.doFinal(data);
} catch (Exception e) {
System.err.println(e.getMessage());
throw new RuntimeException(e);
}
}
}
exception in thread main java.lang.arrayindexoutofboundsexception index out of bounds for length 0
exception in thread main java.lang.arrayindexoutofboundsexception index out of bounds for length 0

As #rzwitserloot pointed out, you need to check if there have been arguments passed into the application in the command line.
You should always be checking for null/empty/invalid values when a user can give input. A simple example on how to prevent the original error and throw a more meaningful error is below:
public static void main(String[] args) {
if (null == args || args.length != 3) {
throw new IOException("Please add arguments key, iv and data");
}
String key = args[0];
String iv = args[1];
String data = args[2];
...
}
You may want to be able to not have any inputs, or only input 1/2 out of the 3 arguments. For that you need to check if the argument value exists and then access it.

Related

AES Decryption - original characters replaced by weird characters

I am trying to encrypt a json string using the below code:
public static final Charset CHARSET = StandardCharsets.UTF_8;
public static Cipher getDefaultCipherInstance(int mode)
throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException {
byte[] key = Base64.getDecoder().decode("encryptionKey".getBytes(CHARSET));
IvParameterSpec iv = new IvParameterSpec("RandomVector".getBytes(CHARSET));
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(mode, skeySpec, iv);
return cipher;
}
public static String encryptText(String plainText) {
try {
Cipher cipher = getDefaultCipherInstance(Cipher.ENCRYPT_MODE);
byte[] cipherText = cipher.doFinal(plainText.getBytes(CHARSET));
return new String(Base64.getEncoder().encode(cipherText));
} catch (Exception ex) {
LOG.error("Problem encryptingText",ex);
return null;
}
}
public static String decryptText(String cipherText) {
try {
Cipher cipher = getDefaultCipherInstance(Cipher.DECRYPT_MODE);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(cipherText));
return new String(decrypted);
} catch (Exception ex) {
LOG.debug("Problem during decrypt text: " + cipherText, ex);
return null;
}
}
It works fine most of the times but sometimes I see weird characters in the decrypted string like "\u001A=`�["Q�\u001D)��ۉ�d":\ , this is corrupting the json and we are not able to deserialize json to object.
Any idea what could be the problem here?
Update::
I added the following code to test encryption/decryption in a concurrent(multi-threaded) environment:
public class EncryptionTest {
#Test
public void test() throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(25);
String text = "Hi there Ithanks for cimngng";
for(int i = 0; i < 5; i++) {
System.out.println("Iteration: " + i);
executorService.submit(new EncryptionRunnable(text));
}
Thread.currentThread().join();
}
static class EncryptionRunnable implements Runnable {
private String text;
public EncryptionRunnable(String text) {
this.text = text;
}
#Override
public void run() {
int i = 0;
while(i < 10) {
String encrypted = encryptText(text);
String prefix = Thread.currentThread().getName() + "::" + i + ":: ";
System.out.println(prefix + "encrypted:: " + encrypted);
try {
System.out.println(prefix + "decrypted:: " + decryptText(encrypted));
} catch (Exception e) {
System.out.println(prefix + "decrypted:: ");
e.printStackTrace();
}
i++;
}
}
}
}
I see that all of the outputs were correct but for one of the output, it produced strange characters like this:
pool-1-thread-5::0:: decrypted:: ȼ����S}�q��j� for cimngng
Even the encrypted string is same for every encryption. Can anybody help now? Note: I am using the same cipher instance for encryption and same for decryption.
Here is a snapshot of the output of the above code.

When encoding the password, always return null value

I want to encode my password using an encryption key. but I got a null value, when printing the encoded password. I have attached my code below:
public class FirstJava {
private static final Long ENCRYPTION_KEY = 29190210908917L;
public static String encrypt(String strToEncrypt, byte[] key) {
if (strToEncrypt == null)
return strToEncrypt;
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes()));
} catch (Exception exception) {
System.out.println("ERROR");
}
return null;
}
public static void main(String[] args) {
String password = "12345678";
byte[] arr = String.valueOf(ENCRYPTION_KEY).getBytes();
String passwordEnc = encrypt(password,arr);
System.out.println("passwordEnc============= "+passwordEnc);
}
}
AES only supports key sizes of 16, 24 or 32 bytes. Your key length is 14, add 2 more digits to your key and it will work.
private static final Long ENCRYPTION_KEY = 2919021090891712L; //16 bytes

Firebase encrypted Chat app Runtime error. DatasnapShot to string?

I am trying to take in a string(message) and encrypt it then send it to the firebase database. Then when the app loads the data should be displayed to the user un-encrypted. So the encrypted string lies on the server/database.
Im getting nul pointer exception because it seems when you use snapshot it calls the default message constructor which does not contain the text which i called for.Essentially datasnapshot calls the default constructor which does not let me call the attributes of the object in the actual constructor. Is there anyway around this ?
Once the app request the Method that will request the messages from the database.The App crashes. I try to de-crypt the messages from a String of bytes before i display them... The messages however will no display and the app crashes
Here's a link to a screenshot
http://ibb.co/hqSJFv
This is the method that gets called when the sign in is successful and request the messages from the database and displays them(this worked until i messed with decrypting) I want to read from DB and decrypt then display the messages
//READ DECRYPT AND DISPLAY THE MESSAGES
mChildEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
//called when new message is inserted into the list also
//triggered for every child message
EncryptoMessage encryptoMessage =
dataSnapshot.getValue(EncryptoMessage.class);
//get the text from the encryptomessage object store as string
String encryptedString = encryptoMessage.getText(); //value of
//encryptedString ends up empty
byte [] bytes = encryptedString.getBytes();
String str = null;
try {
str = new EncryptoMessage().decrypt(bytes);
} catch (Exception e) {
e.printStackTrace();
}
EncryptoMessage decryptedMessage = new EncryptoMessage();
decryptedMessage.setText(str);
mMessageAdapter.add(decryptedMessage);
}
This is the message from user input encrypted and stored as a string in DB. I coverted the btye[] to a string
//SEND CLICKED
// Send button sends a message and clears the EditText && Write to the
//Database
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// TODO: Send messages on click
//get the message the user enters
String messageText = mMessageEditText.getText().toString();
byte[] codedtext = new byte[0];
try {
//take that message and encrypt it
//codedtext now equal to byte array of messageText
codedtext = new EncryptoMessage().encrypt(messageText);
} catch (Exception e) {
e.printStackTrace();
}
//change the encrypted bytes into a string and send to the
//database
String str = new String(codedtext, StandardCharsets.UTF_8);
//Create an EncryptoMessage object for the message the user
//enters
EncryptoMessage encryptoMessage = new EncryptoMessage(str,
mUsername, null);
//add the new message object to the EncryptoChat database
mMsgDatabaseReference.push().setValue(encryptoMessage);
// Clear input box
mMessageEditText.setText("");
}
});
This is Encrypted message object class(with encryption)
package com.google.firebase.david.encryptochat; //firebase API
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
//**************************************
//THis class is our message object
//*****************************************
public class EncryptoMessage {
private String text;
private String name;
private String photoUrl;
public EncryptoMessage() {
// Default constructor required for calls to
//DataSnapshot.getValue(User.class)
}
// The encrypto message constructor to create the object
public EncryptoMessage(String text, String name, String photoUrl) {
this.text = text;
this.name = name;
this.photoUrl = photoUrl;
}
//Copy constuctor
/* public EncryptoMessage(EncryptoMessage EncryptoMessageCopy){
this(EncryptoMessageCopy.getText(), EncryptoMessageCopy.getName());
}*/
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhotoUrl() {
return photoUrl;
}
public void setPhotoUrl(String photoUrl) {
this.photoUrl = photoUrl;
}
//Encryption of the messages
public byte[] encrypt(String message) throws Exception {
final MessageDigest md = MessageDigest.getInstance("md5");
final byte[] digestOfPassword = md.digest("HG58YZ3CR9"
.getBytes("utf-8"));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
final byte[] plainTextBytes = message.getBytes("utf-8");
final byte[] cipherText = cipher.doFinal(plainTextBytes);
return cipherText;
}
//Decrypt
public String decrypt(byte[] message) throws Exception {
//get the bytes if the string passing in
//byte [] bytes = message.getBytes();
final MessageDigest md = MessageDigest.getInstance("md5");
final byte[] digestOfPassword = md.digest("HG58YZ3CR9"
.getBytes("utf-8"));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
final Cipher decipher =
Cipher.getInstance("DESede/CBC/PKCS5Padding");
decipher.init(Cipher.DECRYPT_MODE, key, iv);
final byte[] plainText = decipher.doFinal(message);
return new String(plainText, "UTF-8");
}
}
This is the error i get at runtime just when i sign in and display messages it crashes also
FATAL EXCEPTION: main
Process: com.google.firebase.david.encryptochat, PID: 8733
java.lang.NullPointerException: Attempt to invoke virtual method 'byte[] java.lang.String.getBytes()' on a null object reference
at com.google.firebase.david.encryptochat.MainActivity$4.onChildAdded(MainActivity.java:238)

java.security.InvalidKeyException: unknown key type passed to RSA

i am using shared preferences to store the user name and password in order to achieve onetime user authentication. I am encrypting and storing the data in shared pref file. Again i am decrypting them and validating the values every time the user open the application. It is working fine until the App is running on background.
If the user close the app from background i am again getting the login screen asking to input the user credentials.
Below is the error:
W/System.err: java.security.InvalidKeyException: unknown key type passed to RSA
W/System.err: at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineInit(CipherSpi.java:275)
W/System.err: at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineInit(CipherSpi.java:379)
W/System.err: at javax.crypto.Cipher.init(Cipher.java:661)
W/System.err: at javax.crypto.Cipher.init(Cipher.java:621)
Below is my encryption Algorithm. I am calling the genereteKey() method before comitting the data in to shared pref file and encrypting the data then commiting the data.
private final static String RSA = "RSA";
public static PublicKey uk;
public static PrivateKey rk;
public static void generateKey() throws Exception {
KeyPairGenerator gen = KeyPairGenerator.getInstance(RSA);
gen.initialize(512, new SecureRandom());
KeyPair keyPair = gen.generateKeyPair();
uk = keyPair.getPublic();
rk = keyPair.getPrivate();
}
private static byte[] encrypt(String text, PublicKey pubRSA) throws Exception {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.ENCRYPT_MODE, pubRSA);
return cipher.doFinal(text.getBytes());
}
public final static String encrypt(String text) {
try {
return byte2hex(encrypt(text, uk));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public final static String decrypt(String data) {
try {
return new String(decrypt(hex2byte(data.getBytes())));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static byte[] decrypt(byte[] src) throws Exception {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE, rk);
return cipher.doFinal(src);
}
public static String byte2hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = Integer.toHexString(b[n] & 0xFF);
if (stmp.length() == 1) hs += ("0" + stmp);
else
hs += stmp;
}
return hs.toUpperCase();
}
public static byte[] hex2byte(byte[] b) {
if ((b.length % 2) != 0) throw new IllegalArgumentException("hello");
byte[] b2 = new byte[b.length / 2];
for (int n = 0; n < b.length; n += 2) {
String item = new String(b, n, 2);
b2[n / 2] = (byte) Integer.parseInt(item, 16);
}
return b2;
}

Encrypting PE file with Java

I'm trying to make a file crypter in Java, and it's working perfectly with txt files, however when I try to encrypt an .exe file, the file is getting f*** up. I had write a simple hello world program in C++ which is printing "hello world" on the command prompt, I call it f(for sake of simplicity). The problem is that when I encrypt the file, and then decrypt it, it's corrupted I mean I can't run it I'm getting message that the file isn't compatible with the 64 architecture. Here is my Java code:
The main class(the program starts from here:
public class Main {
public static void main(String[] args) {
try{
FileLoader fl = new FileLoader("C:\\..\\f.exe");
fl.encrypt();
SecretKey key = fl.get_key();
FileLoader dk = new FileLoader("C:\\..\\encrypted.exe", key);
dk.decrypt();
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
The FileHandler is the class which I'm using to work with files
public class FileLoader {
private String fileName;
private byte[] b_file_data;
private String s_file_data;
private List<String> l_file_data;
private Path path;
private SecretKey key;
public FileLoader(String file_name) throws IOException {
this.fileName = file_name;
this.b_file_data = read_file_bytes();
path = Paths.get(this.fileName);
this.l_file_data = s_read_file_lines();
}
public FileLoader(String file_name, SecretKey key) throws IOException {
this.fileName = file_name;
this.key = key;
this.b_file_data = read_file_bytes();
path = Paths.get(this.fileName);
this.l_file_data = s_read_file_lines();
}
public SecretKey get_key(){
return this.key;
}
private byte[] read_file_bytes() throws IOException{
Path path = Paths.get(this.fileName);
return Files.readAllBytes(path);
}
public void write_to_file(byte[] Bytes) throws IOException{
Path path = Paths.get(this.fileName);
Files.write(path, Bytes);
}
public byte[] get_file_bytes() {
return this.b_file_data;
}
private List<String> s_read_file_lines() throws IOException {
Charset charset = Charset.forName("ISO-8859-1");
return Files.readAllLines(this.path, charset);
}
public List<String> get_file_lines() {
return this.l_file_data;
}
public String get_data_string(){
return get_file_lines().toString();
}
public void encrypt() throws Exception {
DES algorithm = new DES(read_file_bytes());
key = algorithm.get_key();
byte[] encrypted = algorithm.get_encrypted_data();
FileOutputStream out = new FileOutputStream(new File("encrypted.exe"));
out.write(encrypted);
}
public void decrypt() throws Exception {
DES algorithm = new DES(read_file_bytes());
key = algorithm.get_key();
byte[] decrypted = algorithm.get_decrypted_data();
FileOutputStream out = new FileOutputStream(new File("decrypted.exe"));
out.write(decrypted);
}
}
The DES class it is just implementing the cryptography algorithm
public class DES {
private KeyGenerator keyGen;
private SecretKey secretKey;
private Cipher cipher;
private byte[] bytes_to_encrypt;
private byte[] encrypted_bytes;
private byte[] decrypted_bytes;
public DES(byte[] bytes_to_encrypt) {
this.bytes_to_encrypt = bytes_to_encrypt;
generate_key();
init_cipher();
encrypt_text();
}
private void generate_key(){
try{
keyGen = KeyGenerator.getInstance("DES");
}catch(Exception e){
System.out.println(e.toString());
}
keyGen.init(56);
secretKey = keyGen.generateKey();
}
private void init_cipher(){
try{
cipher = Cipher.getInstance("DES");
}catch(Exception e){
System.out.println(e.toString());
}
}
private void encrypt_text(){
try{
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
encrypted_bytes = cipher.doFinal(bytes_to_encrypt);
}catch(Exception e){
System.out.println(e.toString());
}
}
private void decrypt_text(){
try{
cipher.init(Cipher.DECRYPT_MODE, secretKey);
decrypted_bytes = cipher.doFinal(encrypted_bytes);
}catch(Exception e){
System.out.println(e.toString());
}
}
public byte[] get_encrypted_data(){
return this.encrypted_bytes;
}
public byte[] get_decrypted_data(){
decrypt_text();
return this.decrypted_bytes;
}
public byte[] get_original_data(){
return this.bytes_to_encrypt;
}
public SecretKey get_key(){
return this.secretKey;
}
}
Since I'm encrypting the PE as any other file, I think I'm messing with the sections, however I have no idea how to correct it. Any help is appreciated. I apologize for the bad looking code

Categories

Resources