2010-11-10 20 views
1

Je stocke des informations sensibles dans une base de données mysql au format champ 'texte' qui est crypté en utilisant openssl_public encrypt et qui est chiffré en utilisant openssl_private_decrypt. Le problème auquel je suis confronté est cependant que lorsque j'essaie d'utiliser mon script php pour 'décoder' le texte, la valeur renvoyée a plusieurs apostrophes et citations, rendant le déchiffrement impossible. Une idée de comment réparer ça?Déchiffrer avec openssl_private_decrypt ne marche pas parce que le texte stocke des apostrophes

Remarque: J'ai d'abord essayé de stocker mes informations dans le type de champ 'varbinary' mais le décryptage a échoué à chaque fois. Après avoir passé en revue un peu plus, je pense que php et mysql ont du mal à traiter toutes les informations (~ 800 enregistrements) car parfois les champs sont laissés vides, d'autres fois non. Si je stocke un par un, cela ne pose aucun problème, mais lorsque j'essaie de parcourir la boucle foreach, cela provoque presque toujours des erreurs. Des idées? Script encode est inférieure à:

<?php 

$publickey = file_get_contents("certificate.pem"); 

function encrypt($text) 
    { 
     return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SALT, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); 
    } 


    try { 
     $db = new PDO('mysql:host=localhost;dbname=DBNAME', 'USER', 'PW'); 
     $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     $db->beginTransaction(); 

     $start = microtime(true); 

     $stmt = $db->prepare("SELECT ID, ITEM1_old, ITEM2_old FROM tablename"); 

     $stmt->execute(); 

     $rows = $stmt->fetchAll(); 

     foreach($rows as $row) { 

      $id = $row['0']; 
      $item1 = $row['1']; 
      $item2 = $row['2']; 

      define('SALT', $id); 

      $item1_enc = encrypt($item1); 
      $item2_enc = encrypt($item2); 

      openssl_public_encrypt($item1_enc, $item1_ssl_enc, $publickey); 
      openssl_public_encrypt($item2_enc, $item2_ssl_enc, $publickey); 

      $stmt2 = $db->prepare("UPDATE tablename SET ITEM1_new=?, ITEM2_new=? WHERE ID=?"); 
      $stmt2->execute(array($item1_ssl_enc, $item2_ssl_enc, $id)); 

     } 

     $db->commit(); 
     $db->NULL; 

     $elapsed = microtime(true) - $start; 
     echo "Finished.<br />Elapsed time: ".$elapsed; 
    } 

    catch (PDOException $e) 
    { 
     $db->rollback(); 
     echo "There was a system error.".$e->getMessage();   
    } 
?> 
+0

Je ne pense pas que cela ait quelque chose à voir avec les guillemets. Ces fonctions ne les traitent pas différemment des autres caractères. Peut-être un exemple de code et un message d'erreur réel ou une meilleure description du problème aiderait. Faites-vous quelque chose à ces chaînes autres que l'utilisation de openssl_public_encrypt et openssl_private_decrypt sur eux? –

+0

@Dan - il n'y a pas de message d'erreur sur la page ou dans le journal des erreurs apache. Je vais mettre en place une version modifiée du script, mais les contrôles et les équilibres globaux dans la page est de près de 600 lignes. Je vais résumer. – JM4

+0

Certains enregistrements sont même ignorés COMPLETEMENT pour ITEM1 lors de l'exécution de la boucle foreach alors que ITEM2 pour le même enregistrement n'est pas – JM4

Répondre

1

Le problème est que les chiffrements chiffrent en blocs, si votre texte brut ne cadre pas avec la taille du bloc de l'algorithme de chiffrement, il s'étoffent. C'est normal et correct, ce que vous devez faire est d'emballer un champ de longueur dans les données avant de le crypter comme ça.

$plaintext = 'text to encrypt'; 
$plaintext = pack('V', strlen($plaintext)) . $plaintext; 
$ciphertext = encrypt($plaintext); 

ensuite pour obtenir la sortie de retour:

$plaintext = decrypt($ciphertext); 
$header = unpack('Vsize', $plaintext); 
$plaintext = substr($plaintext, 4, $header['size'] + 4); 

En outre, si votre charge utile est plus de cent octets ou moins, vous ne devriez pas utiliser RSA pour chiffrer l'ensemble de la charge utile, vous devez générer un clé aléatoire, cryptez la charge utile avec la clé, puis cryptez la clé avec votre clé publique/privée. RSA n'est pas conçu pour chiffrer de grandes charges utiles, il est conçu pour partager un secret pour initialiser un chiffrement symétrique plus rapide tel que Blowfish.

Par exemple.

/* Generate the random key */ 
$key = ''; 
for($i = 0; $i < 255; ++$i) 
    $key .= chr(mt_rand(0, 255)); 
$key = sha1($key); 

/* Pack & encrypt the payload with the key */ 
$plaintext = pack('V', strlen($plaintext)) . $plaintext; 
$ciphertext = encrypt($plaintext, $key); 

/* Encrypt the key with the public key */ 
$key  = public_encrypt($key); 
$payload = pack('V', strlen($key)) . $key . $ciphertext; 

Pour déchiffrer

  1. déballer la longueur de clé de charge utile
  2. décoder la clé chiffrée en utilisant la clé publique
  3. Décoder le texte chiffré en utilisant la clé déchiffrée.