0

I try to make encryption and decryption mechanism in Java. I have found some code for decrypting but I don't know how to encrypt. What encryption method will be compatible with decryption method like this:

private byte[] padKey(byte[] key) {
        byte[] paddedKey = new byte[32];
        System.arraycopy(key, 0, paddedKey, 0, key.length);
        return paddedKey;
    }

    private byte[] unpad(byte[] data) {     
        byte[] unpaddedData = new byte[data.length - data[data.length - 1]];
        System.arraycopy(data, 0, unpaddedData, 0, unpaddedData.length);
        return unpaddedData;
    }


public String decrypt(String encodedJoinedData) throws Exception {

        // Base64-decode the joined data
        byte[] joinedData = Base64.decode(encodedJoinedData); 

        // Get IV and encrypted data
        byte[] iv = new byte[16];
        System.arraycopy(joinedData, 0, iv, 0, iv.length);
        byte[] encryptedData = new byte[joinedData.length - iv.length];
        System.arraycopy(joinedData, iv.length, encryptedData, 0, encryptedData.length);

        // Pad key
        byte[] key = padKey("SiadajerSiadajer".getBytes()); 
        Key aesKey = new SecretKeySpec(key, "AES");

        // Specify CBC-mode
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); 
        cipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);

        // Decrypt data
        byte[] decryptedData = cipher.doFinal(encryptedData);

        // Remove custom padding
        byte[] unpaddedData = unpad(decryptedData);         

        return new String(unpaddedData);
    }
  • 1
    Possible duplicate of [How to encrypt String in Java](https://stackoverflow.com/questions/1205135/how-to-encrypt-string-in-java) – Lino Mar 18 '19 at 07:50
  • Well, encryption and decryption must use the same method, so that would be `Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");`. All of the basic information is in the link @Lino suggested. – KevinO Mar 18 '19 at 07:52
  • 1
    Though I would strongly recommend reading up on what it is you're doing. Encryption is a broad domain, and if you don't know what you're doing it's easy to make something that seems secure but really isn't – Jeroen Steenbeeke Mar 18 '19 at 08:18
  • I am a beginner and I kinda still do not know shat should I exactly do – Jeremiah Mason Mar 18 '19 at 08:44

1 Answers1

0

If you're looking for an encryption-counterpart to your decrypt-method you have simply to reverse the process in your decrypt-method. The following must be done in the body of the encrypt-method (let plainText be a String-parameter containing the plain text):

  1. Add the custom padding

    // Pad data (custom padding)
    byte[] paddedData = pad(plainText.getBytes(), 16);
    
  2. Encrypt your plain text

    // Pad key 
    byte[] key = padKey("SiadajerSiadajer".getBytes()); 
    Key aesKey = new SecretKeySpec(key, "AES");
    
    // Specify block-cipher (AES), mode (CBC) and padding (PKCS5)
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    
    // Create random IV
    SecureRandom secureRandom = new SecureRandom();
    byte iv[] = new byte[cipher.getBlockSize()];
    secureRandom.nextBytes(iv);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); 
    
    // Encrypt data
    cipher.init(Cipher.ENCRYPT_MODE, aesKey, ivParameterSpec);
    byte[] encryptedData = cipher.doFinal(paddedData);
    
  3. Join IV and encrypted data

    // Join IV and encrypted data
    byte[] joinedData = new byte[iv.length + encryptedData.length];  
    System.arraycopy(iv, 0, joinedData, 0, iv.length);
    System.arraycopy(encryptedData, 0, joinedData, iv.length, encryptedData.length);
    
  4. Base 64-encode the joined data

    // Base64-encode data
    String encodedJoinedData = Base64.encode(joinedData, 0);
    

Finally, the encodedJoinedData have to be returned.

Moreover, you have to implement the custom padding. The following method implements a custom PKCS5-Padding and is a possible counterpart to the unpad-method:

private byte[] pad(byte[] data, int size) {
    byte padLength = (byte)(size - (data.length % size));
    byte[] paddedData = new byte[data.length + padLength];
    System.arraycopy(data, 0, paddedData, 0, data.length);
    for (int i = data.length; i < paddedData.length; i++)
        paddedData[i] = (byte)padLength;
    return paddedData;
}

Btw, there are a few issues with your decrypt-method (and thus with the encrypt-method):

  • You shouldn't use a hardcoded key, but probably this is only for testing purposes. For creating a secure AES key see e.g. How to create a secure random AES key in Java?.
  • The most obvious flaw is that it's unpadded / padded twice in the decrypt/encrypt-method which doesn't make any sense. Thus, remove either the chosen PKCS5-Padding (i.e. change from AES/CBC/PKCS5Padding to AES/CBC/NoPadding) or the custom padding in both, the decrypt- and encrypt-method (provided that's possible within the scope of your project).
Topaco
  • 40,594
  • 4
  • 35
  • 62
  • In the last part of your code (exactly in the: String encodedJoinedData = Base64.encode(joinedData, 0); section) encode method is underlined in red because it is not defined for the type Base64. Proposed ones are endcodeBytes(), encodeObject(), encodeToFile(); What should I choose? – Jeremiah Mason Mar 19 '19 at 17:06
  • When I choose the other options almost whole code is underlined in red so maybe there is something else to be done – Jeremiah Mason Mar 19 '19 at 17:07
  • Glad to hear it's working. Unfortunately the posted code didn't show which `Base64`-class was used, so I had to guess here. Probably my choice did not fit the library you used. In principle any (established) implementation can be used, e.g. `java.util.Base64` or the Appache-variant `org.apache.commons.codec.binary.Base64`. Of course the code has to be adapted slightly. But obviously you have already solved the problem. – Topaco Mar 19 '19 at 20:30
  • Can I get a version of the method suited for java.util.Base64? – Jeremiah Mason May 28 '19 at 18:00
  • [`java.util.Base64`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Base64.html) exists since Java 1.8, see also [here](https://stackoverflow.com/a/13109632/9014097). The Base64-encoding is performed at the end of the `encrypt`-method: `String encodedJoinedData = Base64.getEncoder().encodeToString(joinedData)`. The Base64-decoding is performed at the beginning of the `decrypt`-method: `byte[] joinedData = Base64.getDecoder().decode(encodedJoinedData)`. Simply exchange the existing code parts with these. – Topaco May 28 '19 at 21:00