I have a client/server application that encrypts or decrypts a message both on the client-side and server-side. However on decryption I keep getting the following error from the StackTrace
Input length must be multiple of 8 when decrypting with padded cipher
Following is the code from both the Server and Client classes.
The thing is I have tried using ("DES/CBC/PKCS5Padding") and ("UTF-8") but still haven't been able to fix said issue.
Any help would be appreciated thanks?
public class ServerApp {
public static byte[] encrypt(String input, Key k) {
try {
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, k);
byte[] data = input.getBytes();
byte[] result = cipher.doFinal(data);
return result;
} catch (Exception ex) {
return null;
}
}
public static String decrypt(byte[] cipher, Key k) {
try {
Cipher cipher1 = Cipher.getInstance("DES");
cipher1.init(Cipher.DECRYPT_MODE, k);
byte[] original = cipher1.doFinal(cipher);
return new String(original);
} catch (Exception ex) {
return null;
//Logger.getLogger(DES.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) throws NoSuchAlgorithmException {
try {
Key key=KeyGen.getSecretKey();
ServerSocket ser = new ServerSocket(3333);
System.out.println("Server Started");
Socket client = ser.accept();
DataInputStream in = new DataInputStream(client.getInputStream());
DataOutputStream out = new DataOutputStream(client.getOutputStream());
Scanner scan = new Scanner(System.in);
// SecretSocket sc = new SecretSocket(client, KeyGen.getSecretKey());
String serMsg, cliMsg, plain;
// OutputStream sout = sc.getOutputStream();
// InputStream sin = sc.getInputStream();
do {
System.out.print("You say: ");
serMsg = scan.nextLine();
// sout.write(serMsg.getBytes());
// System.out.println("cli server "+sin.read());
byte[] ci = encrypt(serMsg, KeyGen.getSecretKey());
System.out.println("encrypt " +ci.toString());
out.writeUTF(ci.toString());
plain = decrypt(ci, KeyGen.getSecretKey() );
System.out.println("decrypt " + plain);
} while (!serMsg.equals("end"));
client.close();
ser.close();
} catch (IOException ex) {
Logger.getLogger(ServerApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class ClientApp {
public static byte[] encrypt(String input, Key k) {
try {
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, k);
byte[] data = input.getBytes();
byte[] result = cipher.doFinal(data);
return result;
} catch (Exception ex) {
return null;
}
}
public static String decrypt(byte[] cipher, Key k) {
try {
Cipher cipher1 = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher1.init(Cipher.DECRYPT_MODE, k);
byte[] original = cipher1.doFinal(cipher);
return new String(original);
} catch (Exception ex) {
return null;
//Logger.getLogger(DES.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
try {
Socket s = new Socket("localhost", 3333);
DataInputStream in = new DataInputStream(s.getInputStream());
DataOutputStream out = new DataOutputStream(s.getOutputStream());
Scanner scan = new Scanner(System.in);
String serMsg, cliMsg, plain;
do {
System.out.println("server server "+in.readUTF());
serMsg = in.readUTF();
System.out.println("enc: " + serMsg);
plain = decrypt(serMsg.getBytes("UTF-8"), KeyGen.getSecretKey());
System.out.println("Server says: " + plain);
} while (!serMsg.equals("end"));
s.close();
} catch (IOException ex) {
Logger.getLogger(ClientApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, k);
byte[] data = input.getBytes();
byte[] result = cipher.doFinal(data);
Using DES without IV you are implicitly using DES/ECB/PKCS5Padding.
do not print a byte array directly. Java will output only printable characters. Always encode and decode a byte array when printing (Hex or Base64 are the most common encodings)
Here is an example project
Base64.getEncoder().encodeToString(byteArray)
I hope you are aware DES is considered a weak cipher today and should be used only for backward compatibility.
Related
I am creating a server (Responder B) and client (Initiator A) which will exchange encrypted messages that will be decrypted on the receiving end. However, when I send an encrypted message from responder B to initiator a, I am getting the "Input length must be multiple of 8 when decrypting with the padded cipher" error.
Here is the server/Responder B code:
public class ResponderB {
protected static String masterKey = "NETWORK SECURITY";
protected String identityA;
protected String ciphertext;
private DataOutputStream out;
private Socket socket;
private ServerSocket server;
private DataInputStream in;
public ResponderB(int port, String ciphertext) {
this.ciphertext = ciphertext;
try {
server = new ServerSocket(port);
System.out.println("Responder started");
System.out.println("Waiting for initiator ...");
socket = server.accept();
System.out.println("Responder accepted");
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
String line = "";
//System.out.println("ResponderB ciphertext: "+this.ciphertext);
try {
line = in.readUTF();
this.identityA = line;
System.out.println("Identity Recieved");
System.out.println("Initiator Identity: "+this.identityA);
this.identityA = encrypt(this.identityA, masterKey);
this.ciphertext = this.identityA + " " + this.ciphertext;
System.out.println("Message Two Ciphertext in bytes: "+this.ciphertext.getBytes());
System.out.println("Message Two Ciphertext: "+this.ciphertext);
out.writeUTF(this.ciphertext);
}catch(IOException i){
System.out.println(i);
}
System.out.println("Closing connection");
//close connection
socket.close();
in.close();
}catch(IOException i){
System.out.println(i);
}
}
public static void main(String args[]){
String sessionKey = "SESSION";
String ciphertext1 = ""; String ciphertext2 = "";
String identityB = "RESPONDER B";
ciphertext1 = encrypt(identityB, masterKey);
ciphertext2 = encrypt(sessionKey, masterKey);
String cleartext = ciphertext1 + " " + ciphertext2;
ResponderB initiator = new ResponderB(6666, cleartext);
}}
This is the client/initiator a code:
public class InitiatorA {
private String identity = "INITIATOR A";
private String masterKey = "NETWORK SECURITY";
private String ciphertext, plaintext, temptext, sessionKey;
private Socket socket;
private BufferedReader input;
private DataOutputStream out;
private DataInputStream in;
public InitiatorA(String address, int port) {
// try to establish a connection
try {
socket = new Socket(address, port);
System.out.println("Connected");
//ready the input reader
input = new BufferedReader(new InputStreamReader(System.in));
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
out = new DataOutputStream(socket.getOutputStream());
// String to read a message from the input
String line = "";
String buffer = "";
//line = input.readLine(); // Reads line from keyboard
System.out.println("Cleartext of message 1: " + this.identity);
out.writeUTF(this.identity); // writes it to the output stream
buffer = in.readUTF();
this.ciphertext = buffer;
System.out.println("The received ciphertext of message 2: " + this.ciphertext);
String[] tokens = this.ciphertext.split("\\s+");
for(int i = 0; i < tokens.length; i++){
this.plaintext = this.plaintext + decrypt(tokens[i], this.masterKey);
}
System.out.println("The decrypted message 2: " + this.plaintext);
} catch (IOException i) {
System.out.println(i);
}
}
public static void main(String args[]) {
InitiatorA responder = new InitiatorA("127.0.0.1", 6666);
}}
Finally, these are the encrypt and decrypt methods I am using, the algorithm to encrypt and decrypt the messages is DES, and I am using a custom key (masterKey) that is being converted to a secret Key from a string, One thing I noticed is that the byte [] of the ciphertext being transmitted is changing from the server to the client-side, but the actual text in the cipher text remains the same.
Another exception I am getting is the: "
javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption." But I don't see how a bad key would be in place here since the same string is being used on the server and client-side.
public static String encrypt(String plain, String key) {
String plaintext, ciphertext = "", plaintext1;
byte[] plaintextByte, plaintext1Byte, ciphertextByte, keyByte;
plaintext = plain;
try {
keyByte = key.getBytes();
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey desKey = keyFactory.generateSecret(new DESKeySpec(keyByte));
plaintextByte = plaintext.getBytes();
Cipher desCipher;
desCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
desCipher.init(Cipher.ENCRYPT_MODE, desKey);
ciphertextByte = desCipher.doFinal(plaintextByte);
ciphertext = new String(ciphertextByte, StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException i) {
System.out.println(i);
}
return ciphertext;
}
public static String decrypt(String cipher, String key) {
String plaintext = "", ciphertext, plaintext1="";
byte[] plaintextByte, plaintext1Byte, ciphertextByte, keyByte;
try {
keyByte = key.getBytes();
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey desKey = keyFactory.generateSecret(new DESKeySpec(keyByte));
Cipher desCipher;
desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
desCipher.init(Cipher.DECRYPT_MODE, desKey);
plaintext1Byte = desCipher.doFinal(cipher.getBytes());
plaintext1 = new String(plaintext1Byte, StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException i) {
System.out.println(i);
}
return plaintext1;
}
Thank you in advance for the help.
I am trying to decrypt a file using the following code:
Uri targURI = Uri.parse("content://xxxx/yyy.txt");
try {
InputStream content = getContentResolver().openInputStream(targURI);
BufferedReader reader1 = new BufferedReader(new InputStreamReader(content));
String line1;
String text = "";
while ((line1 = reader1.readLine()) != null) {
text+=line1;
}
Log.i("FILE ENCRYPTED", text);
String DECRYPTED = "";
DECRYPTED = decrypt(text);
Log.i("FILE DECRYPTED:", DECRYPTED);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public String decrypt(String paramString) throws Exception {
String md5_pin1 = "";
String md5_pin = MD5(md5_pin1);
SecretKeySpec keySpec = new SecretKeySpec(md5_pin.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] paramString1 = Base64.decode(paramString.getBytes(), 0);
byte[] paramstring2 = cipher.doFinal(paramString1);
String decoded = new String(paramstring2, "UTF-8");
return decoded;
}
#NonNull
public static String MD5(String paramString) throws Exception {
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
digest.update(paramString.getBytes());
byte messageDigest[] = digest.digest();
StringBuffer hexString = new StringBuffer();
int i=0;
while( i < messageDigest.length) {
String str = Integer.toHexString( messageDigest[i] & 0xFF );
if (str.length() == 1) {
hexString.append("0");
}
hexString.append(str);
i += 1;
}
return hexString.toString();
}
as it is showed the file is accessed using a content provider, and stored in a String variable, and actually the correct string value is stored (encrypted data).
The way to decrypt it is to get a seed (empty space in this case), and then use MD5 digest, then use that value to encrypt/decrypt the cleartext.
However whenever the code reaches: String decoded = new String(paramstring2, "UTF-8"); the error message: pad block corrupted is thrown.
Any ideas what I am doing wrong?
Avoid using default padding for cipher as it may be different on different environment.
Try the following code:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
Also use the same padding for encrypting the file.
You can use the following methods:
private static byte[] encrypt(byte[] data, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[cipher.getBlockSize()];
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), ivParams);
return cipher.doFinal(data);
}
private static byte[] decrypt(byte[] encrypted, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] ivByte = new byte[cipher.getBlockSize()];
IvParameterSpec ivParamsSpec = new IvParameterSpec(ivByte);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), ivParamsSpec);
return cipher.doFinal(encrypted);
}
This was not a problem related to coding.
Please disregard this question
I am trying to decrypt a message on server - the error what I got is
Encryption technique used - DES.
--Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
I am having a very difficult time trying to solve this problem,
any help will be appreciated
class TCPClient {
public static void main(String argv[]) throws Exception {
byte[] sentence, textEncrypted;
String modifiedSentence;
String password;
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("localhost", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
password = "Passcode";
byte[] salt = new byte[64];
Random rnd = new Random();
rnd.nextBytes(salt);
byte[] data = deriveKey(password, salt, 64);
// BufferedReader inFromServer = new BufferedReader(new
// InputStreamReader(clientSocket.getInputStream()));
System.out.println("Enter the Data to be transmisted to server\n");
sentence = inFromUser.readLine().getBytes();
SecretKey desKey = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(data));
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, desKey);
textEncrypted = cipher.doFinal(sentence);
outToServer.writeBytes(new String(textEncrypted) + '\n');
clientSocket.close();
}
public static byte[] deriveKey(String password, byte[] salt, int keyLen) {
SecretKeyFactory kf = null;
try {
kf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
KeySpec specs = new PBEKeySpec(password.toCharArray(), salt, 1024, keyLen);
SecretKey key = null;
try {
key = kf.generateSecret(specs);
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return key.getEncoded();
}
}
Server side code
class TCPServer {
public static void main(String argv[]) throws Exception {
String password = null;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(6789);
while (true) {
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
password = "Passcode";
byte[] salt = new byte[64];
Random rnd = new Random();
rnd.nextBytes(salt);
byte[] data = deriveKey(password, salt, 64);
byte [] EncyptedText = inFromClient.readLine().getBytes();
System.out.println("Received Encrypted message " + EncyptedText);
SecretKey desKey = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(data));
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, desKey);
// Decrypt the text
System.out.println("Text Received " + EncyptedText);
byte[] textDecrypted = cipher.doFinal(EncyptedText);
System.out.println("Text Decryted : " + new String(textDecrypted));
}
}
public static byte[] deriveKey(String password, byte[] salt, int keyLen) {
SecretKeyFactory kf = null;
try {
kf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
KeySpec specs = new PBEKeySpec(password.toCharArray(), salt, 1024, keyLen);
SecretKey key = null;
try {
key = kf.generateSecret(specs);
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return key.getEncoded();
}
}
You will lose data doing this:
outToServer.writeBytes(new String(textEncrypted) + '\n');
besides that, it's not necessary. Ciphertext is not really text for modern ciphers, it's binary. And as sockets provide binary InputStreams and OutputStreams there is simply no reason to convert the ciphertext to strings either. All that is required is to convert possible input strings to binary (using the same encoding on both the client and server, of course - UTF-8 is preferred nowadays).
I see this "Input length must be multiple of 16 when decrypting with padded cipher" error when I run the program
RealEchoServer.java
import java.io.*;
import java.net.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class RealEchoServer {
public static void main(String[] args) {
int i = 1;
try {
ServerSocket s = new ServerSocket(9003);
for (;;) {
Socket incoming = s.accept();
System.out.println("Spawning " + i);
new RealEchoHandler(incoming, i).start();
i++;
}
} catch (Exception e) {
System.out.println(e);
}
}
}
class RealEchoHandler extends Thread {
DataInputStream in;
DataOutputStream out;
private Socket incoming;
private int counter;
public RealEchoHandler(Socket i, int c) {
incoming = i;
counter = c;
}
public void run() {
try {
String key1 = "1234567812345678";
byte[] key2 = key1.getBytes();
SecretKeySpec secret = new SecretKeySpec(key2, "AES");
String msg = "Singapore Malaysia Japan India Indonesia HongKong Taiwan China England";
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] encrypted = cipher.doFinal(msg.getBytes());
in = new DataInputStream(incoming.getInputStream());
out = new DataOutputStream(incoming.getOutputStream());
boolean done = false;
String str = "";
out.writeUTF("Connected!\n");
out.flush();
while (!done) {
out.writeUTF(">");
out.flush();
str = in.readUTF();
System.out.println(in + ":" + str);
if (str == null) {
done = true;
} else {
System.out.println("Sending Ciphertext : " + new String(encrypted));
out.writeUTF(new String(encrypted));
out.flush();
}
}
incoming.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
RealSocketTest.java
import java.io.*;
import java.net.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.util.*;
class RealSocketTest {
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
String str = "";
String str2 = "";
DataOutputStream out;
DataInputStream in;
try {
Socket t = new Socket("127.0.0.1", 9003);
in = new DataInputStream(t.getInputStream());
out = new DataOutputStream(t.getOutputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
boolean more = true;
System.out.println(in.readUTF());
while (more) {
str = in.readUTF();
System.out.print(str);
str2 = br.readLine();
out.writeUTF(str2);
out.flush();
str = in.readUTF();
System.out.println("Encrypted Info: " + str);
try {
String key1 = "1234567812345678";
byte[] key2 = key1.getBytes();
SecretKeySpec secret = new SecretKeySpec(key2, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secret);
byte[] decrypted = cipher.doFinal(str.getBytes());
System.out.println("Decrypted Info: " + new String(decrypted));
} catch (BadPaddingException e) {
System.out.println("Wrong Key!");
} catch (InvalidKeyException f) {
System.out.println("Invalid Key!");
}
}
} catch (IOException e) {
System.out.println("Error");
}
}
}
I've read a similar problem here Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher , but I don't understand how I could change mine, because it looks very different from mine.
So what should be added/changed to get it decrypted?
The problem is that ciphertexts may contain every possible byte value. Many byte values on the other hand are not printable and therefore not a valid UTF-8 encoding. When you make a String out of it new String(encrypted), it will silently drop some bytes and you won't be able to successfully decrypt the ciphertext.
Two possible fixes:
Encode the ciphertext as Base64 or Hex to be used in a text-based protocol.
Use the DataOutputStream::write() method to make it a binary protocol without encoding it.
Other security stuff:
Always specify the complete String for the expected Cipher instance. Different providers might have different defaults and it may happen that client and server don't use the same method. Example: AES/ECB/PKCS5Padding.
Never use ECB mode. It is not semantically secure. At least use CBC with a random IV (prepend the IV in front of the ciphertex or write it to the stream in order).
Check your ciphertext for manipulation. This is easily done, by employing an authenticated mode like GCM (AES/GCM/NoPadding with GCMParameters). If you don't want that, then at least try to implement an encrypt-then-MAC scheme where you HMAC the ciphertext (with a different key) and check it before decryption.
I use DES algorithm to encrypt/decrypt my text. And it works perfect with latin texts.
But when I start encrypt/decrypt cyrillic text, decrypted one is shown as ????? ???????? in my TextField form and in console. How can i fix it?
After Joachim Sauer advice I changed inputBytes = textToEnrypt.getBytes(); to inputBytes = textToEnrypt.getBytes("UTF-8"); and now I have javax.crypto.IllegalBlockSizeException. Help me, please...
package crypting;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.microedition.midlet.*;
public class Encryptor extends MIDlet {
String buffer;
public void startApp() {
String keyString = "testtest";
// encrypt("Text for encrypting", keyString);
encrypt("Привет", keyString);
decrypt(buffer, keyString);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void encrypt(String textToEnrypt, String keyString) {
Cipher cipher;
try {
cipher = Cipher.getInstance("DES");
} catch (Exception ex) {
System.out.println(ex.toString());
return;
}
byte[] keyData = keyString.getBytes();
SecretKeySpec key = new SecretKeySpec(keyData, 0, keyData.length, "DES");
try {
cipher.init(Cipher.ENCRYPT_MODE, key);
} catch (Exception ex) {
System.out.println(ex.toString());
return;
}
int cypheredBytes = 0;
byte[] inputBytes;
try {
inputBytes = textToEnrypt.getBytes("UTF-8");
// inputBytes = textToEnrypt.getBytes();
} catch (Exception ex) {
System.out.println(ex.toString());
return;
}
byte[] outputBytes = new byte[100];
try {
cypheredBytes = cipher.doFinal(inputBytes, 0, inputBytes.length,
outputBytes, 0);
} catch (Exception ex) {
System.out.println(ex.toString());
return;
}
String str = new String(outputBytes, 0, cypheredBytes);
buffer = str;
System.out.println("Encrypted string = " + str);
}
public void decrypt(String textToDecrypt, String keyString) {
Cipher cipher;
try {
cipher = Cipher.getInstance("DES");
} catch (Exception ex) {
System.out.println(ex.toString());
return;
}
byte[] keyData = keyString.getBytes();
SecretKeySpec key = new SecretKeySpec(keyData, 0, keyData.length, "DES");
try {
cipher.init(Cipher.DECRYPT_MODE, key);
} catch (Exception ex) {
System.out.println("2. " + ex.toString());
return;
}
int cypheredBytes = 0;
byte[] inputBytes;
try {
inputBytes = textToDecrypt.getBytes("UTF-8");
// inputBytes = textToDecrypt.getBytes();
} catch (Exception ex) {
System.out.println("3. " + ex.toString());
return;
}
byte[] outputBytes = new byte[100];
try {
cypheredBytes = cipher.doFinal(inputBytes, 0, inputBytes.length,
outputBytes, 0);
} catch (Exception ex) {
System.out.println("4. " + ex.toString());
return;
}
String str = new String(outputBytes, 0, cypheredBytes);
System.out.println("Decrypted string = " + str);
}
}
I was able to make it work with the following changes.
Change the return type of encrypt method, from void to byte[]:
static public byte[] encrypt(String textToEnrypt, String keyString)
throws Exception
{
//at the end
//write this down:
byte[] newResponse = new byte[cypheredBytes];
for(int i=0;i < cypheredBytes;i++)
{
newResponse[i] = outputBytes[i];
}
return newResponse;
}
Instead of:
String str = new String(outputBytes, 0, cypheredBytes);
buffer = str;
System.out.println("Encrypted string = " + str);
My guess (and I can't do more without you showing some code) is that you're using getBytes() without a parameter and construct the String from the byte[] without a parameter as well. That means using the platform default encoding and if that can't represent cyrillic characters, then that's what you get.
It's better to use UTF-8 for both transformations, this way you can represent every Unicode character.
DES uses a 64-bit (8-byte) block size. You have to make sure that the data you're encrypting is a multiple of 8 bytes, i.e. pad it out with zero bytes or whatever to ensure that it is. Otherwise you'll get an IllegalBlockSizeException. You'll need to do this after you convert the string to UTF-8, of course....
One problem is the line
String str = new String(outputBytes, 0, cypheredBytes);
in your encrypt method. You cannot use String as a container for binary data. Encrypted data should not be converted to a String unless it is a requirement, and then you need to use an appropriate codec such as base64.