How to encrypt or decrypt with Rijndael and a block-size of 256 bits?
Asked Answered
S

2

6

For certain reasons I need to implement Rijndael de/compression with a blocksize of 256 bits instead of AES which uses a block size of 128 bits (reason: data is encrypted in PHP using Rijndael...).

How can I change the block-size for a cipher?

If i just get a cipher with "RIJNDAEL/CFB/PKCS5Padding" and try to initialize a IV with 256 bits I get an exception, because the block-size is only 128 bits.

Showing answered 10/11, 2011 at 16:46 Comment(4)
You'll probably have to ensure you have the Java JCE unlimited encryption classes installed. They're not part of the typical standard Java distribution because they're illegal in some countries.Fifteen
allready have them. still cant find out how to get a cipher object with the required blocksizeShowing
Then I believe @GregS has the answer. I had believed Rijndael-256 was part of JCE Unlimited Providers, but I'm used to using my company's somewhat customized Java - which has a JCE provider for it, but it may well be private implementation.Fifteen
You should remove AES from the title, AES only have been standardized with 128 bits block. The security of Rijndael with 256 bits blocks is not well studied and could well be way weaker than AES. Whatever reason you had to go with Rijndael with 256 bits blocks wasn't a good one likely.Pilgrimage
H
16

There is no support in any of the Sun JCE providers for anything other than Rijndael with the 128-bit blocksize: this is the AES algorithm. To get rijndael with the 256-bit blocksize you will have to go somewhere else. I suggest the Bouncycastle java library. The RijndaelEngine class has a constructor that accepts a block size in bits. Most people find the PaddedBufferedBlockCipher class to be more convenient when used with suitable padding, e.g.

PaddedBufferedBlockCipher c = new PaddedBufferedBlockCipher(new RijndaelEngine(256), new PKCS7Padding());
Hestia answered 10/11, 2011 at 22:20 Comment(0)
K
4

Note that PHP mcrypt uses Zero Byte padding so new ZeroBytePadding() should be used instead of new PKCS7Padding().

Bellow a full implementation using CBC and RIJNDAEL 256.

import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.RijndaelEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.paddings.ZeroBytePadding;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.encoders.Base64;

public static String encryptWithAesCBC(String plaintext, String key, String iv)
{
    try {
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), new ZeroBytePadding());
        CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key.getBytes()), iv.getBytes());
        cipher.init(true, ivAndKey);
        return new String(Base64.encode(cipherData(cipher, plaintext.getBytes())));
    } catch (InvalidCipherTextException e) {
        throw new RuntimeException(e);
    }
}

public static String decryptWithAesCBC(String encrypted, String key, String iv)
{
    try {
        byte[] ciphertext = Base64.decode(encrypted);
        PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), new ZeroBytePadding());

        CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key.getBytes()), iv.getBytes());
        aes.init(false, ivAndKey);
        return new String(cipherData(aes, ciphertext));
    } catch (InvalidCipherTextException e) {
        throw new RuntimeException(e);
    }
}

private static byte[] cipherData(PaddedBufferedBlockCipher cipher, byte[] data) throws InvalidCipherTextException
{
    int minSize = cipher.getOutputSize(data.length);
    byte[] outBuf = new byte[minSize];
    int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
    int length2 = cipher.doFinal(outBuf, length1);
    int actualLength = length1 + length2;
    byte[] cipherArray = new byte[actualLength];
    for (int x = 0; x < actualLength; x++) {
        cipherArray[x] = outBuf[x];
    }
    return cipherArray;
}

 private String md5(String string)
 {
    try {
        java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
        byte[] array = md.digest(string.getBytes());
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < array.length; ++i) {
            sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString();
    } catch (java.security.NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
}

When using CFB, PaddedBufferedBlockCipher should be replace by the following:

PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CFBBlockCipher(new RijndaelEngine(256),8), new ZeroBytePadding());
// PHP mcrypt uses a blocksize of 8 bit for CFB

Usage:

String salt = "fbhweui3497";
String key = md5(salt);
String iv = md5(md5(salt));

String encrypted = encryptWithAesCBC("text to encript", key, iv);

String decrypted = decryptWithAesCBC(encrypted, key, iv);
Keven answered 16/11, 2017 at 8:52 Comment(2)
Can you please provide the md5() ? String md5(String input) { String result = input; MessageDigest md; try { md = MessageDigest.getInstance("MD5"); md.update(input.getBytes()); BigInteger hash = new BigInteger(1, md.digest()); result = hash.toString(16); while (result.length() < 32) { // 40 for SHA-1 result = "0" + result; } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return result; } Above method giving, " java.lang.IllegalArgumentException: Key length not 128/160/192/224/256 bits."Stewartstewed
@Stewartstewed I've just added to the answer the md5 implementation.Keven

© 2022 - 2024 — McMap. All rights reserved.