@romaprogrammer

Как реализовать шифрование данных на php?

Вот пример на js
function decryptRandomNumber (pwdHash, encryptedRandomNumber) {

        var key = CryptoJS.enc.Utf8.parse(pwdHash);

        var encrypted = CryptoJS.enc.Hex.parse(encryptedRandomNumber.toUpperCase());

        var result = CryptoJS.AES.decrypt({
            ciphertext: encrypted
        }, key , {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        }).toString(CryptoJS.enc.Utf8);

        return result;
    }

    function encryptPwdHash (pwdHash, randomNumber) {

        var randomNumberMd5 = CryptoJS.MD5(randomNumber).toString().toUpperCase();
        var key = CryptoJS.enc.Utf8.parse(randomNumberMd5);
        var result = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(pwdHash), key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        }).ciphertext;

        return result;
    }

Нужно переформатировать на php.

Расшифровку смог сделать вот этой функцией
function aes128_cbc_decrypt($key, $data, $iv) {
      $data = pack("H*", $data);
      $iv = pack("H*", $iv);
      $dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC,   $iv);
      return $dec;
     }


Входящие параметры --> `$key = strtoupper(md5($password));`
хеш пароля
`$data = '54BAA6158E81E1069EA2AB1C4F9D1F29';`- хеш рандомного числа `$iv = '00000000000000000000000000000000';` - вектор в виде 16 - ти ричной константы.

Вот теперь нужно зашифровать обратно пароль с помощью рандомного числа и отправить написал функцию которая делает подобное
function aes128_cbc_encript($key, $data, $iv) {
        $key = pack("H*", strtoupper(md5($key)));
        //var_dump($data);
        //$data = pack("H*", $data);
        $iv = pack("H*", $iv);
        //$enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
        $enc = openssl_encrypt($data,  'AES-128-CBC', $key, true, $iv);
        return bin2hex($enc);
     }

Пробую запускать
$decript = '34345'; // расшифрованное рандомное число
    $pswdHash = strtoupper(md5($password));

    $encript = aes128_cbc_encript($decript, $pswdHash, '00000000000000000000000000000000');

На выходе получаю нечто - `72fc1b49db86787b749c3323421496af00933eb79a9b7d845a51f5ea3fefdf750800554f5fdf0c7d3d765fe7f6653da3`

Такой шифр и должен быть по длинне и в 16 - ти разрядном виде, но он не правильный и при отправке на сервер он не расшифровуется.

Вот пример функции на Oracle которые на сервере делают расшифровку
Fc_Decrypt_Password_Hash(In_Encrypted_Password_Hash In Varchar2,
              In_Random_Number_Md5  In Varchar2) Return Varchar2 Is
              Raw_Random_Number_Md5 Raw(2000);
              Raw_Result            Raw(2000);
              Result                Varchar2(2000);
      Begin
          Raw_Random_Number_Md5 := Utl_I18n.String_To_Raw(Upper(In_Random_Number_Md5), 'AL32UTF8');
          Raw_Result := Dbms_Crypto.Decrypt(Typ => Dbms_Crypto.Aes_Cbc_Pkcs5, Src => Upper(In_Encrypted_Password_Hash), Key => Raw_Random_Number_Md5);
         Result := Utl_I18n.Raw_To_Char(Raw_Result, 'AL32UTF8');
       Return(Result);
      End;

  • Вопрос задан
  • 1900 просмотров
Пригласить эксперта
Ответы на вопрос 1
ZaitsZaits
@ZaitsZaits
Web-разработчик
Попробуйте так:

JS:
/**
 * Зашифровать сообщение AES ключом
 * 
 * @param string шифруемое сообщение
 * @param key ключ, 8 символов от 0 до F
 * @return string зашифрованное сообщение
 */
function encrypt (string, key){
  var mykey = CryptoJS.enc.Hex.parse(key+key+key+key);
  var iv  = CryptoJS.enc.Hex.parse('00000000000000000000000000000000');
  string='_crc_'+string+String.fromCharCode(0);
  var len=string.length;
  var ost=len%16;
  for (var i=0;i<ost-1;i++)
      string=string+String.fromCharCode(getRandomInt(65,90));
  var encrypted = CryptoJS.AES.encrypt(
    string, 
    mykey, 
    {
      keySize: 128 / 8, 
      iv: iv, 
      mode: CryptoJS.mode.CBC, 
      padding: CryptoJS.pad.Pkcs7
    }
  );
  var encr=encrypted.ciphertext.toString(CryptoJS.enc.Hex);
  return encr;
}

/**
 * Расшифровать сообщение AES ключом
 * 
 * @param crypted зашифрованные данные
 * @param key ключ, 8 символов от 0 до F
 * @return string расшифрованное сообщение
 */
function decrypt(crypted, key) {
  try {
    var mykey = CryptoJS.enc.Hex.parse(key+key+key+key);
    var iv  = CryptoJS.enc.Hex.parse('00000000000000000000000000000000');
    var ciphertext = CryptoJS.enc.Hex.parse(crypted);
    var encrypted = new Object();
    encrypted.ciphertext = ciphertext;
    var decrypted = CryptoJS.AES.decrypt(
      encrypted, 
      mykey, 
      {
        keySize: 128 / 8, 
        iv: iv, 
        mode: CryptoJS.mode.CBC, 
        padding: CryptoJS.pad.Pkcs7
      }
    );
    var decr=CryptoJS.enc.Utf8.stringify(decrypted);
  
    var decr2 = "";
    var endIndex = 0;
    for (var i = 0; i<decr.length; i++) {
      if (decr.charCodeAt(i)==0) {
        endIndex=i;
        break;
      }
    }
    
    decr2=decr.substr(0, endIndex);
    
    if (decr2.indexOf('_crc_') !== 0) throw new Error(); 
      
    return decr2.substr(5);
      
  } catch (e) {
      throw "Ошибка расшифровки ответа сервера"; 
  }
}


PHP:
function encrypt ($string, $key) {
    
  //проверяем, чтобы длина ключа была 8 символов
  if (mb_strlen($key,'utf-8') !== 8) 
    throw new Exception ("Длина ключа должна быть 8 символов");

  //устанавливаем тип алгоритма
  $keySize      = MCRYPT_RIJNDAEL_128;
  $mode         = MCRYPT_MODE_CBC;

  //формируем полный ключ, полный ключ состоит из повторяющихся четыре раза ключа, итого 32 байта
  $fullkeystring=$key.$key.$key.$key;

  //преобразуем ключ из строки в байтовый массив
  $mykey=pack("H*",strtoupper($fullkeystring));

  //IV используем нулевой
  $iv=pack("H*",'00000000000000000000000000000000');

  //добавляем к сообщению заголовок, по которому потом будем определять, расшифровалось или нет, в конец записываем 0
  $string='_crc_'.$string.chr(0);

  //дополняем строку до границы разным мусором
  $len=strlen($string);
  $ost=$len % 16;
  for ($i=0;$i<$ost-1;$i++) 
    $string=$string.chr(rand(65, 90));

  //шифруем
  $ciphertext = mcrypt_encrypt($keySize, $mykey, $string, $mode, $iv); 

  //преобразуем байтовый массив в строку содержащую шестнадцатеричный код, и возвращаем ее
  return strtoupper(bin2hex($ciphertext));
}

function decrypt ($crypted, $Key) {

  //проверяем, чтобы длина ключа была 8 символов
  if (mb_strlen($Key,'utf-8') !== 8) 
    throw new Exception ("Неверная длина ключа");

  //устанавливаем тип алгоритма
  $keySize      = MCRYPT_RIJNDAEL_128;
  $mode         = MCRYPT_MODE_CBC;

  //формируем полный ключ, полный ключ состоит из повторяющихся четыре раза ключа, итого 32 байта
  $fullkeystring=$Key.$Key.$Key.$Key;

  //преобразуем ключ из строки в байтовый массив
  $mykey=pack("H*",strtoupper($fullkeystring));

  //IV используем нулевой
  $iv=pack("H*",'00000000000000000000000000000000');

  //преобразуем строку к верхнему регистру, а затем из шестнадцатеричного кода преобразуем в массив байтов
  $BinMessage=pack("H*",strtoupper($crypted));

  //дешифруем сообщение
  $decrypt=mcrypt_decrypt($keySize, $mykey, $BinMessage, $mode, $iv); 

  //обрезаем пробелы
  $result = trim($decrypt);

  //проверяем, корректно ли расшифровалось, или нет
  if (strpos($result,'_crc_') !== false && strpos($result,'_crc_') === 0) {

    //убираем лишний мусор содержащейся в конце строки
    if (strpos($result, chr(0))>0)
      $result = substr($result, 0, strpos($result, chr(0)));

    return substr ($result, 5);  //если все нормально, возвращаем строку
  }
  else throw new Exception ("Неверный ключ шифрования");
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы