Подтвердить что ты не робот

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

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

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


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

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

4b9b3361

Ответ 1

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

Ответ 2

Да, конечно!

Там...

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

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

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

Ответ 3

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

ИЗМЕНИТЬ

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

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

Ответ 4

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

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

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

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

Ответ 5

Простым способом я нашел преобразование в 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

Ответ 6

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

$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

Ответ 7

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

# 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

Ответ 8

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

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

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 only ASCII characters, will have the same binary representation in basically any encoding.
$ok = $b->value == "AACDEF";

Ответ 9

Забавно, как Стефан Гериг на самом деле правильный ответ. Вам не нужно преобразовывать строку в строку "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" ), вы не сможете восстановить исходную bitstring при преобразовании в bytestring. Из обратного преобразования 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

Ответ 10

Почему бы не использовать старый и хороший sprintf() со спецификатором "% b"?!

Просто обратите внимание, что приведенный ниже пример не будет работать с многобайтовыми символами, такими как UTF-8, для этого используйте mb_ord() и mb_chr (оба доступны только в PHP 7.2.0 и выше ) вместо ord() и chr(). Здесь это идет:

$s = 'some string';

// string to 8-bit binary:
$binary = '';

for($i = 0; $s[ $i ]; $i++)
{       
    $binary .= sprintf("%08b", ord($s[ $i ])); // use mb_ord for multibyte characters!
}
//

// 8-bit binary string back to regular string
$a = str_split($binary, 8);

$rs = '';

foreach($a as $s2)
{
    $rs .= chr(bindec($s2)); // use mb_chr for multibyte characters!
}
//

echo "\n\nString: ".$rs;