加密在Android中相当于PHP的MCRYPT_RIJNDAEL_256 [英] Encryption in Android equivalent to php's MCRYPT_RIJNDAEL_256
问题描述
我使用的是下面的PHP code加密:
I am using the below php code for encryption:
$enc_request = base64_encode(
mcrypt_encrypt(MCRYPT_RIJNDAEL_256,
$this->_app_key,
json_encode($request_params),
MCRYPT_MODE_ECB)
);
现在试图加密在Android和获取不同的加密字符串。下面是Android code:
Now trying to encrypt the in android and getting the different encrypted string. Below is the android code:
public void enc(){
byte[] rawKey = getRawKey("my_key".getBytes());
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal("my_message".getBytes());
String result=Base64.encodeToString(encrypted, Base64.DEFAULT);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(256, sr);
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
难道任何一个可以帮助我,我在哪里错了?并获得相同的正确的加密字符串中的机器人了。
Could any one help me, where I am wrong? And get same correct encrypted string in android too.
推荐答案
我已经创建了一个主
方法在Java中使用充气城堡展现的内部运作 mcrypt_encrypt()
在code样品使用。
I've created a main
method in Java using Bouncy Castle to show the inner workings of mcrypt_encrypt()
used in your code sample.
这主要是为了表明其他开发PHP的 mcrypt_encrypt()
是一个非常危险的方法来使用。它不会失败了,但就是因为它,而继续,它应该已经停止很久以前。例如,它增加或从密钥移除值。它发出当它这样做的警告,但在code它不会直接显示
This is mainly to show other developers that PHP's mcrypt_encrypt()
is a very dangerous method to use. It won't fail much, but that is because it rather continues where it should have stopped long ago. For instance, it adds or removes values from the key. It emits a warning when it does do this, but it won't directly show in the code.
public static void main(String[] args) throws DataLengthException, IllegalStateException, InvalidCipherTextException {
// just some constants
boolean ENCRYPT = true;
boolean DECRYPT = false;
// the key is either in binary in PHP or a string (dynamic isn't it?), lets assume ASCII
byte[] givenKey = args[0].getBytes(Charset.forName("ASCII"));
// determine the key size dynamically, somebody thought this was a good idea...
// NOTE: PHP will emit a warning if the key size is larger, but will simply use the
// largest key size otherwise
final int keysize;
if (givenKey.length <= 128 / Byte.SIZE) {
keysize = 128;
} else if (givenKey.length <= 192 / Byte.SIZE) {
keysize = 192;
} else {
keysize = 256;
}
// create a 256 bit key by adding zero bytes to the decoded key
byte[] keyData = new byte[keysize / Byte.SIZE];
System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
KeyParameter key = new KeyParameter(keyData);
// create a Rijndael cipher with 256 bit block size, this is not AES
BlockCipher rijndael = new RijndaelEngine(256);
// use a padding method that only works on data that cannot end with zero valued bytes
ZeroBytePadding c = new ZeroBytePadding();
// use ECB mode encryption, which should never be used
PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(rijndael, c);
// initialize the cipher using the key (no need for an IV, this is ECB)
pbbc.init(ENCRYPT, key);
// create a plain text byte array
byte[] plaintext = args[1].getBytes(Charset.forName("UTF8"));
// create a buffer for the ciphertext
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);
// show the ciphertext
System.out.println(new String(Hex.encode(ciphertext), Charset.forName("ASCII")));
// reverse the encryption
pbbc.init(DECRYPT, key);
byte[] decrypted = new byte[pbbc.getOutputSize(ciphertext.length)];
offset = 0;
offset += pbbc.processBytes(ciphertext, 0, ciphertext.length, decrypted, offset);
offset += pbbc.doFinal(decrypted, offset);
// this will probably print out correctly, but it isn't actually correct
System.out.println(new String(decrypted, Charset.forName("UTF8")));
// check out the zero's at the end
System.out.println(new String(Hex.encode(decrypted), Charset.forName("UTF8")));
// so lets make it a bit shorter... the PHP way
// note that in PHP, the string may *not* contain a null terminator
// add it yourself before printing the string
System.out.println(new String(decrypted, Charset.forName("UTF8")).replaceAll("\\x00+$", ""));
}
这篇关于加密在Android中相当于PHP的MCRYPT_RIJNDAEL_256的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!