it-swarm.com.de

PHP AES verschlüsseln/entschlüsseln

Ich habe in PHP ein Beispiel für die Dekodierung von Strings gefunden. Zuerst sieht es sehr gut aus, aber es funktioniert nicht :-(

Weiß jemand, was das Problem ist?

$Pass = "Passwort";
$Clear = "Klartext";

$crypted = fnEncrypt($Clear, $Pass);
echo "Encrypted: ".$crypted."</br>";

$newClear = fnDecrypt($crypted, $Pass);
echo "Decrypted: ".$newClear."</br>";

function fnEncrypt($sValue, $sSecretKey) {
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, $sDecrypted, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_Rand))));
}

function fnDecrypt($sValue, $sSecretKey) {
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, base64_decode($sEncrypted), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_Rand)));
}

Das Ergebnis ist:

Verschlüsselt: boKRNTYYNp7AiOvY1CidqsAn9wX4ufz/D9XrpjAOPk8=

Entschlüsselt: —‚(ÑÁ ^ yË~F'¸®Ó–í œð2Á_B‰Â—

40
Andreas Prang

$sDecrypted und $sEncrypted waren in Ihrem Code nicht definiert. Sehen Sie sich eine Lösung an, die funktioniert (aber nicht sicher!):


HALT!

Dieses Beispiel ist unsicher! Benutze es nicht!


$Pass = "Passwort";
$Clear = "Klartext";        

$crypted = fnEncrypt($Clear, $Pass);
echo "Encrypred: ".$crypted."</br>";

$newClear = fnDecrypt($crypted, $Pass);
echo "Decrypred: ".$newClear."</br>";        

function fnEncrypt($sValue, $sSecretKey)
{
    return rtrim(
        base64_encode(
            mcrypt_encrypt(
                MCRYPT_RIJNDAEL_256,
                $sSecretKey, $sValue, 
                MCRYPT_MODE_ECB, 
                mcrypt_create_iv(
                    mcrypt_get_iv_size(
                        MCRYPT_RIJNDAEL_256, 
                        MCRYPT_MODE_ECB
                    ), 
                    MCRYPT_Rand)
                )
            ), "\0"
        );
}

function fnDecrypt($sValue, $sSecretKey)
{
    return rtrim(
        mcrypt_decrypt(
            MCRYPT_RIJNDAEL_256, 
            $sSecretKey, 
            base64_decode($sValue), 
            MCRYPT_MODE_ECB,
            mcrypt_create_iv(
                mcrypt_get_iv_size(
                    MCRYPT_RIJNDAEL_256,
                    MCRYPT_MODE_ECB
                ), 
                MCRYPT_Rand
            )
        ), "\0"
    );
}

Aber es gibt noch andere Probleme in diesem Code, die ihn unsicher machen, insbesondere die Verwendung der EZB (die keine Verschlüsselung ist, sondern nur ein Baustein, auf dem Verschlüsselungsmodi definiert werden können). Siehe Fab Sa's answer für eine schnelle Lösung der schlimmsten Probleme und Scotts Antwort für eine Anleitung, wie man dies richtig macht.

52
zz1433

Bitte verwenden Sie eine vorhandene secure PHP Verschlüsselungsbibliothek

Es ist im Allgemeinen eine schlechte Idee, Ihre eigene Kryptographie zu schreiben, es sei denn, Sie haben Erfahrung damit, dass die Kryptographieimplementierungen anderer Völker gebrochen werden.

Keines der Beispiele hier authentifiziert den Geheimtext , wodurch sie für Bit-Rewriting-Angriffe anfällig sind.

Wenn Sie PECL-Erweiterungen installieren können, ist libsodium noch besser

<?php
// PECL libsodium 0.2.1 and newer

/**
 * Encrypt a message
 * 
 * @param string $message - message to encrypt
 * @param string $key - encryption key
 * @return string
 */
function safeEncrypt($message, $key)
{
    $nonce = \Sodium\randombytes_buf(
        \Sodium\CRYPTO_SECRETBOX_NONCEBYTES
    );

    return base64_encode(
        $nonce.
        \Sodium\crypto_secretbox(
            $message,
            $nonce,
            $key
        )
    );
}

/**
 * Decrypt a message
 * 
 * @param string $encrypted - message encrypted with safeEncrypt()
 * @param string $key - encryption key
 * @return string
 */
function safeDecrypt($encrypted, $key)
{   
    $decoded = base64_decode($encrypted);
    $nonce = mb_substr($decoded, 0, \Sodium\CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
    $ciphertext = mb_substr($decoded, \Sodium\CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');

    return \Sodium\crypto_secretbox_open(
        $ciphertext,
        $nonce,
        $key
    );
}    

Dann testen Sie es:

<?php
// This refers to the previous code block.
require "safeCrypto.php"; 

// Do this once then store it somehow:
$key = \Sodium\randombytes_buf(\Sodium\CRYPTO_SECRETBOX_KEYBYTES);
$message = 'We are all living in a yellow submarine';

$ciphertext = safeEncrypt($message, $key);
$plaintext = safeDecrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

Dies kann in allen Situationen verwendet werden, in denen Sie Daten an den Client weitergeben (z. B. verschlüsselte Cookies für Sitzungen ohne serverseitigen Speicher, verschlüsselte URL-Parameter usw.), und das mit einem relativ hohen Maß an Sicherheit, dass der Endbenutzer die Daten nicht entschlüsseln oder zuverlässig manipulieren kann damit.

Da libsodium plattformübergreifend ist, vereinfacht dies auch die Kommunikation mit PHP von z. Java-Applets oder native mobile Apps.


Hinweis: Wenn Sie verschlüsselte Cookies von libsodium zu Ihrer App hinzufügen möchten, entwickelt mein Arbeitgeber Paragon Initiative Enterprises eine Bibliothek namens Halite , die all dies für Sie erledigt.

68

Zur Information verwendet MCRYPT_MODE_ECB nicht den IV (Initialisierungsvektor). Der ECB-Modus teilt Ihre Nachricht in Blöcke auf, und jeder Block wird separat verschlüsselt. Ich wirklich nicht empfohlen.

Im CBC-Modus wird die Nachricht IV verwendet, um jede Nachricht eindeutig zu machen. CBC wird empfohlen und sollte anstelle der EZB verwendet werden.

Beispiel:

<?php
$password = "myPassword_!";
$messageClear = "Secret message";

// 32 byte binary blob
$aes256Key = hash("SHA256", $password, true);

// for good entropy (for MCRYPT_Rand)
srand((double) microtime() * 1000000);
// generate random iv
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_Rand);


$crypted = fnEncrypt($messageClear, $aes256Key);

$newClear = fnDecrypt($crypted, $aes256Key);

echo
"IV:        <code>".$iv."</code><br/>".
"Encrypred: <code>".$crypted."</code><br/>".
"Decrypred: <code>".$newClear."</code><br/>";

function fnEncrypt($sValue, $sSecretKey) {
    global $iv;
    return rtrim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, $sValue, MCRYPT_MODE_CBC, $iv)), "\0\3");
}

function fnDecrypt($sValue, $sSecretKey) {
    global $iv;
    return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, base64_decode($sValue), MCRYPT_MODE_CBC, $iv), "\0\3");
}

Sie müssen die IV auffüllen, um jede Nachricht zu decodieren (IV ist nicht secret). Jede Nachricht ist eindeutig, da jede Nachricht eine eindeutige IV hat.

25
Fabien Sa

Wenn Sie keine starke Abhängigkeit verwenden möchten für etwas, das in 15 Zeilen Code lösbar ist, verwenden Sie die integrierten OpenSSL - Funktionen. Die meisten PHP - Installationen werden mit OpenSSL geliefert, das eine schnelle, kompatible und sichere AES-Verschlüsselung in PHP ermöglicht. Nun, es ist sicher, solange Sie die bewährten Methoden anwenden.

Der folgende Code:

  • verwendet AES256 im CBC-Modus
  • ist kompatibel mit anderen AES-Implementierungen, aber nicht mcrypt , da mcrypt PKCS # 5 anstelle von PKCS # 7 verwendet.
  • generiert einen Schlüssel aus dem bereitgestellten Passwort mit SHA256
  • generiert einen hmac-Hash der verschlüsselten Daten für die Integritätsprüfung
  • generiert eine zufällige IV für jede Nachricht
  • setzt der IV (16 Byte) und dem Hash (32 Byte) den Chiffretext voran
  • sollte ziemlich sicher sein

IV ist eine öffentliche Information und muss für jede Nachricht zufällig sein. Der Hash stellt sicher, dass die Daten nicht manipuliert wurden.

function encrypt($plaintext, $password) {
    $method = "AES-256-CBC";
    $key = hash('sha256', $password, true);
    $iv = openssl_random_pseudo_bytes(16);

    $ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
    $hash = hash_hmac('sha256', $ciphertext, $key, true);

    return $iv . $hash . $ciphertext;
}

function decrypt($ivHashCiphertext, $password) {
    $method = "AES-256-CBC";
    $iv = substr($ivHashCiphertext, 0, 16);
    $hash = substr($ivHashCiphertext, 16, 32);
    $ciphertext = substr($ivHashCiphertext, 48);
    $key = hash('sha256', $password, true);

    if (hash_hmac('sha256', $ciphertext, $key, true) !== $hash) return null;

    return openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv);
}

Verwendungszweck:

$encrypted = encrypt('Plaintext string.', 'password'); // this yields a binary string

echo decrypt($encrypted, 'password');
// decrypt($encrypted, 'wrong password') === null
20
blade

Einige wichtige Punkte bei der AES-Verschlüsselung: 

  1. Verwenden Sie niemals Klartext als Verschlüsselungsschlüssel. Hash-Schlüssel immer im Klartext und dann zur Verschlüsselung verwenden. 
  2. Verwenden Sie zur Verschlüsselung und Entschlüsselung immer Random IV (Initialisierungsvektor). Echte Randomisierung ist wichtig. 
  3. Verwenden Sie wie oben erwähnt nicht den Modus ecb , sondern stattdessen CBC.
2
Navneet Kumar

Dies ist eine funktionierende Lösung von AES encryption - implementiert mit openssl. Es verwendet den Cipher Block Chaining Mode (CBC-Mode). So können Sie neben data und keyiv und block size Angeben.

 <?php
      class AESEncryption {

            protected $key;
            protected $data;
            protected $method;
            protected $iv;

            /**
             * Available OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
             *
             * @var type $options
             */
            protected $options = 0;

            /**
             * 
             * @param type $data
             * @param type $key
             * @param type $iv
             * @param type $blockSize
             * @param type $mode
             */
            public function __construct($data = null, $key = null, $iv = null, $blockSize = null, $mode = 'CBC') {
                $this->setData($data);
                $this->setKey($key);
                $this->setInitializationVector($iv);
                $this->setMethod($blockSize, $mode);
            }

            /**
             * 
             * @param type $data
             */
            public function setData($data) {
                $this->data = $data;
            }

            /**
             * 
             * @param type $key
             */
            public function setKey($key) {
                $this->key = $key;
            }

            /**
             * CBC 128 192 256 
              CBC-HMAC-SHA1 128 256
              CBC-HMAC-SHA256 128 256
              CFB 128 192 256
              CFB1 128 192 256
              CFB8 128 192 256
              CTR 128 192 256
              ECB 128 192 256
              OFB 128 192 256
              XTS 128 256
             * @param type $blockSize
             * @param type $mode
             */
            public function setMethod($blockSize, $mode = 'CBC') {
                if($blockSize==192 && in_array('', array('CBC-HMAC-SHA1','CBC-HMAC-SHA256','XTS'))){
                    $this->method=null;
                    throw new Exception('Invalid block size and mode combination!');
                }
                $this->method = 'AES-' . $blockSize . '-' . $mode;
            }

            /**
             * 
             * @param type $data
             */
            public function setInitializationVector($iv) {
                $this->iv = $iv;
            }

            /**
             * 
             * @return boolean
             */
            public function validateParams() {
                if ($this->data != null &&
                        $this->method != null ) {
                    return true;
                } else {
                    return FALSE;
                }
            }

            //it must be the same when you encrypt and decrypt
            protected function getIV() { 
                return $this->iv;
            }

             /**
             * @return type
             * @throws Exception
             */
            public function encrypt() {
                if ($this->validateParams()) { 
                    return trim(openssl_encrypt($this->data, $this->method, $this->key, $this->options,$this->getIV()));
                } else {
                    throw new Exception('Invalid params!');
                }
            }

            /**
             * 
             * @return type
             * @throws Exception
             */
            public function decrypt() {
                if ($this->validateParams()) {
                   $ret=openssl_decrypt($this->data, $this->method, $this->key, $this->options,$this->getIV());

                   return   trim($ret); 
                } else {
                    throw new Exception('Invalid params!');
                }
            }

        }

Beispielnutzung:

<?php
        $data = json_encode(['first_name'=>'Dunsin','last_name'=>'Olubobokun','country'=>'Nigeria']);
        $inputKey = "W92ZB837943A711B98D35E799DFE3Z18";
        $iv = "tuqZQhKP48e8Piuc";
        $blockSize = 256;
        $aes = new AESEncryption($data, $inputKey, $iv, $blockSize);
        $enc = $aes->encrypt();
        $aes->setData($enc);
        $dec=$aes->decrypt();
        echo "After encryption: ".$enc."<br/>";
        echo "After decryption: ".$dec."<br/>";
1

Wenn Sie MCRYPT_RIJNDAEL_128 verwenden, versuchen Sie es mit rtrim($output, "\0\3"). Wenn die Länge der Zeichenfolge kleiner als 16 ist, gibt die Entschlüsselungsfunktion eine Zeichenfolge mit einer Länge von 16 Zeichen zurück und fügt am Ende 03 hinzu.

Sie können dies leicht überprüfen, z. indem Sie versuchen:

$string = "TheString";
$decrypted_string = decrypt_function($stirng, $key);

echo bin2hex($decrypted_string)."=".bin2hex("TheString");
1
Kamen

Ich verwende den Code für CCAVenue Payment Gateway

class AES {

    public function encrypt($plainText, $key) {
        $secretKey = $this->hextobin(md5($key));
        $initVector = pack("C*", 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f);
        $openMode = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', '');
        $blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, 'cbc');
        $plainPad = $this->pkcs5_pad($plainText, $blockSize);
        if (mcrypt_generic_init($openMode, $secretKey, $initVector) != -1) {
            $encryptedText = mcrypt_generic($openMode, $plainPad);
            mcrypt_generic_deinit($openMode);
        }
        return bin2hex($encryptedText);
    }

    public function decrypt($encryptedText, $key) {
        $secretKey = $this->hextobin(md5($key));
        $initVector = pack("C*", 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f);
        $encryptedText = $this->hextobin($encryptedText);
        $openMode = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', '');
        mcrypt_generic_init($openMode, $secretKey, $initVector);
        $decryptedText = mdecrypt_generic($openMode, $encryptedText);
        $decryptedText = rtrim($decryptedText, "\0");
        mcrypt_generic_deinit($openMode);
        return $decryptedText;
    }

    //*********** Padding Function *********************

    public function pkcs5_pad($plainText, $blockSize) {
        $pad = $blockSize - (strlen($plainText) % $blockSize);
        return $plainText . str_repeat(chr($pad), $pad);
    }

    //********** Hexadecimal to Binary function for php 4.0 version ********

    public function hextobin($hexString) {
        $length = strlen($hexString);
        $binString = "";
        $count = 0;
        while ($count < $length) {
            $subString = substr($hexString, $count, 2);
            $packedString = pack("H*", $subString);
            if ($count == 0) {
                $binString = $packedString;
            } else {
                $binString .= $packedString;
            }

            $count += 2;
        }
        return $binString;
    }

}

Benutzer des Codes

$obj = new AES();
$key = "XXXXXXXXXXXXXXXX";
$plainText = "Hello World";
$encryptedText = $obj->encrypt($plainText, $key);
$rcvdString=$obj->decrypt($encryptedText,$key);
0
Nanhe Kumar

Wenn Sie PHP> = 7.2 verwenden, sollten Sie die eingebaute Natriumkern-Erweiterung für die Verschlüsselung verwenden. 

Weitere Informationen finden Sie hier - http://php.net/manual/en/intro.sodium.php.

0
M_R_K