it-swarm-tr.com

PHP AES şifrelemek/şifresini çözmek

PHP'de en/decoding dizeleri için bir örnek buldum. İlk başta çok iyi görünüyor ama işe yaramaz :-(

Problemin ne olduğunu bilen kimse var mı?

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

Sonuç:

Şifreli: boKRNTYYNp7AiOvY1CidqsAn9wX4ufz/D9XrpjAOPk8=

Şifresi çözülmüş: —‚(ÑÁ ^ yË~F'¸®Ó–í œð2Á_B‰Â—

40
Andreas Prang

$sDecrypted ve $sEncrypted kodunuzda tanımlanmadı. Çalışan bir çözüme bakın ( ancak güvenli değil! ):


DUR!

Bu örnek güvensiz! Kullanmayın!


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

Ancak bu kodda, özellikle ECB (bir şifreleme modu olmayan, yalnızca bir şifreleme modlarının tanımlanabildiği yapı bloğu). Bkz. Fab Sa'nın cevabı en kötü problemlerin hızlıca düzeltilmesi için ve Scott'ın cevabı bu hakkın nasıl yapılacağı için.

52
zz1433

Lütfen varolan güvenli PHP şifreleme kitaplığını kullanın

Diğer insanların şifreleme uygulamalarını çiğneme deneyiminiz yoksa, genellikle kendi şifrelemenizi yazmak kötü bir fikirdir.

Buradaki örneklerin hiçbiri şifrelenmemiş metni doğrular, bu da onları yeniden yazma saldırılarına karşı savunmasız bırakır.

PECL eklentilerini yükleyebilirseniz, libsodium daha da iyidir

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

Sonra test etmek için:

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

Bu, müşteriye veri aktardığınız her durumda (örneğin, sunucu tarafı depolaması olmayan oturumlar için şifreli çerezler, şifreli URL parametreleri vb.), Son kullanıcının şifresini çözemeyeceği veya güvenilir şekilde kurcalayamayacağı konusunda oldukça yüksek bir kesinlik derecesiyle kullanılabilir. Bununla birlikte.

libsodium platformlar arası olduğu için, bu da örneğin PHP ile iletişim kurmayı kolaylaştırır; Java uygulamaları veya yerel mobil uygulamalar.


Not: Özellikle uygulamanıza libsodium destekli şifreli çerezler eklemeniz gerekiyorsa, işverenim Paragon Girişimci İşletmeleriHalite adlı bir kütüphane geliştiriyor.

68

Bilgi için MCRYPT_MODE_ECB IV kullanmaz (ilklendirme vektörü). ECB modu mesajınızı bloklara böler ve her blok ayrı ayrı şifrelenir. Ben gerçekten önerilmez.

CBC modu IV'ü her mesajı benzersiz yapmak için kullanır. CBC önerilir ve ECB yerine kullanılmalıdır.

Örnek :

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

Her iletinin kodunu çözmek için IV'ü stoklamanız gerekir (IV, değil secret). Her mesaj benzersizdir çünkü her mesajın kendine özgü bir IV vardır.

25
Fabien Sa

15 kod satırında çözülebilir bir şey için ağır bir bağımlılık kullanmak istemiyorsanız kullanıyorsanız, yerleşik OpenSSL işlevlerini kullanın. Çoğu PHP kurulum PHP'de hızlı, uyumlu ve güvenli AES şifreleme sağlayan OpenSSL ile birlikte gelir. En iyi uygulamaları takip ettiğiniz sürece güvenlidir.

Aşağıdaki kod:

  • cBC modunda AES256'yı kullanıyor
  • diğer AES uygulamalarıyla uyumludur, ancak mcrypt değil, çünkü mcrypt PKCS # 7 yerine PKCS # 5 kullanır.
  • sHA256'yı kullanarak sağlanan şifreden bir anahtar oluşturur
  • bütünlük kontrolü için şifrelenmiş verinin hmac karmasını üretir
  • her mesaj için rastgele IV üretir
  • iV (16 bayt) ve karma (32 bayt) şifreli metin için hazırlar.
  • oldukça güvenli olmalı

IV, halka açık bir bilgidir ve her mesaj için rastgele olması gerekir. Karma, verilerin değiştirilmemesini sağlar.

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

Kullanımı:

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

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

AES şifrelemesinde dikkat edilmesi gereken birkaç önemli şey: 

  1. Asla şifreleme anahtarı olarak düz metin kullanmayın. Her zaman düz metin anahtarını kullanın ve ardından şifreleme için kullanın. 
  2. Şifreleme ve şifre çözme için her zaman Rastgele IV'ü (başlangıç ​​vektörü) kullanın. Gerçek randomizasyon önemlidir. 
  3. Yukarıda belirtildiği gibi ecb modunu kullanmayın, bunun yerine CBC öğesini kullanın.
2
Navneet Kumar

Bu, openssl kullanılarak uygulanan AES encryption - uygulamasının çalışan bir çözümüdür. Şifreleme Blok Zincirleme Modunu (CBC Modu) kullanır. Böylece, data ve key ile birlikte iv ve block size olarak belirleyebilirsiniz

 <?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!');
                }
            }

        }

Örnek kullanım:

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

MCRYPT_RIJNDAEL_128 kullanıyorsanız, rtrim($output, "\0\3") işlevini deneyin. Dize uzunluğu 16'dan küçükse, şifre çözme işlevi, sonuna 03 ekleyerek, 16 karakter uzunluğunda bir dize döndürür.

Bunu kolayca kontrol edebilirsiniz, örn. deneyerek:

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

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

CCAVenue Payment Gateway için bir şey kodu kullanıyorum

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

}

kod kullanıcısı

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

PHP> = 7.2 kullanıyorsanız, şifreleme için dahili sodyum çekirdek uzantısı kullanmayı düşünün. 

Daha fazla bilgi burada bulabilirsiniz - http://php.net/manual/en/intro.sodium.php.

0
M_R_K