Преобразуйте строку в двоичный, а затем снова с помощью PHP

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

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


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

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

Вы хотите использовать 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)); 

Да, конечно!

Там…

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

… и обратно.

 $char = chr(bindec($bin)); 

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

РЕДАКТИРОВАТЬ

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

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

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

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

Любая строка в 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 

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

Самый простой способ, который я нашел, – преобразовать в 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 

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

 $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 

Я бы определенно рекомендовал использовать встроенные стандартные библиотеки паролей, которые поставляются с 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 

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

 # 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 

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

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

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

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

На практике вы обычно получаете свои 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-массив и упаковать его в строку при взаимодействии с чем-то, использующим строки для двоичных данных. В зависимости от того, в какой степени вы собираетесь изменять blob, это может оказаться проще, и, хотя это неэкономично, я думаю, что вы получите приемлемую производительность для многих задач.

Пример для иллюстрации функциональности:

 // 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"; 

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

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

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

От: 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»), вы не сможете восстановить исходную битовую строку при преобразовании в байтовую строку. Из обратного преобразования bytestring uyou получит «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