Nasıl bir PHP String şifrelemek ve şifresini çözmek?


225

Demek istediğim ... dir:

Original String + Salt or Key --> Encrypted String
Encrypted String + Salt or Key --> Decrypted (Original String)

Belki şöyle bir şey:

"hello world!" + "ABCD1234" --> Encrypt --> "2a2ffa8f13220befbe30819047e23b2c" (may be, for e.g)
"2a2ffa8f13220befbe30819047e23b2c" --> Decrypt with "ABCD1234" --> "hello world!"
  • PHP'de bunu nasıl yapabilirsiniz?

Kullanmaya çalıştı Crypt_Blowfish, ama benim için işe yaramadı.


35
@Rogue Karma istemiyor, simetrik şifreleme istiyor (AES gibi), ne dediğini bilmiyor. (Ve şimdi yapıyor :))
Patashu

ne kadar güvenli olması gerekir?

3
@ 夏 期 劇場, Simetrik şifrelemeyi 'tuzlamayın', bir anahtar kullanın. Bir anahtar gizli tutulmalıdır. Tuz, güvenliğe zarar vermeden herkese açık olabilir (herkesin tuzu farklı olduğu sürece) ve şifrelerin karıştırılmasında kullanılan bir terimdir.
Patashu

2
Tuz (özel anahtar), genel anahtar veya AES-256 gibi bir şifreleme algoritması gerekir: wpy.me/blog/15-encrypt-and-decrypt-data-in-php-using-aes-256
wappy

8
@CristianFlorea Bu blog gönderisinin yazarı simetrik şifreleme bağlamında en ufak bir anlam ifade etmeyen terimler kullanır. AES ile ortak anahtar veya tuz yoktur. Tek bir anahtar var; gizli tutulmalıdır. Bazı çalışma modlarında gizli olması gerekmeyen bir IV vardır, ancak bir IV tuz değildir (moda bağlı olarak, oldukça farklı gereksinimlere sahip olabilir) ve gizli olması gerekmez, ancak gerçek şifreleme anahtarı kesinlikle herkese açık olamaz. Ortak / özel anahtar asimetrik kripto için geçerlidir, ancak AES ile ilgisi yoktur.
cpast

Yanıtlar:


411

Başka bir şey yapmadan önce, şifreleme ve kimlik doğrulama arasındaki farkı ve neden sadece şifreleme yerine kimlik doğrulamalı şifreleme istediğinizi anlamaya çalışın .

Kimliği doğrulanmış şifreleme uygulamak için Önce Şifreleme sonra MAC. Şifreleme ve kimlik doğrulama sırası çok önemlidir! Bu sorunun mevcut cevaplarından biri bu hatayı yaptı; PHP'de yazılmış birçok şifreleme kütüphanesi gibi.

Sen gerektiğini Kendi şifrelemesini uygulamak önlemek ve bunun yerine güvenli bir kütüphane tarafından yazılan ve şifreleme uzmanları tarafından gözden kullanın.

Güncelleme: PHP 7.2 şimdi libsodium sağlıyor ! En iyi güvenlik için sistemlerinizi PHP 7.2 veya üstünü kullanacak şekilde güncelleyin ve yalnızca bu cevaptaki libsodium tavsiyelerine uyun.

PECL erişiminiz varsa libsodium kullanın (veya PECL'siz libsodium istiyorsanız sodyum_compat); aksi takdirde...
defuse / php-şifreleme kullanın ; kendi kriptografinizi atmayın!

Yukarıda bağlantılı her iki kütüphane de kendi kütüphanelerinize doğrulanmış şifreleme uygulamasını kolaylaştırır ve ağrısız hale getirir.

İnternetteki her şifreleme uzmanının geleneksel bilgeliğine karşı kendi şifreleme kitaplığınızı hala yazmak ve dağıtmak istiyorsanız, yapmanız gereken adımlar bunlar.

Şifreleme:

  1. TO modunda AES kullanarak şifreleyin. GCM'yi de kullanabilirsiniz (ayrı bir MAC ihtiyacını ortadan kaldırır). Ayrıca, ChaCha20 ve Salsa20 (tarafından sağlanan sağlanır ) akış şifreleridir ve özel modlara ihtiyaç duymazlar.
  2. Yukarıdaki GCM'yi seçmedikçe, şifreleme metnini HMAC-SHA-256 ile doğrulamanız gerekir (veya akış şifreleri için Poly1305 - çoğu libsodium API'si bunu sizin için yapar). MAC, IV ve şifreli metni kapsamalıdır!

Şifre çözme:

  1. Poly1305 veya GCM kullanılmadıkça, şifre metninin MAC'ini yeniden hesaplayın ve kullanarak gönderilen MAC ile karşılaştırın hash_equals() . Başarısız olursa, iptal edin.
  2. Mesajın şifresini çözün.

Diğer Tasarım Konuları:

  1. Hiçbir şeyi sıkıştırmayın. Şifre metni sıkıştırılamaz; şifrelemeden önce düz metnin sıkıştırılması bilgi sızıntılarına neden olabilir (örneğin TLS'de CRIME ve BREACH).
  2. Emin kullanmak olun mb_strlen()ve mb_substr()kullanmadan, '8bit'önlemek için karakter seti modu mbstring.func_overloadsorunları.
  3. IV'ler bir CSPRNG kullanarak oluşturulmalıdır ; Kullanıyorsanız mcrypt_create_iv(), KULLANMAYINMCRYPT_RAND !
  4. Bir AEAD yapısı kullanmadığınız sürece, DAİMA şifreleyin ve ardından MAC!
  5. bin2hex(), base64_encode()vb. şifreleme anahtarlarınız hakkında önbellek zamanlaması yoluyla bilgi sızdırabilir. Mümkünse bunlardan kaçının.

Burada verilen tavsiyelere uysanız bile, kriptografi ile çok şey ters gidebilir. Her zaman bir kriptografi uzmanının uygulamanızı gözden geçirmesini sağlayın. Yerel üniversitenizdeki bir şifreleme öğrencisi ile kişisel arkadaş olacak kadar şanslı değilseniz, her zaman Şifreleme Yığın Değişimi'ni deneyebilirsiniz tavsiye için forumunu .

Uygulamanızın profesyonel bir analizine ihtiyacınız varsa , PHP şifreleme kodunuzu gözden geçirmek için her zaman saygın bir güvenlik danışmanları ekibi kiralayabilirsiniz. (açıklama: işverenim).

Önemli: Şifreleme Ne Zaman Kullanılmamalıdır

Yapma şifrelemek şifreleri . Bununyerine, şu parola karma algoritmalarından birini kullanarak karma yapmak istiyorsunuz:

Parola depolamak için asla genel amaçlı bir karma işlevi (MD5, SHA256) kullanmayın.

URL Parametrelerini şifrelemeyin . Bu iş için yanlış araç.

Libsodium ile PHP String Şifreleme Örneği

PHP <7.2 kullanıyorsanız veya başka bir şekilde libsodium kurulu değilse , aynı sonucu elde etmek için sodyum_compat komutunu kullanabilirsiniz (daha yavaş da olsa).

<?php
declare(strict_types=1);

/**
 * Encrypt a message
 * 
 * @param string $message - message to encrypt
 * @param string $key - encryption key
 * @return string
 * @throws RangeException
 */
function safeEncrypt(string $message, string $key): string
{
    if (mb_strlen($key, '8bit') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
        throw new RangeException('Key is not the correct size (must be 32 bytes).');
    }
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);

    $cipher = base64_encode(
        $nonce.
        sodium_crypto_secretbox(
            $message,
            $nonce,
            $key
        )
    );
    sodium_memzero($message);
    sodium_memzero($key);
    return $cipher;
}

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

    $plain = sodium_crypto_secretbox_open(
        $ciphertext,
        $nonce,
        $key
    );
    if (!is_string($plain)) {
        throw new Exception('Invalid MAC');
    }
    sodium_memzero($ciphertext);
    sodium_memzero($key);
    return $plain;
}

Sonra test etmek için:

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

// Do this once then store it somehow:
$key = random_bytes(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);

Halite - Libsodium Daha Kolay

Ben üzerinde çalıştığım projelerden biri olarak adlandırılan bir şifreleme kütüphanesidir Halit kolay ve daha sezgisel libsodium yapmak amaçları.

<?php
use \ParagonIE\Halite\KeyFactory;
use \ParagonIE\Halite\Symmetric\Crypto as SymmetricCrypto;

// Generate a new random symmetric-key encryption key. You're going to want to store this:
$key = new KeyFactory::generateEncryptionKey();
// To save your encryption key:
KeyFactory::save($key, '/path/to/secret.key');
// To load it again:
$loadedkey = KeyFactory::loadEncryptionKey('/path/to/secret.key');

$message = 'We are all living in a yellow submarine';
$ciphertext = SymmetricCrypto::encrypt($message, $key);
$plaintext = SymmetricCrypto::decrypt($ciphertext, $key);

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

Temeldeki kriptografinin tamamı libsodyum tarafından ele alınır.

Defuse / php-şifreleme örneği

<?php
/**
 * This requires https://github.com/defuse/php-encryption
 * php composer.phar require defuse/php-encryption
 */

use Defuse\Crypto\Crypto;
use Defuse\Crypto\Key;

require "vendor/autoload.php";

// Do this once then store it somehow:
$key = Key::createNewRandomKey();

$message = 'We are all living in a yellow submarine';

$ciphertext = Crypto::encrypt($message, $key);
$plaintext = Crypto::decrypt($ciphertext, $key);

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

Not : Crypto::encrypt()onaltılık kodlamalı çıktıyı döndürür.

Şifreleme Anahtarı Yönetimi

Eğer bir "şifre" kullanmak istiyorsanız, hemen durun. Unutulmaz 128-bit şifreleme anahtarına ihtiyacınız var, unutulmaz bir şifre değil.

Bir şifreleme anahtarını aşağıdaki gibi uzun süreli kullanım için saklayabilirsiniz:

$storeMe = bin2hex($key);

Ve talep üzerine, şu şekilde alabilirsiniz:

$key = hex2bin($storeMe);

Ben kuvvetle sadece uzun süreli kullanım için rastgele oluşturulmuş anahtarı yerine anahtar olarak şifre her türlü depolamak önerilir (veya anahtarı türetmek).

Defuse kütüphanesini kullanıyorsanız:

"Ama ben gerçekten bir şifre kullanmak istiyorum."

Bu kötü bir fikir, ama tamam, bunu nasıl güvenli bir şekilde yapacağınız.

İlk olarak, rastgele bir anahtar oluşturun ve sabit bir yerde saklayın.

/**
 * Replace this with your own salt! 
 * Use bin2hex() then add \x before every 2 hex characters, like so:
 */
define('MY_PBKDF2_SALT', "\x2d\xb7\x68\x1a\x28\x15\xbe\x06\x33\xa0\x7e\x0e\x8f\x79\xd5\xdf");

Ekstra iş eklediğinizi ve bu sabiti anahtar olarak kullanabileceğinizi ve kendinizi çok fazla acı çekebileceğini unutmayın!

Ardından, doğrudan şifrenizle şifrelemek yerine şifrenizden uygun bir şifreleme anahtarı elde etmek için PBKDF2'yi (böyle) kullanın.

/**
 * Get an AES key from a static password and a secret salt
 * 
 * @param string $password Your weak password here
 * @param int $keysize Number of bytes in encryption key
 */
function getKeyFromPassword($password, $keysize = 16)
{
    return hash_pbkdf2(
        'sha256',
        $password,
        MY_PBKDF2_SALT,
        100000, // Number of iterations
        $keysize,
        true
    );
}

Sadece 16 karakterli bir şifre kullanmayın. Şifreleme anahtarınız komik bir şekilde bozulacaktır.


3
Şifreleri şifrelemeyin , birleştirmeyin password_hash()ve kontrol edin password_verify().
Scott Arciszewski

2
"Hiçbir şeyi sıkıştırmayın." HTTP, spdy ve diğer protokollerin yaptığı gibi mi demek istediniz? TLS'den önce? Absolutist tavsiye çok mu?
Tiberiu-Ionuț Stan

1
@ScottArciszewski Anahtar hakkındaki yorumunuzu beğendim "// Bunu bir kez yapın ve bir şekilde saklayın:" .. bir şekilde, lol :)) Peki bu 'anahtarı' (nesne olan) düz dize olarak, sabit kodlu olarak saklamaya ne dersiniz? Bir dize olarak, anahtarın kendisine ihtiyacım var. Bir şekilde bu nesneden alabilir miyim? Teşekkürler
Andrew

2
Teşekkürler, sodyum örneklerinizin çalışmasını sağlamak için sadece bir satırda değişiklik yapmak zorunda kaldım:function getKeyFromPassword($password, $keysize = \Sodium\CRYPTO_SECRETBOX_KEYBYTES)
Alexey Ozerov

1
Vaov! URL parametrelerini şifrelememekten bahsettiği için +1. Verdiğiniz makaleyi gerçekten beğendim: paragonie.com/blog/2015/09/…
Lynnell Emmanuel Neri

73

Partiye geç kaldım, ancak bunu yapmanın doğru yolunu arayan bu sayfaya rastladım, Google aramasının en iyi sonuçlarından biri oldu, bu yüzden sorunla ilgili görüşümü paylaşmak istiyorum. bu yazının yazıldığı tarihe kadar (2017 başı). PHP 7.1.0'dan itibaren mcrypt_decryptve mcrypt_encryptkullanımdan kaldırılacaktır, bu nedenle gelecekteki kanıt kodunu oluşturmak openssl_encrypt ve openssl_decrypt kullanmalıdır

Gibi bir şey yapabilirsiniz:

$string_to_encrypt="Test";
$password="password";
$encrypted_string=openssl_encrypt($string_to_encrypt,"AES-128-ECB",$password);
$decrypted_string=openssl_decrypt($encrypted_string,"AES-128-ECB",$password);

Önemli : Güvenli olmayan ECB modunu kullanır . Kriptografi mühendisliğinde çarpışma kursu almadan basit bir çözüm istiyorsanız, kendiniz yazmayın, sadece bir kütüphane kullanın.

Güvenlik gereksiniminize bağlı olarak diğer yongalama yöntemlerini de kullanabilirsiniz. Mevcut parçalayıcı yöntemlerini bulmak için lütfen openssl_get_cipher_methods işlevine bakın.


10
Teşekkür ederim, bu basit ve net cevabın daha fazla onaylanmamasına şaşırdım. İstediğim tek şey basit bir dize şifrelemek / şifresini çözmek olduğunda üst cevap gibi konuda 10 sayfalık bir tartışma okumak istemem.
laurent

4
Bu güvenli bir cevap değil. ECB modu kullanılmamalıdır. "Basit ve açık bir cevap" istiyorsanız, bir kütüphane kullanın .
Scott Arciszewski

2
@ScottArciszewski, evet bazı basit kod ararken çok hızlı konuştuğumu itiraf ediyorum. O zamandan beri bir IV ekledim ve kendi kodumda CBC kullanıyorum, bu da benim kullanımım için yeterince iyi.
laurent

Bunu okuyun ve yeniden düşünün . CBC modunda, bir saldırgan mesajı tamamen değiştirebilir. İleti bir dosyaysa, saldırgan bitleri ve pop calc.exe'yi çevirebilir. Kimliği doğrulanmamış şifreleme riskleri ağırdır.
Scott Arciszewski

7
Her şey kullanım durumuna bağlıdır! Bunun tamamen GÜZEL olduğu durumlar vardır. Örneğin, bir GET parametresini sayfadan sayfaya geçirmek istiyorum, diyelim prod_id=123ama 123'ü herkes için okunabilir yapmak istemiyorum, ancak okuyabilseler bile sorun olmayacak. Saldırganın 123'ü özel bir değere değiştirebilmesi zarar vermez, yalnızca başka bir ürünün ayrıntılarını alabilir, ancak Joe Ortalama Kullanıcısı için ayrıntıları nasıl alacağına dair bir ipucu olmaz örneğin 124. Bunun gibi bir senaryo için mükemmel bir çözümdür, güvenlik için hiç sorun değil!
Emil Borconi

43

Ne yapmamalı

UYARI:
Bu cevap ECB kullanır . ECB bir şifreleme modu değil, sadece bir yapı taşıdır. ECB'nin bu cevapta gösterildiği gibi kullanılması, dizeyi güvenli bir şekilde şifrelemez. Kodunuzda ECB kullanmayın. İyi bir çözüm için Scott'ın cevabına bakınız .

Kendime aldım. Aslında Google'da bazı cevaplar buldum ve sadece bir şey değiştirdim. Ancak sonuç tamamen güvensizdir.

<?php
define("ENCRYPTION_KEY", "!@#$%^&*");
$string = "This is the original data string!";

echo $encrypted = encrypt($string, ENCRYPTION_KEY);
echo "<br />";
echo $decrypted = decrypt($encrypted, ENCRYPTION_KEY);

/**
 * Returns an encrypted & utf8-encoded
 */
function encrypt($pure_string, $encryption_key) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
    return $encrypted_string;
}

/**
 * Returns decrypted original string
 */
function decrypt($encrypted_string, $encryption_key) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $encryption_key, $encrypted_string, MCRYPT_MODE_ECB, $iv);
    return $decrypted_string;
}
?>

8
Daha fazla güvenlik sağlamak için "MCRYPT_MODE_ECB" yerine "MCRYPT_MODE_CBC" kullanıcısını kullanabilirsiniz.
Parixit

10
Ramesh, bunun nedeni ham şifrelenmiş verileri almanızdır. Aşağıdaki gibi base64 kullanarak şifrelenmiş verilerin daha güzel bir sürümünü alabilirsiniz: base64_encode(encrypt($string))- Şifresini çözmek için:decrypt(base64_decode($encrypted))
mendezcode 31:14

82
UYARI: bu güvensizdir . ECB modu, ECB yerine AES bir eski şifre (Blowfish) kullanan, bu doğrulanmış değil, damar yolu almaz dizeleri kullanılmamalıdır, anahtar vb vb ikili değil SO topluluk gerçekten durdurma şifreleme upvoting gerekir / şifre çözme sadece "çalışır" ve güvenli olduğu bilinen cevapları oylamaya başlar. Eğer kesin olarak bilmiyorsanız, oy vermeyin.
Maarten Bodewes

3
Bu tür bir örnek kod mcrypt_encryptdeğiştirerek zaten yaptım : php.net/manual/en/function.mcrypt-encrypt.php . Şimdi gözden geçirmenin sonunda bir rtrimfor karakteri olması gerektiğini unutmayın "\0".
Maarten Bodewes

4
Doğru cevap, kendi mcrypt kodunuzu yazmak yerine defuse / php-şifreleme gibi bir şey kullanmaktır .
Scott Arciszewski

18

Laravel çerçevesi için

Laravel çerçevesini kullanıyorsanız, dahili işlevlerle şifrelemek ve şifresini çözmek daha kolaydır.

$string = 'Some text to be encrypted';
$encrypted = \Illuminate\Support\Facades\Crypt::encrypt($string);
$decrypted_string = \Illuminate\Support\Facades\Crypt::decrypt($encrypted);

var_dump($string);
var_dump($encrypted);
var_dump($decrypted_string);

Not: config / app.php dosyasının anahtar seçeneğinde 16, 24 veya 32 karakterlik rastgele bir dize ayarladığınızdan emin olun. Aksi takdirde, şifrelenmiş değerler güvenli olmaz.


1
Elbette, kullanımı kolay olabilir. Ama güvenli mi? Stackoverflow.com/a/30159120/781723'teki sorunları nasıl çözer ? Kimliği doğrulanmış şifreleme kullanıyor mu? Yan kanal güvenlik açıklarından kaçınıyor mu ve sabit zamanlı eşitlik kontrolleri sağlıyor mu? Parola / parola yerine gerçekten rastgele bir anahtar kullanıyor mu? Uygun bir çalışma şekli kullanıyor mu? Rastgele IV'leri düzgün bir şekilde üretir mi?
DW

10

Güncellenmiş

PHP 7 hazır sürümü. PHP OpenSSL Library'den openssl_encrypt fonksiyonunu kullanır .

class Openssl_EncryptDecrypt {
    function encrypt ($pure_string, $encryption_key) {
        $cipher     = 'AES-256-CBC';
        $options    = OPENSSL_RAW_DATA;
        $hash_algo  = 'sha256';
        $sha2len    = 32;
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);
        $ciphertext_raw = openssl_encrypt($pure_string, $cipher, $encryption_key, $options, $iv);
        $hmac = hash_hmac($hash_algo, $ciphertext_raw, $encryption_key, true);
        return $iv.$hmac.$ciphertext_raw;
    }
    function decrypt ($encrypted_string, $encryption_key) {
        $cipher     = 'AES-256-CBC';
        $options    = OPENSSL_RAW_DATA;
        $hash_algo  = 'sha256';
        $sha2len    = 32;
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = substr($encrypted_string, 0, $ivlen);
        $hmac = substr($encrypted_string, $ivlen, $sha2len);
        $ciphertext_raw = substr($encrypted_string, $ivlen+$sha2len);
        $original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $encryption_key, $options, $iv);
        $calcmac = hash_hmac($hash_algo, $ciphertext_raw, $encryption_key, true);
        if(function_exists('hash_equals')) {
            if (hash_equals($hmac, $calcmac)) return $original_plaintext;
        } else {
            if ($this->hash_equals_custom($hmac, $calcmac)) return $original_plaintext;
        }
    }
    /**
     * (Optional)
     * hash_equals() function polyfilling.
     * PHP 5.6+ timing attack safe comparison
     */
    function hash_equals_custom($knownString, $userString) {
        if (function_exists('mb_strlen')) {
            $kLen = mb_strlen($knownString, '8bit');
            $uLen = mb_strlen($userString, '8bit');
        } else {
            $kLen = strlen($knownString);
            $uLen = strlen($userString);
        }
        if ($kLen !== $uLen) {
            return false;
        }
        $result = 0;
        for ($i = 0; $i < $kLen; $i++) {
            $result |= (ord($knownString[$i]) ^ ord($userString[$i]));
        }
        return 0 === $result;
    }
}

define('ENCRYPTION_KEY', '__^%&Q@$&*!@#$%^&*^__');
$string = "This is the original string!";

$OpensslEncryption = new Openssl_EncryptDecrypt;
$encrypted = $OpensslEncryption->encrypt($string, ENCRYPTION_KEY);
$decrypted = $OpensslEncryption->decrypt($encrypted, ENCRYPTION_KEY);

1
Bu daha iyi ve daha güvenli bir versiyonudur. Teşekkürler, beklendiği gibi çalışıyor.

1
şifreleme anahtarını nasıl oluşturuyorsunuz ve nerede tutuyorsunuz?
user2800464

7

Tarihsel Not: Bu PHP4 zamanında yazılmıştır. Şimdi buna "eski kod" diyoruz.

Bu yanıtı tarihi amaçlar için bıraktım - ancak bazı yöntemler artık kullanımdan kaldırıldı, DES şifreleme yöntemi önerilen bir uygulama değil.

Bu kodu iki nedenden dolayı güncellemedim: 1) Artık PHP'de elle şifreleme yöntemleri ile çalışmıyorum ve 2) bu kod hala amaçlandığı amaca hizmet ediyor: şifrelemenin nasıl çalışabileceğine dair minimum, basit konsepti göstermek PHP.

Benzer şekilde basit bir "10 mm kod satırında veya daha az satırda insanları başlatabilen" aptallar için PHP şifrelemesi "türünde bir kaynak bulursanız, yorumlarda bana bildirin.

Bunun ötesinde, erken dönem PHP4 minimalist şifreleme cevabının bu Klasik Bölüm tadını çıkarın.


İdeal olarak, kesinlikle popüler ve çok çeşitli görevler olduğu için mcrypt PHP kütüphanesine erişebilirsiniz - veya alabilirsiniz. İşte farklı şifreleme türlerinin ve bazı örnek kodların tükenmesi: PHP'de Şifreleme Teknikleri

//Listing 3: Encrypting Data Using the mcrypt_ecb Function 

<?php 
echo("<h3> Symmetric Encryption </h3>"); 
$key_value = "KEYVALUE"; 
$plain_text = "PLAINTEXT"; 
$encrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $plain_text, MCRYPT_ENCRYPT); 
echo ("<p><b> Text after encryption : </b>"); 
echo ( $encrypted_text ); 
$decrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $encrypted_text, MCRYPT_DECRYPT); 
echo ("<p><b> Text after decryption : </b>"); 
echo ( $decrypted_text ); 
?> 

Birkaç uyarı:

1) Tek yönlü karma yapıldığında asla tersinir veya "simetrik" şifreleme kullanmayın.

2) Veriler, kredi kartı veya sosyal güvenlik numaraları gibi gerçekten hassassa, durun; herhangi bir basit kod yığınından daha fazlasına ihtiyacınız vardır, ancak bunun yerine bu amaç için tasarlanmış bir kripto kütüphanesine ve gerekli yöntemleri araştırmak için önemli bir süreye ihtiyacınız vardır. Ayrıca, yazılım kripto hassas verilerin güvenliğinin muhtemelen <% 10'udur. Bu bir nükleer güç santralini yeniden kablolamak gibi - görevin tehlikeli ve zor olduğunu ve bu durumda bilginizin ötesinde olduğunu kabul edin. Mali cezalar muazzam olabilir, bu nedenle bir hizmet kullanmak ve onlara sorumluluk göndermek daha iyidir.

3) Burada listelendiği gibi kolayca uygulanabilen her türlü şifreleme, meraklı gözlerden korumak istediğiniz hafif önemli bilgileri makul bir şekilde koruyabilir veya kazara / kasıtlı sızıntı durumunda maruz kalmayı sınırlayabilir. Ancak, anahtarın web sunucusunda düz metinde nasıl saklandığını görünce, verileri alabilirlerse şifre çözme anahtarını alabilirler.

Olabilir, eğlenin :)


9
Eww, DES. AES nerede?
Patashu

2
Teşekkürler! Ama bazı konular. M�������f=�_=Şifreli karakter olarak garip karakterler alıyorum . Basit karakterler alamıyor muyum? Gibi: 2a2ffa8f13220befbe30819047e23b2c. Ayrıca, $key_value(8 sabit ???) LENGTH ve çıkış LENGTH değiştiremez $encrypted_textmiyim? (32 veya 64 uzun olamaz ya da daha uzun olamaz ??)
夏 期 劇場

3
@ 夏 期 劇場 Şifrelemenin sonucu ikili verilerdir. İnsan tarafından okunabilir olması gerekiyorsa, üzerinde base64 veya hex kodlama kullanın. 'Anahtar değerinin uzunluğunu değiştiremez miyim?' Farklı simetrik şifreleme algoritmalarının anahtar değeri için farklı gereksinimleri vardır. 've çıkışın UZUNLUĞU ...' Şifreli metnin uzunluğu en az orijinal metin kadar uzun olmalıdır, aksi takdirde orijinal metni yeniden oluşturmak için yeterli bilgi yoktur. (Bu Pigeonhole prensibinin bir uygulamasıdır.) BTW, DES yerine AES kullanmalısınız. DES kolayca kırılabilir ve artık güvenli değildir.
Patashu

8
mcrypt_ecb PHP 5.5.0'dan beri DEPRECATED. Bu işleve güvenmek son derece önerilmez. php.net/manual/tr/function.mcrypt-ecb.php
Hafez Divandari

1
@BrianDHall Bunun hala aşağı oy almasının nedeni, ECB modunun güvenli olmaması (CBC, CTR, GCM veya Poly1305 kullanın), DES zayıftır (AES'i istiyorsunuz MCRYPT_RIJNDAEL_128) ve şifrelerin doğrulanması ( hash_hmac()doğrulanmış olması) ile hash_equals()).
Scott Arciszewski

7

Kütüphaneyi (istemeniz gereken) kullanmak istemiyorsanız, böyle bir şey kullanın (PHP 7):

function sign($message, $key) {
    return hash_hmac('sha256', $message, $key) . $message;
}

function verify($bundle, $key) {
    return hash_equals(
      hash_hmac('sha256', mb_substr($bundle, 64, null, '8bit'), $key),
      mb_substr($bundle, 0, 64, '8bit')
    );
}

function getKey($password, $keysize = 16) {
    return hash_pbkdf2('sha256',$password,'some_token',100000,$keysize,true);
}

function encrypt($message, $password) {
    $iv = random_bytes(16);
    $key = getKey($password);
    $result = sign(openssl_encrypt($message,'aes-256-ctr',$key,OPENSSL_RAW_DATA,$iv), $key);
    return bin2hex($iv).bin2hex($result);
}

function decrypt($hash, $password) {
    $iv = hex2bin(substr($hash, 0, 32));
    $data = hex2bin(substr($hash, 32));
    $key = getKey($password);
    if (!verify($data, $key)) {
      return null;
    }
    return openssl_decrypt(mb_substr($data, 64, null, '8bit'),'aes-256-ctr',$key,OPENSSL_RAW_DATA,$iv);
}

$string_to_encrypt='John Smith';
$password='password';
$encrypted_string=encrypt($string_to_encrypt, $password);
$decrypted_string=decrypt($encrypted_string, $password);

Bu stackoverflow.com/a/16606352/126833 yerine kullanılabilir mi? Benim ev sahibi PHP 7.2 yükseltene kadar eski kullanıyorum.
anjanesh

@anjanesh bununla eski verilerin şifresini çözemezsiniz (farklı algoritmalar + bu da imzayı kontrol eder)
Ascon

2
Sizin durumunuzda bu muhtemelen:define("ENCRYPTION_KEY", "123456*"); $string = "This is the original data string!"; $encrypted = openssl_encrypt($string, 'BF-ECB', ENCRYPTION_KEY); $decrypted = openssl_decrypt($encrypted,'BF-ECB',ENCRYPTION_KEY);
Ascon

Bu Süper!
anjanesh

2

Bunlar AES256 CBC kullanarak PHP ile dizeleri şifrelemek / şifresini çözmek için kompakt yöntemlerdir :

function encryptString($plaintext, $password, $encoding = null) {
    $iv = openssl_random_pseudo_bytes(16);
    $ciphertext = openssl_encrypt($plaintext, "AES-256-CBC", hash('sha256', $password, true), OPENSSL_RAW_DATA, $iv);
    $hmac = hash_hmac('sha256', $ciphertext.$iv, hash('sha256', $password, true), true);
    return $encoding == "hex" ? bin2hex($iv.$hmac.$ciphertext) : ($encoding == "base64" ? base64_encode($iv.$hmac.$ciphertext) : $iv.$hmac.$ciphertext);
}

function decryptString($ciphertext, $password, $encoding = null) {
    $ciphertext = $encoding == "hex" ? hex2bin($ciphertext) : ($encoding == "base64" ? base64_decode($ciphertext) : $ciphertext);
    if (!hash_equals(hash_hmac('sha256', substr($ciphertext, 48).substr($ciphertext, 0, 16), hash('sha256', $password, true), true), substr($ciphertext, 16, 32))) return null;
    return openssl_decrypt(substr($ciphertext, 48), "AES-256-CBC", hash('sha256', $password, true), OPENSSL_RAW_DATA, substr($ciphertext, 0, 16));
}

Kullanımı:

$enc = encryptString("mysecretText", "myPassword");
$dec = decryptString($enc, "myPassword");

0

Özel karakter ile tüm dize için php altında kod çalışması

   // Encrypt text --

    $token = "9611222007552";

      $cipher_method = 'aes-128-ctr';
      $enc_key = openssl_digest(php_uname(), 'SHA256', TRUE);  
      $enc_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher_method));  
      $crypted_token = openssl_encrypt($token, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv);
    echo    $crypted_token;
    //unset($token, $cipher_method, $enc_key, $enc_iv);

    // Decrypt text  -- 

    list($crypted_token, $enc_iv) = explode("::", $crypted_token);  
      $cipher_method = 'aes-128-ctr';
      $enc_key = openssl_digest(php_uname(), 'SHA256', TRUE);
      $token = openssl_decrypt($crypted_token, $cipher_method, $enc_key, 0, hex2bin($enc_iv));
    echo   $token;
    //unset($crypted_token, $cipher_method, $enc_key, $enc_iv);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.