I am working on a hybrid encryption mechanism in java that involves encrypting message using 3DES encryption algorithm and then encrypt its key using RSA encryption mechanism at the sender side. Once delivered to the receiver side, the encrypted 3DES key is decrypted using RSA decryption mechanism and then is used to decrypt the cipher text. Once I obtain the decrypted 3DES key its string value is the same but byte [] is not the same instead returns a 2's complement of the original key.
How can I get the decrypted 3DES to be the same as the originally generated 3DES in byte [] form at the receiver side?
Below is the code I am using for my hybrid encryption mechanism: package hybrid_implementation;
import java.security.Key;
import java.security.InvalidKeyException;
import java.security.spec.InvalidKeySpecException;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.IllegalBlockSizeException;
public class Hybrid_Implementation {
//RSA_Encryption Algorithm Required Variables
private static final BigInteger one = new BigInteger("1");
private static final SecureRandom random = new SecureRandom();
private BigInteger privatekey;
private BigInteger publickey;
private BigInteger modulus;
//3DES_Encryption Algorithm Required Variables
private byte[] DES_Key;
private SecretKeyFactory keyfactory;
private DESedeKeySpec spec;
private Key deskey;
private int DES_Key_Length;
private byte[] data;
private Cipher cipher;
private String CipherText;
private byte [] CIPHERText;
Hybrid_Implementation() throws InvalidKeyException,
NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException
{
DES_Key_Generator();
RSA_Key_Generator(999);
}
//3DES Encryption-Decryption Algorithm with 2 differnt keys
private String DES_Encryption(String plaintext) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException
{
data = plaintext.getBytes();
cipher.init(Cipher.ENCRYPT_MODE, deskey);
CIPHERText = cipher.doFinal(data);
StringBuilder hexCiphertext = new StringBuilder();
for(int i=0; i<CIPHERText.length; i++)
{
int v = CIPHERText[i] & 0xff;
v+=0x100;
String temp = Integer.toString(v,16);
hexCiphertext.append(temp).substring(1);
}
return hexCiphertext.toString();
}
private String DES_Decryption(byte [] key, byte [] encrypted_text) throws
InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
InvalidKeySpecException
{
spec = new DESedeKeySpec(key);
deskey = keyfactory.generateSecret(spec);
byte[] plaintext = cipher.doFinal(encrypted_text);
StringBuilder decrypttext= new StringBuilder();
for (int i = 0; i < plaintext.length; i++)
decrypttext.append((char) plaintext[i]);
String decrypted_plaintext = decrypttext.toString();
return decrypted_plaintext;
}
private void DES_Key_Generator() throws InvalidKeyException,
NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException
{
Random rnd = new Random();
String key = rnd.toString();
DES_Key = key.getBytes();
spec = new DESedeKeySpec(DES_Key);
keyfactory = SecretKeyFactory.getInstance("desede");
deskey = keyfactory.generateSecret(spec);
cipher = Cipher.getInstance("desede");
}
//RSA Encryption-Decryption Algorithm
private BigInteger RSA_Encryption(BigInteger des_Key ) //RSA Encryption of
3DES Key
{
BigInteger encrypted_DES_Key = des_Key.modPow(publickey, modulus);
return encrypted_DES_Key;
}
private BigInteger RSA_Decryption(BigInteger encrypted_DES_Key) //RSA
Decryption of 3DES Key
{
BigInteger des_Key = encrypted_DES_Key.modPow(privatekey, modulus);
return des_Key;
}
private void RSA_Key_Generator(int number) //RSA Public - Private Key
Generation
{
BigInteger p = BigInteger.probablePrime(number/2,random);
BigInteger q = BigInteger.probablePrime(number/2, random);
BigInteger phi = (p.subtract(one)).multiply(q.subtract(one));
modulus = p.multiply(q);
publickey = new BigInteger("65537");
privatekey = publickey.modInverse(phi);
}
private String encryption(String plaintext) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException
{
String cipher_text = DES_Encryption(plaintext);
BigInteger RSA_DESKey = RSA_Encryption(new BigInteger(DES_Key));
String temp_key = RSA_DESKey.toString();
DES_Key_Length = temp_key.length();
CipherText ="";
CipherText = new
StringBuilder().append(temp_key).append(cipher_text).toString();
return CipherText;
}
private String decryption(String encrypted_text) throws InvalidKeyException,
InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException
{
StringBuilder encryptedkey = new StringBuilder();
for(int i = 0 ; i < DES_Key_Length; i++)
encryptedkey.append (encrypted_text.charAt(i));
StringBuilder cipheredtext = new StringBuilder();
for(int j = DES_Key_Length ; j< encrypted_text.length() ; j++)
cipheredtext.append (encrypted_text.charAt(j));
BigInteger DES_Encrypted_Key = new BigInteger(encryptedkey.toString());
BigInteger DES_KEY = RSA_Decryption(DES_Encrypted_Key);
byte[] decrypt_key = DES_KEY.toByteArray();
String plaintext =
DES_Decryption(decrypt_key,cipheredtext.toString().getBytes());
return plaintext;
}
/**
*
* @param args
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
* @throws java.security.NoSuchAlgorithmException
* @throws java.security.spec.InvalidKeySpecException
* @throws javax.crypto.NoSuchPaddingException
*/
public static void main(String[] args) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException,
InvalidKeySpecException, NoSuchPaddingException {
String plaintext;
Hybrid_Implementation hi = new Hybrid_Implementation ();
Scanner sc = new Scanner(System.in);
System.out.print("Enter Text = ");
plaintext = sc.nextLine();
String encrypted_text = hi.encryption(plaintext);
String decrypted_text = hi.decryption(encrypted_text);
System.out.println("Plain Text Entered = "+plaintext);
System.out.println("Encrypted Text = "+encrypted_text);
System.out.println("Decrypted Text = "+decrypted_text);
}
}
The output I receive is: enter image description here Whereas the decrypted text is not the same as the entered plain text
System.out.print(bytearray[i])
orArrays.toString(bytearray)
? The latter is expected because typebyte
in Java is signed. However Java crypto (and I/O also) treatsbyte[]
elements (both keys/IVs/etc and data) as unsigned and works correctly. It's usually clearer to display (and sometimes enter) crypto values as hex. OTOH keys should not be restricted to valid characters and so treating them asString
will usually produce wrong results. – dave_thompson_085RSA/ECB/PKCS1Padding
orRSA/ECB/OAEPWithSHA-1AndMGF1Padding
RSA modes. – Alastair McCormack