将string转换为二进制,然后再使用PHP返回

有没有办法将一个string转换为二进制然后再回到标准的PHP库?

澄清我想要做的是在数据库上存储密码。 我将首先使用散列函数将其转换,然后最终将其存储为二进制。


我发现最好的方法是使用这个function。 似乎在二进制散列和输出的同时。

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

你想使用packbase_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)); 

一个string只是一个字节序列,因此它实际上是PHP中的二进制数据。 你到底在做什么?

编辑

如果要将二进制数据存储在数据库中,最常见的问题就是数据库中的列定义。 PHP不区分二进制数据和string,但是数据库可以。 在MySQL中,例如,您应该将二进制数据存储在BINARYVARBINARYBLOB列中。

另一个select是base64_encode你的PHPstring,并将其存储在数据库的某个VARCHARTEXT列中。 但请注意,使用base64_encode时,string的长度将会增加。

你的散列已经是二进制的,可以和你的数据库一起使用了。

但是,您必须将其转换为数据库列定义所期望的格式。

PHP中的任何string(直到5.3)都是二进制string。 这意味着它只包含二进制数据。

但是由于PHP 6的向后兼容性,你已经可以将你的string明确地转换为二进制:

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

但是这仅仅是出于兼容性的原因,在你的代码中你可以做:

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

因为它是一样的。 “转换”是多余的。

我find的最简单的方法是转换为HEX而不是string。 如果它适合你:

 $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位转换,并在这里,如果下一个案件是你拿/所以…如果你想使用从一个string的位到不同的位,也许这个例子会帮助

 $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自带的标准密码库 – 下面是如何使用它们的一个很好的例子 。


对于那些来到这里想要如何从二进制string到小数点后退,下面有一些很好的例子。

为了将二进制“string”转换为小数/字符,你可以做这样的事情…

 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 

为了将小数转换为字符/string,你可以这样做:

 # 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中的string总是BLOB。 所以你可以使用一个string来保存数据库BLOB的值。 所有这些东西转换等都与提出这个BLOB有关。

如果你想要一个漂亮的人类可读的BLOB表示,那么显示它所包含的字节是有意义的,而且可能使用hex而不是十进制。 因此,string“41 42 43”是呈现 C#中的字节数组的好方法

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

但它显然不是一个好方法来表示这些字节! string“ABC”是一个高效的表示,因为它实际上是相同的BLOB(只是在这种情况下它不是那么大)。

在实践中,您通常会从返回string的函数(如散列函数或其他内置函数(如fread))获取您的BLOB。

在极less数情况下(但只是在尝试/原型时不那么罕见),您只需从某些硬编码字节构造一个string,我就不知道比将“hexstring”转换为什么更有效在PHP中经常被称为“二进制string”:

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

如果你var_dump($data); 它会显示你的string(3) "ABC" 。 这是因为0x41 = 65十进制='A'(基本上所有的编码)。

由于通过将二进制数据解释为string来查看二进制数据并不直观,因此您可能需要制作一个基本的包装来使debugging更容易。 一个可能的这种包装是

 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); } } 

这是我在飞机上制作的东西,可能只是您自己的包装的起点。 但是这个想法是使用一个string进行存储,因为这是PHP中最有效的结构,同时当你想要检查内容时,提供像toArray()这样的方法用于debugging器监视/评估。

当然,你可以使用一个完全简单的PHP数组,并在与使用二进制数据的string进行交互时将其打包。 根据你实际要修改blob的程度,这可能会更容易,尽pipe这不是空间效率,但是我认为你可以在很多任务中获得可接受的性能。

举例说明function:

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

Stefan Gehrig的回答实际上是正确的,这很有趣。 您不需要将string转换为“011010101”string以将其存储在数据库的BINARY字段中。 无论如何,因为这是第一个答案,当你谷歌的“PHP转换string到二进制string”。 这是我对这个问题的贡献。

对于长string(字节串或比特串)而言,Francois Deschenes的答案最多,这是因为

由于与使用的内部“double”或“float”types相关的属性,base_convert()可能会失去大数精度。 请参阅手册中的“浮点数字”部分以获取更多具体信息和限制。

来自: https : //secure.php.net/manual/en/function.base-convert.php

要解决这个限制,可以将inputstring分成块。 下面的function实现这个技术。

 <?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; 

请注意,如果插入的string不是8的倍数(例如:“101”),则在转换为string时,将无法恢复原始位串。 从string转换回来,你会得到数字相同(无符号8位整数),但具有不同的string长度的“00000101”。 因此,如果比特串长度对你很重要,那么你应该把长度保存在一个单独的variables中,并在转换之后将string的第一部分截断。

 $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