-1

I am trying to send protected text over the network encryption it with AES algorithm and Base64. For several text that I tried it works fine, but there are a few strings that are not properly decoded. I found a pattern on the string that could not be decoded. They have what it seems to be a breakline on them. Example: Encryption Steps:

1) PlainText

2) AES Encrypted Text:

Íe l1 Ÿ?‰|6ÎÔ.jcæ÷Ï_ðNSO˜A’q@Ó[

3) BASE64 AES Text:

zWUNbDEgnz+JfDbO1C5qY+b3z1/wTlNPmAdBknFA01s=

Decryption Steps:

1) BASE64 AES Text:

zWUNbDEgnz+JfDbO1C5qY+b3z1/wTlNPmAdBknFA01s=

2) AES Encrypted Text:

Íe l1 Ÿ?‰|6ÎÔ.jcæ÷Ï_ðNSO˜A’q@Ó[

3) Plain Text:

í¿Ð“tº„£¹ÍG‰\îœ

Any other text that I encrypt that does not contains breaklines on it encrypted version is properly decrypted.

Ex:

Encryption Steps:

1) Plain Text: P@$$w0rd

2) AES Encrypted Text:

÷÷Odã29ôÐÑÌe£™ø

3) Base64 AES Text:

9xH3T2TjMjn00NHMZaOZ+A==

Decryption Steps:

3) Base64 AES Text:

9xH3T2TjMjn00NHMZaOZ+A==

2) AES Encrypted Text:

÷÷Odã29ôÐÑÌe£™ø

3) Plain Text:

P@$$w0rd

Below are the objects that I created for this purpose.

Base64Codec Object:

package security;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;
public class Base64Codec
{
    private static Base64Codec objInstance;
    private Encoder objEncoder;
    private Decoder objDecoder;
    private Base64Codec()
    {
        this.setEncoder();
        this.setDecoder();
    }
    public static Base64Codec getInstance()
    {
        if (objInstance == null)
        {
            objInstance = new Base64Codec();
        }
        return objInstance;
    }
    private void setEncoder()
    {
        this.objEncoder = Base64.getEncoder();
    }
    private Encoder getEncoder()
    {
        return this.objEncoder;
    }
    private void setDecoder()
    {
        this.objDecoder = Base64.getDecoder();
    }
    private Decoder getDecoder()
    {
        return this.objDecoder;
    }
    protected String encode(String strValue)
    {
        return this.getEncoder().encodeToString(strValue.getBytes());
    }
    protected String decode(String strValue)
    {
        return new String(this.getDecoder().decode(strValue));
    }
}

AdvancedEncryptionStandard Object

package security;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class AdvancedEncryptionStandard
{
    private static final String strKey = "02E68E02BE7400FE11E8A45B60017F98";
    private static final byte[] bytKey = strKey.getBytes();
    private static final String strAlgorithm = "AES";
    private static AdvancedEncryptionStandard objInstance;
    private Cipher objCipher;
    private SecretKeySpec objSecretKey;
    private AdvancedEncryptionStandard() throws NoSuchAlgorithmException, NoSuchPaddingException
    {
        this.setSecretKey();
        this.setCipher();
    }
    public static AdvancedEncryptionStandard getInstance() throws NoSuchAlgorithmException, NoSuchPaddingException
    {
        if (objInstance == null)
        {
            objInstance = new AdvancedEncryptionStandard();
        }
        return objInstance;
    }
    private byte[] getKey()
    {
        return bytKey;
    }
    private String getAlgorithm()
    {
        return strAlgorithm;
    }
    private void setSecretKey()
    {
        this.objSecretKey = new SecretKeySpec(this.getKey(), this.getAlgorithm());
    }
    private SecretKeySpec getSecretKey()
    {
        return this.objSecretKey;
    }
    private void setCipher() throws NoSuchAlgorithmException, NoSuchPaddingException
    {
        this.objCipher = Cipher.getInstance(this.getAlgorithm());
    }
    private Cipher getCipher()
    {
        return this.objCipher;
    }
    protected String encrypt(String strValue) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException
    {
        this.getCipher().init(Cipher.ENCRYPT_MODE, this.getSecretKey());
        return new String(this.getCipher().doFinal(strValue.getBytes()));
    }
    protected String decrypt(String strValue) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException
    {
        this.getCipher().init(Cipher.DECRYPT_MODE, this.getSecretKey());
        return new String(this.getCipher().doFinal(strValue.getBytes()));
    }
}

SecureText Object

package security;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class SecureText
{
    private static SecureText objInstance;
    private SecureText()
    {

    }
    public static SecureText getInstance()
    {
        if (objInstance == null)
        {
            objInstance = new SecureText();
        }
        return objInstance;
    }
    public String encode(String strValue) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException
    {
        return Base64Codec.getInstance().encode(AdvancedEncryptionStandard.getInstance().encrypt(strValue));
    }
    public String decode(String strValue) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException
    {
        return AdvancedEncryptionStandard.getInstance().decrypt(Base64Codec.getInstance().decode(strValue));
    }
}

Test:

public static void main(String[] args)
    {
//Test SecureText Object. AES and Base64
        String strSecureText = <plain text>
        System.out.println(strSecureText);
        System.out.println(SecureText.getInstance().decode(strSecureText));
//Test AES and Base64 separated
        String strCoded;
        String strEncrypted;
        String strDecrypted;
        String strDecoded;
        strEncrypted = AdvancedEncryptionStandard.getInstance().encrypt(<plain text>);
        System.out.println(strEncrypted);
        strCoded = Base64Codec.getInstance().encode(strEncrypted);
        System.out.println(strCoded);
        strDecoded = Base64Codec.getInstance().decode(strCoded);
        System.out.println(strDecoded);
        strDecrypted = AdvancedEncryptionStandard.getInstance().decrypt(strDecoded);
        System.out.println(strDecrypted);
        String strSecureText = SecureText.getInstance().encode(<plain text>);
    }
delucaezequiel
  • 161
  • 1
  • 17
  • How are you invoking it? I don't see a `main` method and your code isn't thread-safe, not to mention that it's barely readable because of totally unnecessary constructs such as private getter and setter methods. – SeverityOne Feb 19 '18 at 23:08
  • All the objects were constructed with the Singleton Patter. The invoke method is: SecureText.getInstance().encode() and SecureText.getInstance().decode() – delucaezequiel Feb 19 '18 at 23:29
  • 1
    Please read how to create [mcve]. Yours is not minimal, incomplete and thus not verifiable. – Devstr Feb 19 '18 at 23:35
  • 2
    First of all, I wouldn't just create a string from unknown array of bytes. Especially considering that you don't specify charset. Encrypt string as array of bytes, then pass the array of bytes to base64 codec, then you can use it as a string. Decrypt in the reverse order : string - base64 decode - array of bytes - decrypt - string – Devstr Feb 19 '18 at 23:41
  • Also see why using singletons is generally not so good idea https://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons – Devstr Feb 20 '18 at 00:54

1 Answers1

1

I see two issues with your code (regarding the encryption, for the structure you have enough comments already)

For several text that I tried it works fine, but there are a few strings that are not properly decoded. I found a pattern on the string that could not be decoded.

Never try to represent a random byte array in Java as a String. JVM will try to imply character set conversion and you may loose/change your data. The same applies when you convert a String to bytes, it is good practice to explicitly state the encoding.

Encrypted data are simply a byte array and as soon you plan to print them, encode the byte arrays to something readable, such as hex or base64. Do not use new String(encryptedArray)

Next issue is I don't see you using IV (and it seems to be too much asking for authenticated encryption), please read my blog about how to do encryption at least almost properly.

Devstr
  • 3,786
  • 1
  • 12
  • 27
gusto2
  • 8,500
  • 2
  • 14
  • 26