Проблемы с шифрованием / дешифрованием между Android и PHP - PullRequest
1 голос
/ 20 марта 2012

привет, коллеги-программисты,

Я следовал учебному руководству на 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 ... что здесь происходит? Есть идеи ??

Ответы [ 2 ]

1 голос
/ 21 марта 2012

Итак, после долгих исследований и (наконец) перезагрузки компьютера я нашел решение своей проблемы, которым хочу поделиться с вами:

сначала я изменил свою функцию hex2Bin(String str) на следующую:

private byte[] hex2ByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

после этого я все еще получал одну и ту же ошибку снова и снова, Android будет показывать только адрес байтового массива вместо расшифрованной строки, поэтому я обратился к Гарри Поттеру, и он сказал мне магию, чтобы иметь возможность сортировать это и теперь я хочу поделиться этим с вами ... самое главное это .... ПЕРЕЗАГРУЗИТЬ СВОЙ КОМПЬЮТЕР, если вы работаете с Eclipse / Motodev Studio более нескольких часов в день - это сэкономит вам некоторое время и деньги точно;)

0 голосов
/ 28 января 2013

Вы сталкиваетесь с этой проблемой, возможно, потому что когда вы вызываете метод encrypt в PHP, он использует один ключ для шифрования, но , когда вы дешифруете зашифрованную строку в коде Java, вы должны генерировать ключи, которые будут отличаться от ключей PHP , поэтому вы получаете эти специальные символы в расшифрованной строке

Вы можете передавать объекты из PHP в код Java или использовать мост PHP-Java

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...