CrazySabbath
CrazySabbath

Reputation: 1334

Cipher decrypt wrong result

For some reason I can not get cipher to decrypt correctly.

If I run encrypt/decrypt code in one iteration, decrypt works. If I however encrypt a string, then run program again with that encrypted string, decription is wrong.

private final String CIPHER_ALGHORITM = "AES/CTR/NoPadding";

private final String KEY_ALGHORITM = "AES";

private Cipher cipher;

private Key key;

private static Ciphering ciphering;

public static Ciphering get() {
    if (ciphering == null) ciphering = new Ciphering();
    return ciphering;
}

public static void main(String[] args) {
    String input = "test123456789test123456789";
    String encrypted = get().encrypt(input);
    System.out.println(encrypted);
    String decrypted = get().decrypt("96BnAtmlkC49gj4p3/2azkRH6JhufRQ851k=");
    System.out.println(decrypted);
}

private Ciphering() {
    try {
        this.cipher = Cipher.getInstance(CIPHER_ALGHORITM);
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGHORITM);
        keyGenerator.init(256);
        key = keyGenerator.generateKey();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    }
}

public byte [] encrypt(byte [] data) {
    return performOp(Cipher.ENCRYPT_MODE, data, key);
}

public String encrypt(String string) {
    return Base64.getEncoder().encodeToString(encrypt(string.getBytes()));
}

public byte [] decrypt(byte [] data) {
    return performOp(Cipher.DECRYPT_MODE, data, key);
}

public String decrypt(String string) {
    return new String(decrypt(Base64.getDecoder().decode(string)));
}

private byte [] performOp(int opmode, byte [] data, Key key) {
    byte [] result = new byte[] {};

    try {
        IvParameterSpec ivParameterSpec = new IvParameterSpec(new byte[16]);
        cipher.init(opmode, key, ivParameterSpec);
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    }

    try {
        result = cipher.doFinal(data);
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    }

    return result;
}

note hardcoded value in decrypt() in Main. That is a result from encrypt() method from previous iteration. result is: ����#��r��z�EX��>��z��ѧ which is obviously incorrect.

However, main method:

String input = "test123456789test123456789";
String encrypted = get().encrypt(input);
System.out.println(encrypted);
String decrypted = get().decrypt(encrypted);
System.out.println(decrypted);

Gives me a correct result.

What am I missing here? Or am going about this (encrypting string) completely wrong? I admit I'm not very familiar with encryption or java Cipher.

Upvotes: 0

Views: 346

Answers (1)

erickson
erickson

Reputation: 269627

You are generating a new key every time you run the program. It works when you decrypt the result of the current run, because you haven't changed the key. But the ciphertext from a previous run can't be decrypted because you no longer have the key.

Randomly generated keys like these are most commonly exchanged with the message recipient using an additional layer of encryption. You'd make sure you have the authentic public key of the intended recipient (which may be yourself) and encrypt the AES key with that using the RSA algorithm. Later, when the message is to be decrypted, the AES key can be recovered with the RSA private key.

Upvotes: 1

Related Questions