【问题标题】:JAVA a reliable equivalent for php's MCRYPT_RIJNDAEL_256JAVA 是 php 的 MCRYPT_RIJNDAEL_256 的可靠等价物
【发布时间】:2014-12-21 03:32:35
【问题描述】:

我需要访问一些使用 PHP 加密的数据。 PHP加密是这样的。

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

作为 $text 的值,它们传递 time() 函数值,每次调用该方法时都会有所不同。我已经在 J​​ava 中实现了这一点。像这样,

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));
}

我在创建 MCRYPT_RIJNDAEL_256 方法时参考了这个答案。” Encryption in Android equivalent to php's MCRYPT_RIJNDAEL_256 “我使用了 apache 编解码器用于 Base64。这就是我如何调用加密函数,

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

问题是有时输出与 PHP 不同,但有时可以正常工作。 我认为我的 MCRYPT_RIJNDAEL_256 方法不可靠。 我想知道我哪里出错了,找到一个可靠的方法,这样我总能得到与 PHP 相似的加密字符串。

【问题讨论】:

    标签: java php encryption rijndael


    【解决方案1】:

    问题很可能是ZeroBytePadding。 Bouncy 总是添加/删除至少一个值为 0 的字节(例如 PKCS5Padding,1 到 16 个字节的填充),但 PHP 的一个只填充直到遇到第一个块边界(0 到 15 个字节的填充)。我已经与 Bouncy Castle 军团的 David 讨论过这个问题,但是 PHP 零字节填充非常不适合 Bouncy 填充的方式,所以目前你必须自己做这件事,并且使用没有填充的密码。

    当然,作为真正的解决方案,重写 PHP 部分以使用 AES (MCRYPT_RIJNDAEL_128)、CBC 模式加密、HMAC 身份验证、真正的基于密码的密钥派生函数(PBKDF,例如 PBKDF2 或 bcrypt)和 PKCS#7兼容的填充而不是这种不安全、不兼容的代码。或者,选择 OpenSSL 兼容性或已知的安全容器格式。

    【讨论】:

    • 我曾经尝试创建一个类似的类,试图模仿所有mcrypt_encrypt,但最后我厌恶地放弃了。我确实重写了mcrypt_encrypt 的示例代码,以防止人们落入同一个陷阱。
    • 感谢您所做的一切。我正在创建一个类似于现有 PHP 框架的 java 框架。有许多客户已经在使用 PHP 框架。我会检查我能做些什么来将其更改为 MCRYPT_RIJNDAEL_128。非常感谢。
    猜你喜欢
    • 2010-09-23
    • 2017-06-13
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    相关资源
    最近更新 更多