我需要访问一些使用PHP加密的数据。 PHP加密就是这样。
base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($cipher), $text, MCRYPT_MODE_ECB));
作为$ text的值,它们传递time()函数值,每次调用该方法时都会有所不同。我已经用Java实现了它。像这样,
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方法时已经提到了这个答案。&#34; Encryption in Android equivalent to php's MCRYPT_RIJNDAEL_256 &#34;我已经为Base64使用了apache编解码器。这就是我如何调用加密函数,
long time= System.currentTimeMillis()/1000;
String encryptedTime = EncryptionUtils.encrypt(String.valueOf(time), secretkey);
问题是有时输出与PHP不相似,但有时它工作正常。 我认为我的MCRYPT_RIJNDAEL_256方法不可靠。 我想知道我哪里出错并找到一个可靠的方法,这样我总能获得与PHP类似的加密字符串。
答案 0 :(得分:1)
问题可能是ZeroBytePadding
。 Bouncy中的一个总是添加/删除至少一个值为零的字节(一个PKCS5Padding,1到16个字节的填充),但PHP中的一个仅填充,直到遇到第一个块边界(0到15个字节的填充)。我和Bouncy Castle军团的大卫讨论了这个问题,但PHP零字节填充对于Bouncy填充的方式非常不合适,所以目前你必须自己做这个,并使用没有填充的密码。
当然,作为一个真正的解决方案,重写PHP部分以使用AES(MCRYPT_RIJNDAEL_128
),CBC模式加密,HMAC身份验证,真正的基于密码的密钥派生功能(PBKDF,例如PBKDF2或bcrypt)和PKCS #7兼容填充,而不是这种不安全,不兼容的代码。或者,请寻求OpenSSL兼容性或已知的安全容器格式。