JAVA is robust php equivalent MCRYPT_RIJNDAEL_256

I need to access some data using PHP encryption. PHP encryption looks like this.

base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($cipher), $text, MCRYPT_MODE_ECB));
      

They pass the value of $ text to the time () function, which will be different each time the method is called. I have implemented this in Java. Like this,

public static String md5(String string) {
    byte[] hash;

    try {
        hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("Huh, MD5 should be supported?", e);
    } catch (UnsupportedEncodingException e) {
        throw new RuntimeException("Huh, UTF-8 should be supported?", e);
    }

    StringBuilder hex = new StringBuilder(hash.length * 2);

    for (byte b : hash) {
        int i = (b & 0xFF);
        if (i < 0x10) hex.append('0');
        hex.append(Integer.toHexString(i));
    }

    return hex.toString();
}

public static byte[] rijndael_256(String text, byte[] givenKey) throws DataLengthException, IllegalStateException, InvalidCipherTextException, IOException{
    final int keysize;

    if (givenKey.length <= 192 / Byte.SIZE) {
        keysize = 192;
    } else {
        keysize = 256;
    }

    byte[] keyData = new byte[keysize / Byte.SIZE];
    System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
    KeyParameter key = new KeyParameter(keyData);
    BlockCipher rijndael = new RijndaelEngine(256);
    ZeroBytePadding c = new ZeroBytePadding();
    PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(rijndael, c);
    pbbc.init(true, key);

    byte[] plaintext = text.getBytes(Charset.forName("UTF8"));
    byte[] ciphertext = new byte[pbbc.getOutputSize(plaintext.length)];
    int offset = 0;
    offset += pbbc.processBytes(plaintext, 0, plaintext.length, ciphertext, offset);
    offset += pbbc.doFinal(ciphertext, offset);
    return ciphertext;
}


public static String encrypt(String text, String secretKey) throws Exception {


    byte[] givenKey = String.valueOf(md5(secretKey)).getBytes(Charset.forName("ASCII"));

    byte[] encrypted = rijndael_256(text,givenKey);

    return new String(Base64.encodeBase64(encrypted));
}

      

I referred to this answer when creating the MCRYPT_RIJNDAEL_256 method. " Android encryption equivalent to MCRYPT_RIJNDAEL_256 php " I used the apache codec for Base64. This is how I call the encryption function,

long time= System.currentTimeMillis()/1000;
String encryptedTime = EncryptionUtils.encrypt(String.valueOf(time), secretkey);
      

The problem is that sometimes the output doesn't look like PHP, but sometimes it works fine. I find my MCRYPT_RIJNDAEL_256 method unreliable. I want to know where I went wrong and find a reliable method so that I can always get a similar encrypted string like PHP.

+3


source to share


1 answer


The problem is likely to be ZeroBytePadding

. One of Bouncy always adds / removes at least one byte with a null value (a la PKCS5Padding, 1 to 16 padding bytes), but one of PHP only works until the first frame boundary is encountered (0 to 15 padding bytes ). I discussed this with David from the Bouncy Castle legion, but PHP null byte padding is very poorly suited to the way Bouncy does the padding, so nowadays you have to do it yourself and use a no padding cipher.



Of course, as a real solution, rewrite the PHP part to use AES ( MCRYPT_RIJNDAEL_128

), CBC mode encryption, HMAC authentication, real password based key determination function (PBKDF like PBKDF2 or bcrypt) and PKCS # 7 compliant addition instead of this insecure, incompatible code. Alternatively, you can use OpenSSL interoperability or the well-known secure container format.

+1


source







All Articles