привет, коллеги-программисты,
Я следовал учебному руководству на http://www.androidsnippets.com/encrypt-decrypt-between-android-and-php, чтобы отправить String
в зашифрованном виде PHP обратно на мой Android-клиент, где я хочу снова его расшифровать. Часть шифрования / дешифрования работает на моем PHP-сервере как чудо, и я также могу доставить зашифрованную строку в мой клиент Android, но я не могу понять, как расшифровать строку в Android ... все, что у меня есть какие-то загадочные (хаха) признаки ...
описание проблемы:
Я отправляю ключ IV и ключ шифрования, сгенерированный на клиенте Android через REST Api, на мой сервер PHP, который обрабатывает некоторые запросы к базе данных и шифрует строку с указанным ключом IV и ключом шифрования, которая затем возвращается клиенту Android.
Клиент может считать возвращаемое значение и получить зашифрованную строку, НО шифрование не работает так, как ожидается ...
Я строго следовал верхнему уроку, но не могу понять, в чем проблема ...
вот код для шифрования на PHP:
class MCrypt {
private $iv;
private $key;
private $mode;
function __construct() {
$this->mode = 'cbc';
}
public function setIV($iv) {
$this->iv = $iv;
}
public function setKey($key) {
//$this->key = $this->hex2bin($key);
$this->key = $key;
}
public function getIV() {
return $this->iv;
}
public function getKey() {
return $this->key;
}
public function encrypt($value) {
$iv = $this->iv;
$td = mcrypt_module_open('rijndael-128', '', $this->mode, $iv);
mcrypt_generic_init($td, $this->key, $iv);
$encrypted = mcrypt_generic($td, $value);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return bin2hex($encrypted);
}
public function decrypt($value) {
$value = $this->hex2bin($value);
$iv = $this->iv;
$td = mcrypt_module_open('rijndael-128', '', $this->mode, $iv);
mcrypt_generic_init($td, $this->key, $iv);
$decrypted = mdecrypt_generic($td, $value);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return utf8_encode(trim($decrypted));
}
protected function hex2bin($hexdata) {
$bindata = '';
for($i = 0; $i < strlen($hexdata); $i += 2) {
$bindata .= chr(hexdec(substr($hexdata, $i, 2)));
}
return $bindata;
}
}
и вот как я это реализовал:
$value = "some data I want to read out";
// create new MCrypt object
$mcrypt = new MCrypt();
// set IV to hash
$mcrypt->setIV($data['iv']);
// set key to salt
$mcrypt->setKey($data['key']);
// encrypt the key
$enc = $mcrypt->encrypt($value);
return array("data"=>$enc);
Таким образом, это возвращает правильно закодированную строку (проверено с помощью функции расшифровки PHP, которая декодирует строку до ожидаемого результата).
Вот как выглядит реализация JAVA:
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import android.util.Log;
публичный класс MCrypt {
private static final String TAG = MCrypt.class.getSimpleName ();
private String iv;
private String key;
private IvParameterSpec mIvParameterSpec;
private SecretKeySpec mSecretKeySpec;
private Cipher mCipher;
public MCrypt(String iv, String key) {
Log.v(TAG, "IV Bytes.length=" + iv.getBytes().length);
this.iv = cut(iv, 16);
Log.i(TAG, "IV = " + this.iv + ", Bytelength=" + this.iv.getBytes().length);
this.key = key;
mIvParameterSpec = new IvParameterSpec(this.iv.getBytes());
mSecretKeySpec = new SecretKeySpec(this.key.getBytes(), "AES");
try {
mCipher = Cipher.getInstance("AES/CBC/NoPadding");
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "Got Exception while initializing mCipher: " + e.toString(), e);
} catch (NoSuchPaddingException e) {
Log.e(TAG, "Got Exception while initializing mCipher: " + e.toString(), e);
}
}
public String getIV() {
return this.iv;
}
public byte[] decrypt(String code) throws Exception {
if(code == null || code.length() == 0) {
throw new Exception("Emtpy string given");
}
byte[] decrypted = null;
try {
mCipher.init(Cipher.DECRYPT_MODE, mSecretKeySpec, mIvParameterSpec);
decrypted = mCipher.doFinal(hexToBytes(code));
} catch(Exception e) {
throw new Exception("[decrypt] " + e.getMessage());
}
return decrypted;
}
private byte[] hexToBytes(String str) {
if (str==null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i=0; i<len; i++) {
buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
}
return buffer;
}
}
private String cut(String s, int n) {
byte[] sBytes = s.getBytes();
if(sBytes.length < n) {
n = sBytes.length;
}
int n16 = 0;
boolean extraLong = false;
int i = 0;
while(i < n) {
n16 += (extraLong) ? 2 : 1;
extraLong = false;
if((sBytes[i] & 0x80) == 0) {
i += 1;
}
else if((sBytes[i] & 0xC0) == 0x80) {
i += 2;
}
else if((sBytes[i] & 0xE0) == 0xC0) {
i += 3;
} else {
i += 4;
extraLong = true;
}
}
return s.substring(0, n16);
}
}
Если я хочу сейчас en / decrypt String (например, «Hello World»), я получаю эту строку взамен: af8d89fa962794d5b945b74c4b6fd9b6, которая декодируется реализацией PHP в «Hello World», но JAVA просто дает некоторые забавные знаки. ..
Я знаю, что это много кода, но я был бы признателен за любую помощь здесь по этому вопросу!
Заранее спасибо за ваше терпение и время, чтобы прочитать ветку;)
Итак, я пришел к выводу, что эти «загадочные» знаки, которые я получил вместо ожидаемого расшифрованного вывода, на самом деле являются адресом самого байтового массива , даже если я пытаюсь создать новая строка из этого байтового массива с использованием String str = new String(byteArray);
Я получаю вывод, который выглядит как [B@44e8c0c8
... что здесь происходит? Есть идеи ??