2013-10-08 3 views
4

У меня есть базовая функция шифрования на C#, которую я использую для шифрования и сохранения файлов сохранения для игры, в которой используются имя пользователя и пароль пользователя для веб-сайта игры. Недавно я понял, что если пользователь должен был изменить свой пароль, это приведет к тому, что их сохранение станет недоступным, поскольку оно зашифровано старым паролем. Итак, я пытаюсь создать функцию PHP, чтобы «переконвертировать» их сохранение, когда они обновляют свой пароль. К сожалению, проблема заключается в том, что C# использует массивы байтов для выполнения хэширования, а PHP использует строки, и я не уверен, как согласовать их. Вот общий процесс:Не знаете, как перенести функцию шифрования C# на PHP

  • хэш имя пользователя (в массив байт)
  • хэш пароля (в массив байт)
  • конкатенации имя пользователя + хэши паролей (в два раза, как длиной массива байт)
  • хэш результат, чтобы получить ключ (который возвращается к длине 256-битной) файл байты за байтом с ключом, чтобы получить зашифрованный файл
  • исключающего

Я не уверен, как аккомпанемент lish это в PHP. Первоначально я пытался использовать unpack('C*', hash("sha256", $thing_to_be_hashed, false)), но это, похоже, не приводило к правильным байтовым массивам. Тогда я попытался это:

$new_key = hash("sha256", hash("sha256", $username, false) . hash("sha256", $newpass, false), false); 
$old_key = hash("sha256", hash("sha256", $username, false) . hash("sha256", $oldpass, false), false); 

$conversion_key = array(); 
for($i = 0; $i < strlen($new_key); ++$i) { 
    $conversion_key[] = $old_key[$i]^$new_key[$i]; 
    // this part with the array is a bit wonky, I know, but it didn't seem like 
    // it would have worked anyway since I was xor'ing things like 'f' and '3' 
    // instead of bytes like '23' and '57'. 
} 
$file_contents = file_get_contents("savefile.sav"); 
for($i = 0; $i < strlen($file_contents); ++$i) { 
    $file_contents[$i] = $file_contents[$i]^$conversion_key[$i % count($conversion_key)]; // I read somewhere I can access $file_contents like this to get bytes 
} 

Ни один из методов работы, к сожалению, на любой стадии (предыдущий метод распаковывать не производит правильные массивы байтов для даже первой стадии хеширования, при этом я не уверен, что я надевал их обратно в строку правильно для второго этапа). Буду признателен за любую помощь, которую я могу получить. Благодаря!

EDIT: Мне пришло в голову unpack() не даст мне правильные байтовые массивы, потому что это буквально расшифровывает строки; поэтому я думаю, что мой главный вопрос - это, во-первых, «как бы преобразовать гекситы, возвращенные hash() в байтовые массивы?» и, во-вторых, «как я могу использовать хэширование этих байтовых массивов?» (с результатом «преобразование байт-массивов обратно в строки гекситов и их хэширование будет достаточным?»)

ответ

2

В отличие от .NET, где строки кодируются последовательностями Unicode, строки PHP являются глупыми последовательностями байтов - по существу , они уже являются байт массивов. Итак, на стороне PHP вы можете делать все, что вам нужно, с строками, и нет необходимости вовлекать массивы вообще, что в свою очередь означает, что unpack не требуется.

Главное, чтобы иметь дело с тем, что хеш-функции PHP возвращают шестнадцатеричное кодирование вместо прямого двоичного вывода по умолчанию. Это очень легко конвертировать из одного в другое: используйте hex2bin, но также гораздо проще просто дать третий (необязательный) аргумент как true.

Таким образом, вы можете получить хэши, которые Вам нужны:

// for convenience 
function sha256($data) { 
    return hash("sha256", $data, true); 
} 

$new_key = sha256(sha256($username).sha256($newpass)); 
$old_key = sha256(sha256($username).sha256($oldpass)); 

Эта функция будет XOR два ключа:

function str_xor($str1, $str2) { 
    if (strlen($str1) != strlen($str2)) { 
     return false; 
    } 

    $len = strlen($str1); 
    for($i=0; $i < $len; $i++) { 
     $str1[$i] = $str1[$i]^$str2[$i]; 
    } 

    return $str1; 
} 

Таким образом, вы можете использовать свой существующий контур в «перешифровать «сохраненные данные от одного ключа к другому.

+0

Итак, по существу, я должен обернуть все мои выходы 'hash' с помощью' hex2bin', прежде чем что-либо делать с ними? Затем я могу получить доступ к каждому байту с помощью '$ string_that_is_secretly_just_bytes [$ i]'? –

+0

@AlexVanLiew: Не нужно, есть третий аргумент в 'hash', который делает это автоматически.Да, вы можете рассматривать строки как массивы напрямую. Я все еще добавляю к ответу. – Jon

+0

У меня создалось впечатление, что аргумент вернул строки типа «1000100100000100», это приятно знать. Я думаю, что это сработает, позвольте мне проверить. –

Смежные вопросы