I have implemented rsa Encryption and Decryption in Java which works totally fine. But my problem is, when I write my encrypted string to a JTextField, I can't get the correct value back out of the JTextField in order to decrypt the message again.
Here is my code, I believe I am doing something wrong at the conversion of my values (byte[] and string):
public static byte[] encrypt(String message, PublicKey pk) {
Cipher cipher= null;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pk);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
byte[] chiffrat = null;
try {
chiffrat = cipher.doFinal(message.getBytes());
} catch (IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
return chiffrat;
}
public static String decrypt(byte[] chiffrat, PrivateKey sk)
{
byte[] dec = null;
Cipher cipher = null;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, sk);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
try {
dec = cipher.doFinal(chiffrat);
} catch (IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
return new String(dec);
}
And in my Window class:
Writing encrypted string in my TextField
JButton btnEncrypt = new JButton("Plaintext -> RSA");
btnEncrypt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
txtEncryptionRSA.setText(new String(rsa.encrypt(pwboxEncryptionPlain.getText(), rsa.key.getPublic())));
}
});
This writes d¿Åád6×Ãö† G0|ôw;-3—?Ó^xudC\Ö>Ós`H9ÅóÛ`¥ in my TextField.
Trying to decrypt and write in another TextField:
JButton btnDecrypt = new JButton("RSA -> Plaintext");
btnDecrypt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
byte[] encryptedmsg = txtEncryptionRSA.getText().getBytes();
System.out.println(encryptedmsg);
pwboxEncryptionPlain.setText(rsaClass.decrypt(encryptedmsg, rsa.key.getPrivate()));
}
});
This prints out: [B#abd4af7 and Encryption fails.
Related
Despite checking that both my IV and derived keys are equal for encryption and decryption, it still throws the same error. The byte array will encrypt no problem, but decryption always fails. My decryption and encryption code looks like:
private final static int BLOCK_SIZE = 256;
private final static int IV_SIZE = 16;
private final static int ITERATION_COUNT = 10;
private final static String ENCRYPTION_ALGORITHM = "PBKDF2WithHmacSHA256";
private final static String ALGORITHM = "AES/CBC/PKCS5Padding";
public byte[] encryptByteArray(byte[] plaintext, String fileName) throws InvalidKeyException
{
extractIVfromName(fileName);
genKey();
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
GCMParameterSpec parameterSpec = new GCMParameterSpec(BLOCK_SIZE, iv);
Log.d("encryptByteArray", "Size: " + plaintext.length + " IV SPEC: " +
Base64.encodeToString(parameterSpec.getIV(), Base64.DEFAULT) + "DerivedKey: " +
Base64.encodeToString(derivedKey.getEncoded(), Base64.DEFAULT));
cipher.init(Cipher.ENCRYPT_MODE, derivedKey, parameterSpec);
return cipher.doFinal(plaintext);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
And here we have decryption, where the error is occuring:
public byte[] decryptByteArray(byte[] ciphertext, String fileName) throws InvalidKeyException
{
extractIVfromName(fileName);
genKey();
try {
//IV fails for some reason
Cipher cipher = Cipher.getInstance(ALGORITHM);
GCMParameterSpec parameterSpec = new GCMParameterSpec(BLOCK_SIZE, iv);
Log.d("decryptByteArray", "Size: " + ciphertext.length + " IV SPEC: " +
Base64.encodeToString(parameterSpec.getIV(), Base64.DEFAULT) + "DerivedKey: " +
Base64.encodeToString(derivedKey.getEncoded(), Base64.DEFAULT));
cipher.init(Cipher.DECRYPT_MODE, derivedKey, parameterSpec);
return cipher.doFinal(ciphertext);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
An example of the debug log gives this:
2020-07-26 22:40:03.667 9089-9089/com.iso.gallery256 D/decryptByteArray: Size: 45312 IV SPEC: NWZmYmUzZGItZGE4MS00Yw==
DerivedKey: pa2OYoRLjTphldeSi1L6EQCmlXTzQJLeXgPIuu6kRus=
2020-07-26 22:40:00.184 9089-9089/com.iso.gallery256 D/encryptByteArray: Size: 45307 IV SPEC: NWZmYmUzZGItZGE4MS00Yw==
DerivedKey: pa2OYoRLjTphldeSi1L6EQCmlXTzQJLeXgPIuu6kRus=
I don't think the problem is with how the IV or key are generated, since they come out exactly the same for decryption and encryption, but rather with my cipher options.
I have a test function that returns a byte[] in one Java class, FirstClass:
public static byte[] testA(){
CipherClass crypto = new CipherClass();
byte[] a = crypto.encrypt("helloWorld");
return a;
}
Where CipherClass contains my java.crypto.Cipher methods to encrypt and decrypt inputs.
In another Java class, SecondClass, I instantiate my previous FirstClass and call its testA() method which I save to a byte[] variable and then try to decrypt it:
FirstClass fc = new FirstClass();
byte[] b = fc.testA();
System.out.println(crypto.decrypt(b)); //Outputs BadPaddingError
Why does encrypting a String in one Java file and then passing the resulting byte[] into another Java file to decrypt it causes a BadPaddingError?
What can be done to fix a way around this?
Why does the Cipher only work if both encryption and decryption are in the same class as follows?:
CipherClass crypto = new CipherClass();
byte[] a = crypto.encrypt("helloWorld"); //Outputs [B#5474c6c
byte[] b = a;
System.out.println(crypto.decrypt(b)); //Outputs "helloWorld"
EDIT: My CipherClass code as requested below.
SecretKey and IVParameterSpec generator:
public List<KeyGenerator> getKeyGenerator(){
List<KeyGenerator> list = new ArrayList<KeyGenerator>();
KeyGenerator keyGenerator;
int keyBitSize = 128;
try
{
SecureRandom secureRandom = new SecureRandom();
keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(keyBitSize, secureRandom);
list.add(keyGenerator);
return list;
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
return list;
}
public List<SecretKey> getSecretKey(List<KeyGenerator> keygen) {
List<SecretKey> list = new ArrayList<SecretKey>();
KeyGenerator keyGenerator;
SecretKey secretKey;
keyGenerator = keygen.get(0);
secretKey = keyGenerator.generateKey();
list.add(secretKey);
return list;
}
public List<IvParameterSpec> getIvSpec(List<SecretKey> secretKey) {
List<IvParameterSpec> list = new ArrayList<IvParameterSpec>();
Cipher cipher;
byte[] iv;
try
{
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
iv = new byte[cipher.getBlockSize()];
IvParameterSpec ivSpec = new IvParameterSpec(iv);
list.add(ivSpec);
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (NoSuchPaddingException e)
{
e.printStackTrace();
}
return list;
}
List<KeyGenerator> kgList = getKeyGenerator();
List<SecretKey> skList = getSecretKey(kgList); //skList.get(0) is the SecretKey
List<IvParameterSpec> ivList = getIvSpec(skList); //ivList.get(0) is the IVParameterSpec
My encrypt() method:
public byte[] encrypt(String inputStr) {
Cipher cipher;
SecretKey secretKey = skList.get(0);
IvParameterSpec ivSpec = ivList.get(0);
byte[] plainText;
byte[] cipherText = new byte[]{};
try
{
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try
{
secretKey = skList.get(0);
ivSpec = ivList.get(0);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
try
{
plainText = inputStr.getBytes("UTF-8");
cipherText = cipher.doFinal(plainText);
return cipherText;
}
catch (IllegalBlockSizeException e)
{
e.printStackTrace();
}
catch (BadPaddingException e)
{
e.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
catch (InvalidKeyException e)
{
e.printStackTrace();
}
catch (InvalidAlgorithmParameterException e1)
{
e1.printStackTrace();
}
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (NoSuchPaddingException e)
{
e.printStackTrace();
}
return cipherText;
}
My decrypt() method:
public String decrypt(byte[] cipherText){
Cipher cipherDe;
SecretKey secretKey = skList.get(0);
IvParameterSpec ivSpec = ivList.get(0);
byte[] deciByte;
String decryptText = "";
try
{
cipherDe = Cipher.getInstance("AES/CBC/PKCS5Padding");
try
{
secretKey = skList.get(0);
ivSpec = ivList.get(0);
cipherDe.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
try
{
//De-cryption
deciByte = cipherDe.doFinal(cipherText);
decryptText = new String(deciByte);
return decryptText;
}
catch (IllegalBlockSizeException e)
{
e.printStackTrace();
}
catch (BadPaddingException e)
{
e.printStackTrace();
}
}
catch (InvalidKeyException e)
{
e.printStackTrace();
}
//De-cryption
catch (InvalidAlgorithmParameterException e1)
{
e1.printStackTrace();
}
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (NoSuchPaddingException e)
{
e.printStackTrace();
}
return decryptText;
}
Here are my encryption settings
public static final String ALGORITHM = "RSA";
public static final String CIPHER = "RSA/ECB/PKCS1Padding";
public static final String HASH_ALGORITHM = "SHA-256";
public static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
public static final int KEY_SIZE = 1048;
Here is my code to encrypt
public byte[] encrypt(byte[] toEncrypt, String keyPath){
int keyLength = KEY_SIZE/8 - 11;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
String toEncryptString = new String(toEncrypt,StandardCharsets.UTF_8);
String[] lines = toEncryptString.split("(?<=\\G.{" + keyLength + "})");
byte[] encryptedData = new byte[0];
try{
inputStream = new ObjectInputStream(new FileInputStream(keyPath));
final PublicKey publicKey = (PublicKey) inputStream.readObject();
final Cipher cipher = Cipher.getInstance(CIPHER);
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
if(toEncrypt.length >= keyLength){
for(String line : lines){
byteArrayOutputStream.write(cipher.doFinal(line.getBytes("UTF-8")));
}
}else{
byteArrayOutputStream.write(cipher.doFinal(toEncrypt));
}
encryptedData = byteArrayOutputStream.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
byte[] cipheredData = base64Encoder(encryptedData);
System.out.println(Arrays.toString(cipheredData));
return cipheredData;
}
Here is my code to decrypt
public byte[] decrypt(byte[] toDecrypt, String keyPath) {
byte[] decypherText = base64Decoder(toDecrypt);
System.out.println(toDecrypt.length);
System.out.println(decypherText.length);
int keyLength = KEY_SIZE/8 - 11;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
String toEncryptString = Arrays.toString(decypherText);
String[] lines = toEncryptString.split("(?<=\\G.{" + keyLength + "})");
byte[] decipheredData = new byte[0];
try{
inputStream = new ObjectInputStream(new FileInputStream(keyPath));
final PrivateKey privateKey = (PrivateKey) inputStream.readObject();
final Cipher cipher = Cipher.getInstance(CIPHER);
cipher.init(Cipher.DECRYPT_MODE,privateKey);
if(decypherText.length >= keyLength){
for(String line : lines){
byteArrayOutputStream.write(cipher.doFinal(line.getBytes("UTF-8")));
}
}else{
byteArrayOutputStream.write(cipher.doFinal(decypherText));
}
decipheredData = byteArrayOutputStream.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
System.out.println(Arrays.toString(decipheredData));
return decipheredData;
}
I'm trying to encrypt a Public Key "A" with the Public Key "B". Encryption is successful, but when I try to decrypt it with the Private Key "B", it gives me that error.
The code looks fine to me, already reviewed it several times, these past 16 hours, already searched through several posts in here, and did not found a suitable answer for my problem.
Also, it already gave me BadPaddingException when decrypting. "Data must not be longer than 131 bytes". However, I'm using a Cipher with padding, so it can only decrypt data with 120 bytes. Why this error, if the Public key ciphered is splitted into blocks of 120 bytes?
Edit: before anyone else says that encrypting a Public Key is a mistery, have in your mind that it's the purpose of the project.. to have a Public Key as an ID and, as such, the need to encrypt so that no one discovers the ID of the user.
Your code doesn't make sense. You're trying to split the ciphertext on a plaintext string. It isn't there. It got removed when you split the string. In any case the data has been encrypted, so searching for a plaintext in it is futile.
You should be base64-decoding, decrypting, reading objects, and then recombining them using "(?<=\\G.{" + keyLength + "})" as a delimiter.
In fact why you're splitting in the first place and then encrypting multiple lines is a mystery.
And why you're serializing is another. Just encrypt the entire thing, without splitting, base64-encode it, and save that. When decrypting, just base64-decode it and decrypt it.
And, finally, why you're encrypting a public key at all is a complete mystery. It's PUBLIC. Not a secret.
I have an encrypted file, which is encrypted in java using RC4 Encryption. Below is the code in java.
public class ata {
public static byte[] a(byte[] bArr, String str) {
try {
return ata.a(bArr, str.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static byte[] a(byte[] bArr, byte[] bArr2) {
try {
Cipher instance = Cipher.getInstance("RC4");
instance.init(2, new SecretKeySpec(bArr2, "RC4"));
return instance.update(bArr);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (NoSuchPaddingException e2) {
e2.printStackTrace();
return null;
} catch (InvalidKeyException e3) {
e3.printStackTrace();
return null;
}
}
}
I need to decrypt the file in C# so i need equivalent class of the java code in C#. Is anybody have any idea how to do it ?
I am creating a secure chat client and server combo that, when finished, will have multiple layers of encryption. However, I don't understand why I am getting this error. I know there are multiple questions out there with many different answers (some so different I don't understand how anyone gets their problem resolved), however I have yet to find one that I can understand enough of to fix this error.
Originally, this actually worked; it sent the key through without a problem. I don't remember changing any part of this code. Maybe someone can tell me what's wrong? I'll mark the line with the error.
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at secureserver.Server$1.run(Server.java:88)
at java.lang.Thread.run(Unknown Source)
Part of Server that receives key
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec("i15646dont6321wanna".toCharArray(),"ahhalkdjfslk3205jlk3m4ljdfa85l".getBytes("UTF8"),65536,256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey key = new SecretKeySpec(tmp.getEncoded(),"AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivspec);
byte[] b = new byte[is.available()];
is.read(b);
/* Line 88 */ byte[] dec = cipher.doFinal(b);
SecretKey ck = new SecretKeySpec(dec,"AES");
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, ck, ivspec);
eciphers.put(client, c);
c.init(Cipher.DECRYPT_MODE, ck, ivspec);
dciphers.put(client, c);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Part of the client that sends key to server
public void sendKey(SecretKey k) {
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec("i15646dont6321wanna".toCharArray(),"ahhalkdjfslk3205jlk3m4ljdfa85l".getBytes("UTF8"),65536,256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey key = new SecretKeySpec(tmp.getEncoded(),"AES");
Cipher ec = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
ec.init(Cipher.ENCRYPT_MODE, key, ivspec);
byte[] ekey = ec.doFinal(k.getEncoded());
os.write(ekey);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
It's probably your stream handling that causes this:
byte[] b = new byte[is.available()];
is.read(b);
Is not a correct way of handling streams. Try a Java I/O tutorial to understand how to treat streams.
As a side note, for better and more legible exception handling:
try {
// handling Cipher code...
} catch (final IllegalBlockSizeException | BadPaddingException | IOException e) {
// or use your own checked exception
throw new IllegalArgumentException("Invalid ciphertext", e);
} catch (final GeneralSecurityException e) {
throw new IllegalStateException("Cryptographic algorithms not available", e);
}