Convertir la chaîne de caractères en binaire puis revenir en utilisant PHP

y a-t-il un moyen de convertir une chaîne en binaire puis de revenir dans la bibliothèque PHP standard?

pour clarifier ce que j'essaie de faire est de stocker un mot de passe dans une base de données. Je vais d'abord le convertir en utilisant une fonction de hachage, puis éventuellement le stocker en binaire.


j'ai trouvé la meilleure façon est d'utiliser cette fonction. Semble hachage et sortie en binaire en même temps.

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

45
demandé sur casperOne 2011-06-17 11:36:39

9 réponses

vous voulez utiliser pack et 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));
48
répondu Francois Deschenes 2012-11-12 19:38:25

Oui, bien sûr!

là...

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

... et de retour à nouveau.

$char = chr(bindec($bin));
27
répondu SteeveDroz 2011-06-17 07:47:08

une chaîne de caractères est juste une séquence d'octets, donc ce sont en fait des données binaires en PHP. Qu'est-ce exactement que vous essayez de faire?

MODIFIER

si vous voulez stocker des données binaires dans votre base de données, le problème le plus souvent est la définition de la colonne dans votre base de données. PHP ne fait pas de différence entre les données binaires et les chaînes, mais les bases de données le font. Dans MySQL par exemple, vous devriez stocker des données binaires dans BINARY , VARBINARY ou BLOB colonnes.

une autre option serait de base64_encode votre chaîne PHP et de le stocker dans quelque VARCHAR ou TEXT colonne dans la base de données. Mais sachez que la longueur de la chaîne augmentera quand base64_encode est utilisé.

9
répondu Stefan Gehrig 2011-06-17 07:57:44

la façon la plus facile que j'ai trouvée était de convertir en HEX au lieu d'une chaîne. Si cela vous convient:

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

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

ou

$bin = hex2bin($hex); // Available only on PHP 5.4
4
répondu Regis Camimura 2013-07-26 17:17:49

votre hachage est déjà binaire et prêt à être utilisé avec votre base de données.

cependant, vous devez avoir besoin de le convertir dans un format que la définition de colonne de base de données attend.

toute chaîne en PHP (jusqu'à 5.3) est une chaîne binaire. Cela signifie qu'il ne contient que des données binaires.

Cependant, en raison de la compatibilité avec PHP 6, Vous pouvez déjà lancer votre chaîne explicitement en tant que binaire:

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

mais c'est simplement pour des raisons de compatibilité, dans votre code vous pouvez juste faire:

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

Parce que c'est la même chose. Le "converti" est superflu.

3
répondu hakre 2011-06-17 07:56:40

je cherchais une conversion de bits de corde et je suis arrivé ici, Si le prochain cas est pour vous prenez / / il en est ainsi... si vous voulez utiliser les bits d'une chaîne en bits différents peut-être que cet exemple pourrait aider

$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
0
répondu shoetrax 2014-07-09 18:14:02

je recommanderais très certainement l'utilisation des bibliothèques de mots de passe standards que viennent avec PHP - voici un bon exemple sur la façon de les utiliser.


pour ceux qui viennent ici pour comprendre comment passer des chaînes binaires aux décimales et vice-versa, il y a quelques bons exemples ci-dessous.

pour la conversion binaire "chaînes" de décimales/caractères que vous pouvez faire quelque chose comme cela...

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

les sorties ci-dessus:

1
2
4
8
16
32
64
128
65
123452465

pour convertir les décimales en char/strings vous pouvez faire ceci:

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

les sorties ci-dessus:

1
10
100
1000
10000
100000
1000000
10000000
01000001
01000001
1111111111111111
111010110111011110000110001
0
répondu MichaelICE 2015-06-11 14:11:11
Les chaînes

en PHP sont toujours des BLOBs. Ainsi, vous pouvez utiliser une chaîne de caractères pour maintenir la valeur de votre BLOB de base de données. Tout ce truc conversion de base et ainsi de suite a à voir avec présentant que BLOB.

si vous voulez une belle représentation de votre BLOB lisible par l'homme, alors il est logique de montrer les octets qu'elle contient, et probablement d'utiliser hex plutôt que décimal. Par conséquent, la chaîne "41 42 43" est un bon moyen de présent le byte tableau qui en C# serait

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

mais il est évidemment pas une bonne façon de représenter ces octets! La chaîne "ABC" est une représentation efficace, parce qu'elle est en fait le même BLOB (seulement il n'est pas si grand dans ce cas).

dans la pratique, vous obtiendrez généralement vos BLOBs à partir de fonctions qui renvoient la chaîne-comme cette fonction de hachage, ou d'autres fonctions intégrées comme fread .

dans les rares cas (mais pas si rares lors de l'essai/prototypage) que vous devez juste construire une chaîne à partir de quelques octets codés en dur Je ne sais pas quoi de plus efficace que de convertir une "chaîne hex" en ce qui est souvent appelé une "chaîne binaire" en PHP:

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

si vous var_dump($data); ça vous montrera string(3) "ABC" . C'est parce que 0x41 = 65 décimal = 'A' (dans pratiquement tous les encodages).

comme regarder des données binaires en les interprétant comme une chaîne de caractères n'est pas tout à fait intuitif, vous pouvez vouloir faire un wrapper de base pour faciliter le débogage. Un tel emballage possible est

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

C'est quelque chose que j'ai cuit à la volée, et probablement qu'un point de départ pour votre propre emballage. Mais l'idée est d'utiliser une chaîne de caractères pour le stockage car C'est la structure la plus efficace disponible en PHP, tout en fournissant des méthodes comme toArray () pour une utilisation dans debugger montres / évaluations quand vous voulez examiner le contenu.

bien sûr, vous pouvez utiliser un tableau PHP parfaitement simple à la place et l'empaqueter sur une chaîne de caractères lors de l'interfaçage avec quelque chose qui utilise des chaînes de caractères pour les données binaires. Selon le degré auquel vous allez réellement modifier le blob cela peut se révéler plus facile, et bien que ce ne soit pas efficace de l'espace je pense que vous obtiendriez des performances acceptables pour de nombreuses tâches.

un exemple pour illustrer le fonctionnalité:

// 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
répondu Dojo 2017-01-06 13:11:19

C'est drôle comment Stefan Gehrig sa réponse est en fait la bonne. Vous n'avez pas besoin de convertir une chaîne en chaîne "011010101" pour la stocker dans un champ binaire dans une base de données. Quoi qu'il en soit puisque c'est la première réponse qui apparaît lorsque vous google pour "PHP convertir chaîne en chaîne binaire". Voici ma contribution à ce problème.

la réponse la plus votée de François Deschenes se trompe pour de longues cordes (bytestrings ou bitstrings) qui est parce que

base_convert () peut perdre de la précision sur les grands nombres en raison des propriétés liées au type interne "double" ou "float" utilisé. Veuillez consulter la section numéros à virgule flottante du manuel pour obtenir des renseignements plus précis et connaître les limites.

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

Pour contourner cette limitation, vous pouvez couper la chaîne d'entrée en morceaux. Les fonctions ci-dessous implémentent cette technique.

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

notez que si vous insérez un bitstring qui n'est pas une multitude de 8 (Exemple:" 101"), vous ne pourrez pas récupérer le bitstring original lorsque vous le convertirez en bytestring. À partir de la conversion bytestring back, uyou obtiendra "00000101" qui est numériquement le même (entier 8 bits non signé) mais a une longueur de chaîne différente. Par conséquent, si la longueur de bitstring est importante pour vous, vous devez sauvegarder longueur dans une variable séparée et côtelette de la première partie de la chaîne après conversion.

$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
répondu Flip 2017-10-26 13:34:33