0

I have just discovered the PBE method to generate a "salty" key in order to encrypt an object (here, a string).

I do not know much how all this works, but the lessons I had made me want to go a little further and therefore to create my own salege and everything that follows without leaving java "everything to do".

So I developed methods that are used to encrypt and decrypt a message, and everything seems to work very well ... But in fact, it works weirdly, because the message I find at the end is present, but present with extra characters!

I find it hard to understand how this is done.

Could you enlighten me on this question?

The code of my class below:

package fr.doranco.cryptage.pbe;
import fr.doranco.utils.Utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Random;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

/**
 *
 * @author Boule
 */
public abstract class CryptagePBE {

    private static final int KEY_SIZE = 128;
    private static final String KEY_ALGO = "AES";
    private static final String ALGOTRANSFORM = "AES/CBC/PKCS5Padding";
    private static final String KDF = "PBKDF2WithHmacSHA1";
    private static final int ITERATION = 1000;
    private static final Random RANDOM = new SecureRandom();

    private CryptagePBE() {
    }

    public static final byte[] encrypter(Object objetACrypter, SecretKey clePBE) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, IOException, InvalidAlgorithmParameterException {

        Cipher cipher = Cipher.getInstance(ALGOTRANSFORM);

        cipher.init(Cipher.ENCRYPT_MODE, clePBE,new IvParameterSpec(new byte[16]));
        byte[] objetBytes = Utils.convertToBytes(objetACrypter);
        byte[] cipherBytes = cipher.doFinal(objetBytes);
        return cipherBytes;
    }

    public static final byte[] decrypter(byte[] stringCrypte, SecretKey cle, String encodage) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance(ALGOTRANSFORM);

        cipher.init(Cipher.DECRYPT_MODE, cle, new IvParameterSpec(new byte[16]));
        //Ne pas oublier de caster le retour afin de récupérer l'objet désiré !
        return cipher.doFinal(stringCrypte);
    }

    public static final SecretKey generatePBEKey(String password) throws NoSuchAlgorithmException, InvalidKeySpecException {
        SecretKey clePBE = null;
        char[] passwordTochar = password.toCharArray();
        PBEKeySpec pbeKeySpec = new PBEKeySpec(passwordTochar, CryptagePBE.getNextSalt(), ITERATION, KEY_SIZE);
        //On vide le tableau de charactère du mot de passe.
        password = "";
        for (int j = 0; j < passwordTochar.length; j++) {
            passwordTochar[j] = 0;
        }

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KDF);
        SecretKey keyPBE = keyFactory.generateSecret(pbeKeySpec);
        clePBE = new SecretKeySpec(keyPBE.getEncoded(), KEY_ALGO);
        return clePBE;
    }

    public static byte[] getNextSalt() {
        byte[] salt = new byte[16];
        RANDOM.nextBytes(salt);
        return salt;
    }

    public static final byte[] convertKeyToBytes(SecretKey key) throws IOException {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutput out = new ObjectOutputStream(bos)) {
            out.writeObject(key);
            return bos.toByteArray();
        }
    }

    public static final SecretKey convertKeyFromBytes(byte[] keyData) throws IOException, ClassNotFoundException {
        try (ByteArrayInputStream bis = new ByteArrayInputStream(keyData);
                ObjectInput in = new ObjectInputStream(bis)) {
            return (SecretKey) in.readObject();
        }
    }
}

Here my main

public class Main {

    public static void main(String[] args) {

        try {


            SecretKey clePBE = CryptagePBE.generatePBEKey("coucou");
            String messageA = "Hi people";

            System.err.println("Original message : "+ messageA+" //Message in bytes array : "+Utils.convertToBytes(messageA));

            byte[] messageCrypte2 = CryptagePBE.encrypter(messageA, clePBE);

            System.err.println("Crypted message : "+messageCrypte2);

            byte[] messageDecrypte = CryptagePBE.decrypter(messageCrypte2, clePBE, "UTF8");

            System.err.println("Decrypted message : "+messageDecrypte);


        } catch (Exception ex) {
            System.err.println("Une erreur est survenue dans le main : " + ex);
        }
    }

    public Main() {
    }
}

And this is what I have in my output console :

Original message : Hi people //Message in bytes array : [B@704921a5
Crypted message : [B@31f924f5
Decrypted message : [B@5579bb86 //This will return "Hi people" but with a changed bytes array.

I wonder if it's a problem due to the encoding ?

Thank you !

Edit

Thx to @andreas who gave me the reason. The method to compare the both messages is to compare with Arrays.toString(myArray). With this method we can see the same array of bytes, not a different for both.

Here the full explaination of this : What's the simplest way to print a Java array?

Batche
  • 65
  • 1
  • 8
  • What does `Utils.convertToBytes(Object)` do? Why do you believe the reverse of that is `new String(byte[])`? --- What does `Utils.fromByteToString()` do? – Andreas May 13 '20 at 15:45
  • Hi, Utils.convertToBytes() is'nt really usefull, it just converts bytes to string. It's just to see how it looks in string. I'll edit my code without that. For your second question, maybe I can just let a byte[] return and cast after ? It was just a common way to have a string in return. – Batche May 13 '20 at 15:51
  • How can `Utils.convertToBytes()` "convert bytes to string", when the parameter is `Object` and the return type is `byte[]`? I think you means to say `Utils.fromByteToString()`. --- The real question is still, what does `Utils.convertToBytes()` do, and why do you believe the reverse is `new String()`? – Andreas May 13 '20 at 15:59
  • Now read: [What's the simplest way to print a Java array?](https://stackoverflow.com/q/409784/5221149) – Andreas May 13 '20 at 16:02
  • Lol, I'm so stupid, sorry. The method I wanted to use is Utils.convertFromBytes. This method convert to an object (for example a string) who whas originnally in bytes. If i used this method on my decrypted object and if I use the right cast, I will have my string "Hello people", but with hm.. I d'ont know wich word is good, but I want to say a different signature. I updated my code with the changes. Now the method encrypte() return bytes and the method decrypte() also does. I'm not sure to understand your question, but I can try to answer to it : because I want a string in return ? – Batche May 13 '20 at 16:11
  • Yes thank you, I changed my code to have this kind of return. But the problem is still the same and the question is if it's a problem or not that the original message in bytes is : "[B@704921a5" and the decrypted message is "[B@5579bb86", even if finally the result is "Hi people". – Batche May 13 '20 at 16:14
  • Did you not look at the link I gave you? – Andreas May 13 '20 at 17:48
  • Yes !! I was not sure where you wanted to take me, but after testing the Arrays.toString (array) method, it appeared much clearer and I actually have the same table for both messages. :)) Thank you very much for your help, I understand better now. :) – Batche May 13 '20 at 19:37

0 Answers0