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‰Â—
$sDecrypted
und $sEncrypted
waren in Ihrem Code nicht definiert. Sehen Sie sich eine Lösung an, die funktioniert (aber nicht sicher!):
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.
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.
<?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.
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.
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:
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
Einige wichtige Punkte bei der AES-Verschlüsselung:
CBC
.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 key
iv
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/>";
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");
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);
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
.