Преобразовать строку в двоичный файл, а затем снова использовать PHP - PullRequest
48 голосов
/ 17 июня 2011

Есть ли способ преобразовать строку в двоичный файл и затем снова вернуться в стандартную библиотеку PHP?

Чтобы пояснить, что я пытаюсь сделать, это сохранить пароль в базе данных.Я собираюсь сначала преобразовать его, используя хеш-функцию, а затем в конечном итоге сохранить его в двоичном виде.


Я обнаружил, что лучший способ - использовать эту функцию.Кажется, что хэш и вывод в двоичном виде одновременно.

http://php.net/manual/en/function.hash-hmac.php

Ответы [ 9 ]

50 голосов
/ 17 июня 2011

Вы хотите использовать pack и base_convert.

// Convert a string into binary
// Should output: 0101001101110100011000010110001101101011
$value = unpack('H*', "Stack");
echo base_convert($value[1], 16, 2);

// Convert binary into a string
// Should output: Stack
echo pack('H*', base_convert('0101001101110100011000010110001101101011', 2, 16));
29 голосов
/ 17 июня 2011

Да, конечно!

Там ...

$bin = decbin(ord($char));

... и обратно.

$char = chr(bindec($bin));
9 голосов
/ 17 июня 2011

Строка это просто последовательность байтов, следовательно, на самом деле это двоичные данные в PHP.Что именно вы пытаетесь сделать?

EDIT

Если вы хотите хранить двоичные данные в вашей базе данных, проблема чаще всего заключается в определении столбца в вашей базе данных.PHP не различает двоичные данные и строки, но базы данных делать.Например, в MySQL вы должны хранить двоичные данные в столбцах BINARY, VARBINARY или BLOB.

Другим вариантом будет base64_encode строка PHP и сохранение ее в каком-либо столбце VARCHAR или TEXT в базе данных.Но следует помнить, что длина строки будет увеличиваться при base64_encode используется.

4 голосов
/ 26 июля 2013

Самый простой способ, который я нашел, - это конвертировать в HEX вместо строки.Если это работает для вас:

$hex = bin2hex($bin); // It will convert a binary data to its hex representation

$bin = pack("H*" , $hex); // It will convert a hex to binary

ИЛИ

$bin = hex2bin($hex); // Available only on PHP 5.4
3 голосов
/ 17 июня 2011

Ваш хэш уже является двоичным и готов к использованию с вашей базой данных.

Однако вам необходимо преобразовать его в формат, ожидаемый определением столбца базы данных.

Любая строка в PHP (до версии 5.3) является двоичной строкой. Это означает, что он содержит только двоичные данные.

Однако из-за обратной совместимости с PHP 6 вы уже можете явно преобразовать вашу строку в двоичную форму:

 $string = 'my binary string';
 $binary = b'my binary string';

Но это только из соображений совместимости, в вашем коде вы можете просто сделать:

  $string = $binary; // "convert" binary string into string
  $binary = $string  // "convert" string into binary string

Потому что это то же самое. «Преобразование» является излишним.

0 голосов
/ 26 октября 2017

Забавно, как Стефан Гериг его ответ на самом деле правильный. Вам не нужно преобразовывать строку в строку «011010101», чтобы сохранить ее в поле BINARY в базе данных. Во всяком случае, так как это первый ответ, который появляется, когда вы гуглите "php преобразовать строку в двоичную строку". Вот мой вклад в эту проблему.

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

base_convert () может потерять точность при больших числах из-за свойств, связанных с используемым внутренним типом "double" или "float". Пожалуйста, обратитесь к разделу с числами с плавающей точкой в ​​руководстве для получения более конкретной информации и ограничений.

От: https://secure.php.net/manual/en/function.base-convert.php

Чтобы обойти это ограничение, вы можете разделить входную строку на куски. Приведенные ниже функции реализуют эту технику.

<?php

function bytesToBits(string $bytestring) {
  if ($bytestring === '') return '';

  $bitstring = '';
  foreach (str_split($bytestring, 4) as $chunk) {
    $bitstring .= str_pad(base_convert(unpack('H*', $chunk)[1], 16, 2), strlen($chunk) * 8, '0', STR_PAD_LEFT);
  }

  return $bitstring;
}

function bitsToBytes(string $bitstring) {
  if ($bitstring === '') return '';

  // We want all bits to be right-aligned
  $bitstring_len = strlen($bitstring);
  if ($bitstring_len % 8 > 0) {
    $bitstring = str_pad($bitstring, intdiv($bitstring_len + 8, 8) * 8, '0', STR_PAD_LEFT);
  }

  $bytestring = '';
  foreach (str_split($bitstring, 32) as $chunk) {
    $bytestring .= pack('H*', str_pad(base_convert($chunk, 2, 16), strlen($chunk) / 4, '0', STR_PAD_LEFT));
  }

  return $bytestring;
}

for ($i = 0; $i < 10000; $i++) {
  $bytestring_in = substr(hash('sha512', uniqid('', true)), 0, rand(0, 128));
  $bits = bytesToBits($bytestring_in);
  $bytestring_out = bitsToBytes($bits);
  if ($bytestring_in !== $bytestring_out) {
    printf("IN  : %s\n", $bytestring_in);
    printf("BITS: %s\n", $bits);
    printf("OUT : %s\n", $bytestring_out);
    var_dump($bytestring_in, $bytestring_out); // printf() doesn't show some characters ..
    die('Error in functions [1].');
  }
}


for ($i = 0; $i < 10000; $i++) {
  $len = rand(0, 128);
  $bitstring_in = '';
  for ($j = 0; $j <= $len; $j++) {
    $bitstring_in .= (string) rand(0,1);
  }
  $bytes = bitsToBytes($bitstring_in);
  $bitstring_out = bytesToBits($bytes);

  // since converting to byte we always have a multitude of 4, so we need to correct the bitstring_in to compare ..
  $bitstring_in_old = $bitstring_in;
  $bitstring_in_len = strlen($bitstring_in);
  if ($bitstring_in_len % 8 > 0) {
    $bitstring_in = str_pad($bitstring_in, intdiv($bitstring_in_len + 8, 8) * 8, '0', STR_PAD_LEFT);
  }

  if ($bitstring_in !== $bitstring_out) {
    printf("IN1  : %s\n", $bitstring_in_old);
    printf("IN2  : %s\n", $bitstring_in);
    printf("BYTES: %s\n", $bytes);
    printf("OUT  : %s\n", $bitstring_out);
    var_dump($bytes); // printf() doesn't show some characters ..
    die('Error in functions [2].');
  }
}

echo 'All ok!' . PHP_EOL;

Обратите внимание, что если вы вставите цепочку битов, не являющуюся множеством 8 (пример: «101»), вы не сможете восстановить исходную цепочку битов при преобразовании в строку байтов. Из обратного преобразования байтовой строки вы получите «00000101», которое численно такое же (8-разрядное целое число без знака), но имеет другую длину строки. Поэтому, если для вас важна длина цепочки битов, вы должны сохранить длину в отдельной переменной и обрезать первую часть строки после преобразования.

$bits_in = "101";
$bits_in_len = strlen($bits_in); // <-- keep track if input length
$bits_out = bytesToBits(bitsToBytes("101"));
var_dump($bits_in, $bits_out, substr($bits_out, - $bits_in_len)); // recover original length with substr
0 голосов
/ 06 января 2017

Строки в PHP всегда являются BLOB-объектами.Таким образом, вы можете использовать строку для хранения значения для вашей базы данных BLOB.Все это базовое преобразование и т. Д. Связано с представлением этого BLOB.

Если вы хотите хорошее представление вашего BLOB, понятное человеку, то имеет смысл показать байтыон содержит, и, вероятно, использовать шестнадцатеричный, а не десятичный.Следовательно, строка "41 42 43" - это хороший способ представить байтовый массив, который в C # будет

var bytes = new byte[] { 0x41, 0x42, 0x43 };

, но, очевидно, не aхороший способ представлять эти байты!Строка «ABC» является эффективным представлением, потому что на самом деле это тот же самый BLOB-объект (только в этом случае он не такой большой).

На практике вы обычно получаете свои большие двоичные объекты от функций, которые возвращают строку, таких как эта функция хеширования, или других встроенных функций, таких как fread .

В редких случаях.случаи (но не настолько редкие, когда просто что-то пробуете / прототипируете), когда вам нужно просто создать строку из некоторых жестко закодированных байтов, и я не знаю ничего более эффективного, чем преобразование «шестнадцатеричной строки» в то, что часто называют«бинарная строка» в PHP:

$myBytes = "414243";
$data = pack('H*', $myBytes);

Если вы var_dump($data);, он покажет вам string(3) "ABC".Это потому, что 0x41 = 65 decimal = 'A' (в основном во всех кодировках).

Поскольку просмотр двоичных данных путем интерпретации их как строки не совсем интуитивно понятен, вы можете захотеть сделать базовую оболочку, чтобы упростить отладку.Один из возможных таких оберток - это

class blob
{
    function __construct($hexStr = '')
    {
        $this->appendHex($hexStr);
    }

    public $value;

    public function appendHex($hexStr)
    {
        $this->value .= pack('H*', $hexStr);
    }

    public function getByte($index)
    {
        return unpack('C', $this->value{$index})[1];
    }

    public function setByte($index, $value)
    {
        $this->value{$index} = pack('C', $value);
    }

    public function toArray()
    {
        return unpack('C*', $this->value);
    }
}

Это то, что я приготовил на лету, и, вероятно, просто отправная точка для вашей собственной обертки.Но идея состоит в том, чтобы использовать строку для хранения, поскольку это наиболее эффективная структура, доступная в PHP, и в то же время предоставляемые методы, такие как toArray (), для использования в наблюдениях / оценках отладчика, когда вы хотите изучить содержимое.

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

Пример, иллюстрирующийфункциональность:

// Construct a blob with 3 bytes: 0x41 0x42 0x43.
$b = new blob("414243");

// Append 3 more bytes: 0x44 0x45 0x46.
$b->appendHex("444546");

// Change the second byte to 0x41 (so we now have 0x41 0x41 0x43 0x44 0x45 0x46).
$b->setByte(1, 0x41); // or, equivalently, setByte(1, 65)

// Dump the first byte.
var_dump($b->getByte(0));

// Verify the result. The string "AACDEF", because it's only ASCII characters, will have the same binary representation in basically any encoding.
$ok = $b->value == "AACDEF";
0 голосов
/ 11 июня 2015

Я бы определенно рекомендовал использовать встроенные стандартные библиотеки паролей, которые поставляются с PHP - Вот хороший пример накак их использовать.


Для тех, кто приезжает сюда, чтобы выяснить, как перейти от двоичных строк к десятичным и обратно, есть несколько хороших примеров ниже.

Для преобразования двоичных "строк" в десятичные / символьные числа вы можете сделать что-то вроде этого ...

echo bindec("00000001") . "\n";
echo bindec("00000010") . "\n";
echo bindec("00000100") . "\n";
echo bindec("00001000") . "\n";
echo bindec("00010000") . "\n";
echo bindec("00100000") . "\n";
echo bindec("01000000") . "\n";
echo bindec("10000000") . "\n";
echo bindec("01000001") . "\n";

# big binary string
echo bindec("111010110111011110000110001")."\n";

Приведенные выше выходные данные:

1
2
4
8
16
32
64
128
65
123452465

Для преобразования десятичных знаков в символы / строки вы можете сделать это:

# convert to binary strings "00000001"
echo decbin(1) . "\n";
echo decbin(2) . "\n";
echo decbin(4) . "\n";
echo decbin(8) . "\n";
echo decbin(16) . "\n";
echo decbin(32) . "\n";
echo decbin(64) . "\n";
echo decbin(128) . "\n";

# convert a ascii character
echo str_pad(decbin(65), 8, 0, STR_PAD_LEFT) ."\n";

# convert a 'char'
echo str_pad(decbin(ord('A')), 8, 0, STR_PAD_LEFT) ."\n";

# big number...
echo str_pad(decbin(65535), 8, 0, STR_PAD_LEFT) ."\n";
echo str_pad(decbin(123452465), 8, 0, STR_PAD_LEFT) ."\n";

Вышеуказанные выходные данные:

1
10
100
1000
10000
100000
1000000
10000000
01000001
01000001
1111111111111111
111010110111011110000110001
0 голосов
/ 09 июля 2014

Я искал преобразование битов строк и получил здесь, если следующий случай для вас, возьмите // это так ... если вы хотите использовать биты из строки в разные биты, возможно, этот пример поможет

$string="1001"; //this would be 2^0*1+....0...+2^3*1=1+8=9
$bit4=$string[0];//1
$bit3=$string[1];
$bit2=$string[2];
$bit1=$string[3];//1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...