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

时间:2011-06-17 07:36:40

标签: php binary

有没有办法在标准PHP库中将字符串转换为二进制文件然后再返回?

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


我发现最好的方法是使用这个功能。似乎同时散列并以二进制输出。

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

11 个答案:

答案 0 :(得分:50)

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

答案 1 :(得分:29)

是的,当然!

有...

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

......又回来了。

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

答案 2 :(得分:9)

字符串只是一个字节序列,因此它实际上是PHP中的二进制数据。你究竟想做什么?

修改

如果要在数据库中存储二进制数据,最常出现的问题是数据库中的列定义。 PHP不区分二进制数据和字符串,但数据库确实如此。例如,在MySQL中,您应该将二进制数据存储在BINARY, VARBINARYBLOB列中。

另一个选项是base64_encode您的PHP字符串,并将其存储在数据库的某些VARCHARTEXT列中。但请注意,使用base64_encode时字符串的长度会增加。

答案 3 :(得分:4)

我发现最简单的方法是转换为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

OR

$bin = hex2bin($hex); // Available only on PHP 5.4

答案 4 :(得分:3)

您的哈希已经是二进制文件,可以随数据库一起使用。

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

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 :(得分:1)

2021 年来到这里的任何人,都可以使用 SteeveDroz answer;但不幸的是,这仅适用于 1 个字符。所以我把它放到一个 for 循环中来遍历并改变字符串的每个字符。

编辑:我刚刚意识到我所做的 binary_encode 函数不会将字符转换为 8 位(这非常重要),而是将它们转换为 6-7 位,但幸运的是我需要做的就是在它们前面加上额外的 0需要使它成为 8 位。我更新了下面的编码功能。 此外,我不需要修复解码功能,因为它可以使用前置 0 而没有 :)

功能(更新):

function binary_encode($str){
    
    # Declare both Binary variable and Prepend variable
    $bin = (string)""; $prep = (string)"";
    
    # Iterate through each character of our input ($str) 
    for($i = 0; $i < strlen($str); $i++){
        
        # Encode The current character into binary
        $bincur = decbin( ord( $str[$i] ) );
        
        # Count the length of said binary
        $binlen = strlen( $bincur );
        
        # If the length of our character in binary is less than a byte (8 bits); Then
        # For how ever many characters it is short;
        # it will replace with 0's in our Prepend variable.
        if( $binlen < 8 ) for( $j = 8; $j > $binlen; $binlen++ ) $prep .= "0"; 
        
        # Build our correct 8 bit string and add it to our Binary variable
        $bin .= $prep.$bincur." ";
        
        # Clear our Prepend variable before the next Loop
        $prep = "";

    }

    # Return the final result minus the one whitespace at the end
    # (from our for loop where we build the 8 bit string
    return substr($bin, 0, strlen($bin) - 1);

}

function binary_decode($bin){
    $char = explode(' ', $bin);
    $nstr = '';
    foreach($char as $ch) $nstr .= chr(bindec($ch));
    return $nstr;
}

用法:

$bin = binary_encode("String Here");
$str = binary_decode("1010011 1110100 1110010 1101001 1101110 1100111 100000 1001000 1100101 1110010 1100101");

旧的现场演示:

http://sandbox.onlinephpfunctions.com/code/2553fc9e26c5148fddbb3486091d119aa59ae464

新的现场演示:

http://sandbox.onlinephpfunctions.com/code/1d71888cd41371646431f9914ccd86cf5ef6303e

答案 6 :(得分:0)

我正在寻找一些字符串位转换并到达这里, 如果下一个案例适合你,那就这样吧...... 如果要将字符串中的位用于不同的位  也许这个例子会有所帮助

$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 :(得分:0)

我绝对建议使用come with PHP 的内置标准密码库 - 这是一个很好的example如何使用它们

对于那些来到这里以了解如何从二进制字符串转到十进制字符并返回的人,下面有一些很好的例子。

用于转换二进制&#34;字符串&#34;小数/字符你可以做这样的事情......

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

答案 8 :(得分:0)

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十进制='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";

答案 9 :(得分:0)

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

Francois Deschenes得到的最多回答是错误的长字符串(字节串或位串),因为

  由于与所使用的内部“double”或“float”类型相关的属性,

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时将无法恢复原始位串。从字节串转换回来,你将获得“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 :(得分:0)

为什么要使用PHP进行转换。现在,有太多可用的前端语言,为什么还包括服务器?您可以在前端将密码转换为二进制数,然后在数据库中发送转换后的字符串。根据我的观点,这将很方便。

var bintext, textresult="", binlength;
    this.aaa = this.text_value;
    bintext = this.aaa.replace(/[^01]/g, "");
        binlength = bintext.length-(bintext.length%8);
        for(var z=0; z<binlength; z=z+8) {
            textresult += String.fromCharCode(parseInt(bintext.substr(z,8),2));
                            this.ans = textresult;

这是我在这里找到的Javascript代码:http://binarytotext.net/,他们已将此代码与Vue.js一起使用。在代码中,this.aaa是v模型动态值。为了将二进制转换为文本值,他们使用了大数字。您需要安装其他软件包,然后将其转换回文本字段。在我看来,这很容易。