mcrypt jest przestarzały, jaka jest alternatywa?

103

Rozszerzenie mcrypt jest przestarzałe i zostanie usunięte w PHP 7.2 zgodnie z komentarzem zamieszczonym tutaj . Dlatego szukam alternatywnego sposobu szyfrowania haseł.

W tej chwili używam czegoś takiego

mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key, true), $string, MCRYPT_MODE_CBC, $iv)

Potrzebuję Twojej opinii na temat najlepszego / najsilniejszego sposobu szyfrowania haseł, zaszyfrowane hasło powinno oczywiście być obsługiwane przez PHP 7.xx i powinno być również możliwe do odszyfrowania, ponieważ moi klienci chcą mieć opcję `` odzyskania '' swoich haseł bez generowania nowego jeden.

Piet
źródło
9
Dlaczego musisz szyfrować / odszyfrowywać hasła? Dlaczego po prostu ich nie haszować password_hashi nie weryfikować password_verify?
Don't Panic
3
„zaszyfrowane hasło powinno być również możliwe do odszyfrowania” - dlaczego? nie brzmi zbyt bezpiecznie. Jakiś szczególny powód?
Funk Forty Niner
24
„ponieważ moi klienci chcą mieć możliwość„ odzyskania ”swoich haseł bez generowania nowego”. - To nie jest bezpieczne i zamiast tego powinni mieć możliwość zresetowania swoich haseł.
Funk Forty Niner
4
Nie szyfruj haseł , gdy atakujący zdobędzie bazę danych, otrzyma również klucz szyfrujący. Wykonaj iterację w HMAC z losową solą przez około 100 ms i zachowaj sól z hashem. Użyj funkcji, takich jak hash_hash, PBKDF2, Bcrypt i podobne. Chodzi o to, aby atakujący spędzał dużo czasu na wyszukiwaniu haseł przy użyciu brutalnej siły.
zaph
2
Z podręcznika php -> Ta funkcja została WYCOFANA w PHP 7.1.0. Poleganie na tej funkcji jest wysoce odradzane. Alternatywą jest sód -> php.net/manual/en/book.sodium.php
MarcoZen

Odpowiedzi:

47

Najlepszą praktyką jest haszowanie haseł, aby nie można było ich odszyfrować. To sprawia, że ​​osoby atakujące, które mogły uzyskać dostęp do Twojej bazy danych lub plików, są nieco trudniejsze.

Jeśli musisz zaszyfrować swoje dane i umożliwić ich odszyfrowanie, przewodnik dotyczący bezpiecznego szyfrowania / deszyfrowania jest dostępny pod adresem https://paragonie.com/white-paper/2015-secure-php-data-encryption . Podsumowując ten link:

  • Użyj Libsodium - rozszerzenia PHP
  • Jeśli nie możesz użyć Libsodium, użyj defuse / php-encryption - Straight PHP code
  • Jeśli nie możesz użyć Libsodium lub defuse / php-encryption, użyj OpenSSL - wiele serwerów będzie już miało to zainstalowane. Jeśli nie, można go skompilować za pomocą --with-openssl [= DIR]
Phil
źródło
1
Powinienem najpierw wypróbować openssl, ponieważ jest bardzo powszechny, podczas gdy libsodium nie jest. Nie należy używać surowego php, chyba że wszystkie rozszerzenia natywne są wyłączone w razie wątpliwości
JSON
mimo że openssl jest bardzo powszechne, wygląda na to, że php 7 będzie używał libsodium do podstawowego kryptografii securityintelligence.com/news/ ...
shadi
1
Zauważ, że istnieje biblioteka o nazwie Sodium-compat( github.com/paragonie/sodium_compat ), która działa w PHP> = 5.2.4
RaelB
30

Jak sugeruje @rqLizard , możesz zamiast tego użyć funkcji openssl_encrypt/ openssl_decryptPHP, które zapewniają znacznie lepszą alternatywę dla implementacji AES (The Advanced Encryption Standard), znanego również jako szyfrowanie Rijndael.

Zgodnie z poniższym komentarzem Scotta na php.net :

Jeśli piszesz kod do szyfrowania / szyfrowania danych w 2015 roku, powinieneś użyć openssl_encrypt()i openssl_decrypt(). Podstawowa biblioteka ( libmcrypt) została porzucona od 2007 roku i działa znacznie gorzej niż OpenSSL (który wykorzystuje AES-NInowoczesne procesory i jest bezpieczny w czasie buforowania).

Nie MCRYPT_RIJNDAEL_256jest też AES-256, to inny wariant szyfru blokowego Rijndael. Jeśli chcesz AES-256w mcrypt, trzeba korzystać MCRYPT_RIJNDAEL_128z kluczem 32-bajtowy. OpenSSL sprawia, że ​​jest bardziej oczywiste, którego trybu używasz (tj. aes-128-cbcVs aes-256-ctr).

OpenSSL używa również wypełnienia PKCS7 w trybie CBC zamiast wypełniania bajtów NULL w mcrypt. W związku z tym mcrypt jest bardziej podatny na ataki typu padding oracle niż OpenSSL.

Wreszcie, jeśli nie uwierzytelniasz swoich zaszyfrowanych tekstów (Szyfruj następnie MAC), robisz to źle.

Dalsze czytanie:

Przykłady kodu

Przykład 1

Szyfrowanie uwierzytelnione AES w trybie GCM, przykład dla PHP 7.1+

<?php
//$key should have been previously generated in a cryptographically safe way, like openssl_random_pseudo_bytes
$plaintext = "message to be encrypted";
$cipher = "aes-128-gcm";
if (in_array($cipher, openssl_get_cipher_methods()))
{
    $ivlen = openssl_cipher_iv_length($cipher);
    $iv = openssl_random_pseudo_bytes($ivlen);
    $ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=0, $iv, $tag);
    //store $cipher, $iv, and $tag for decryption later
    $original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, $options=0, $iv, $tag);
    echo $original_plaintext."\n";
}
?>

Przykład nr 2

Przykład szyfrowania uwierzytelnionego AES dla PHP 5.6+

<?php
//$key previously generated safely, ie: openssl_random_pseudo_bytes
$plaintext = "message to be encrypted";
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );

//decrypt later....
$c = base64_decode($ciphertext);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
if (hash_equals($hmac, $calcmac))//PHP 5.6+ timing attack safe comparison
{
    echo $original_plaintext."\n";
}
?>

Przykład nr 3

W oparciu o powyższe przykłady zmieniłem następujący kod, który ma na celu zaszyfrowanie identyfikatora sesji użytkownika:

class Session {

  /**
   * Encrypts the session ID and returns it as a base 64 encoded string.
   *
   * @param $session_id
   * @return string
   */
  public function encrypt($session_id) {
    // Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    // For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    // Encrypt the session ID.
    $encrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $session_id, MCRYPT_MODE_CBC, $iv);
    // Base 64 encode the encrypted session ID.
    $encryptedSessionId = base64_encode($encrypt);
    // Return it.
    return $encryptedSessionId;
  }

  /**
   * Decrypts a base 64 encoded encrypted session ID back to its original form.
   *
   * @param $encryptedSessionId
   * @return string
   */
  public function decrypt($encryptedSessionId) {
    // Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    // For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    // Decode the encrypted session ID from base 64.
    $decoded = base64_decode($encryptedSessionId);
    // Decrypt the string.
    $decryptedSessionId = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $decoded, MCRYPT_MODE_CBC, $iv);
    // Trim the whitespace from the end.
    $session_id = rtrim($decryptedSessionId, "\0");
    // Return it.
    return $session_id;
  }

  public function _getIv() {
    return md5($this->_getSalt());
  }

  public function _getSalt() {
    return md5($this->drupal->drupalGetHashSalt());
  }

}

w:

class Session {

  const SESS_CIPHER = 'aes-128-cbc';

  /**
   * Encrypts the session ID and returns it as a base 64 encoded string.
   *
   * @param $session_id
   * @return string
   */
  public function encrypt($session_id) {
    // Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    // For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    // Encrypt the session ID.
    $ciphertext = openssl_encrypt($session_id, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
    // Base 64 encode the encrypted session ID.
    $encryptedSessionId = base64_encode($ciphertext);
    // Return it.
    return $encryptedSessionId;
  }

  /**
   * Decrypts a base 64 encoded encrypted session ID back to its original form.
   *
   * @param $encryptedSessionId
   * @return string
   */
  public function decrypt($encryptedSessionId) {
    // Get the Drupal hash salt as a key.
    $key = $this->_getSalt();
    // Get the iv.
    $iv = $this->_getIv();
    // Decode the encrypted session ID from base 64.
    $decoded = base64_decode($encryptedSessionId, TRUE);
    // Decrypt the string.
    $decryptedSessionId = openssl_decrypt($decoded, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
    // Trim the whitespace from the end.
    $session_id = rtrim($decryptedSessionId, '\0');
    // Return it.
    return $session_id;
  }

  public function _getIv() {
    $ivlen = openssl_cipher_iv_length(self::SESS_CIPHER);
    return substr(md5($this->_getSalt()), 0, $ivlen);
  }

  public function _getSalt() {
    return $this->drupal->drupalGetHashSalt();
  }

}

Aby wyjaśnić, powyższa zmiana nie jest prawdziwą konwersją, ponieważ te dwa szyfrowania wykorzystują inny rozmiar bloku i inne zaszyfrowane dane. Ponadto domyślne wypełnienie jest inne, MCRYPT_RIJNDAELobsługuje tylko niestandardowe wypełnienie zerowe. @zaph


Dodatkowe uwagi (z komentarzy @ zaph):

  • Rijndael 128 ( MCRYPT_RIJNDAEL_128) jest odpowiednikiem AES , jednak Rijndael 256 ( MCRYPT_RIJNDAEL_256) nie jest AES-256, ponieważ 256 określa rozmiar bloku 256-bitów, podczas gdy AES ma tylko jeden rozmiar bloku: 128-bitów. Zasadniczo więc Rijndael z blokiem o rozmiarze 256 bitów ( MCRYPT_RIJNDAEL_256) został błędnie nazwany z powodu wyborów dokonanych przez programistów mcrypt . @zaph
  • Rijndael z blokiem o rozmiarze 256 może być mniej bezpieczny niż z blokiem o rozmiarze 128-bitowym, ponieważ ten ostatni miał znacznie więcej recenzji i zastosowań. Po drugie, interoperacyjność jest utrudniona, ponieważ AES jest ogólnie dostępna, podczas gdy Rijndael z blokiem o rozmiarze 256 bitów nie.
  • Szyfrowanie z różnymi rozmiarami bloków dla Rijndael daje różne zaszyfrowane dane.

    Na przykład MCRYPT_RIJNDAEL_256(nie równoważne AES-256) definiuje inny wariant szyfru blokowego Rijndael o rozmiarze 256 bitów i rozmiarze klucza opartym na przekazanym kluczu, gdzie aes-256-cbcjest Rijndael o rozmiarze bloku 128-bitów i rozmiarze klucza 256-bitowe. Dlatego używają różnych rozmiarów bloków, które generują zupełnie inne zaszyfrowane dane, ponieważ mcrypt używa liczby do określenia rozmiaru bloku, gdzie OpenSSL użył liczby do określenia rozmiaru klucza (AES ma tylko jeden rozmiar bloku o długości 128 bitów). A więc w zasadzie AES to Rijndael z rozmiarem bloku 128-bitów i kluczami o rozmiarach 128, 192 i 256 bitów. Dlatego lepiej jest używać AES, który w OpenSSL nazywa się Rijndael 128.

kenorb
źródło
1
Ogólnie używanie Rijndaela z blokiem o rozmiarze 256 bitów jest błędem z powodu wyborów dokonanych przez programistów mcrypt. Ponadto Rijndael z blokiem o rozmiarze 256 może być mniej bezpieczny niż z blokiem o rozmiarze 128-bitowym, ponieważ ten ostatni miał znacznie więcej przeglądów i zastosowań. Dodatkowo interoperacyjność jest utrudniona przez to, że podczas gdy AES jest ogólnie dostępny, Rijndael z blokiem o rozmiarze 256 bitów nie jest.
zaph
Dlaczego $session_id = rtrim($decryptedSessionId, "\0");? Czy w końcu można openssl_decryptzwrócić jakieś niechciane postacie? Co się stanie, jeśli zaszyfrowana zmienna kończy się na 0 (tj. encrypt("abc0")?
hlscalon
@hiscalon "\0"to nie "0"tylko znak NULL, którego kod ASCII to 0x00 (szesnastkowo 0).
kiamlaluno
11

Implementacja Rijndael w czystym PHP istnieje z phpseclib dostępnym jako pakiet kompozytora i działa na PHP 7.3 (przetestowane przeze mnie).

W dokumentacji phpseclib znajduje się strona, która generuje przykładowy kod po wprowadzeniu podstawowych zmiennych (szyfr, tryb, rozmiar klucza, rozmiar w bitach). Wyprowadza następujące dane dla Rijndael, ECB, 256, 256:

kod z mycrypt

$decoded = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, ENCRYPT_KEY, $term, MCRYPT_MODE_ECB);

działa tak z biblioteką

$rijndael = new \phpseclib\Crypt\Rijndael(\phpseclib\Crypt\Rijndael::MODE_ECB);
$rijndael->setKey(ENCRYPT_KEY);
$rijndael->setKeyLength(256);
$rijndael->disablePadding();
$rijndael->setBlockLength(256);

$decoded = $rijndael->decrypt($term);

* $termbyłbase64_decoded

Pentium10
źródło
11

Zgodnie z innymi odpowiedziami tutaj, najlepszym rozwiązaniem, które znalazłem, jest użycie OpenSSL. Jest wbudowany w PHP i nie potrzebujesz żadnej zewnętrznej biblioteki. Oto proste przykłady:

Aby zaszyfrować:

function encrypt($key, $payload) {
  $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
  $encrypted = openssl_encrypt($payload, 'aes-256-cbc', $key, 0, $iv);
  return base64_encode($encrypted . '::' . $iv);
}

Aby odszyfrować:

function decrypt($key, $garble) {
    list($encrypted_data, $iv) = explode('::', base64_decode($garble), 2);
    return openssl_decrypt($encrypted_data, 'aes-256-cbc', $key, 0, $iv);
}

Link referencyjny: https://www.shift8web.ca/2017/04/how-to-encrypt-and-execute-your-php-code-with-mcrypt/

Ariston Cordeiro
źródło
Dużo dobrej karmy dla twojego przyjaciela! Tylko jedno: jeśli na przykład hasło zostało zaszyfrowane starym kodem, nowy kod odszyfrowywania nie będzie w stanie go zweryfikować. Należy go ponownie zapisać i zaszyfrować tym nowym kodem.
Lumis
Prosty skrypt migracji rozwiązałby ten problem. Użyj starego sposobu odszyfrowywania, a następnie nowego sposobu szyfrowania i przechowywania. Alternatywą jest dodanie flagi do tabeli użytkownika i skrypty w celu wymuszonego resetowania hasła na wszystkich kontach użytkowników, które wymagają zmiany hasła.
cecil merrel aka bringrainfire
8

Możesz użyć pakietu pollyfill phpseclib. Nie możesz użyć otwartego ssl lub libsodium do szyfrowania / deszyfrowania za pomocą rijndael 256. Kolejna kwestia, nie potrzebujesz zastępować żadnego kodu.

Ahmet Erkan ÇELİK
źródło
2
To było bardzo pomocne dzięki. Musiałem usunąć rozszerzenie php-mcrypt, a to działa jak urok.
DannyB
Zainstalowałem mcrypt_compatprzez uruchomienie, composer require phpseclib/mcrypt_compatale nadal PHP Fatal error: Uncaught Error: Call to undefined function mcrypt_get_key_size() in /app/kohana/classes/Kohana/Encrypt.php:124używam 7.2.26framwork php i Kohana. Czy trzeba wykonać więcej czynności po zainstalowaniu go w programie Composer?
M-Dahab,
Rozumiem. Musisz dodać require APPPATH . '/vendor/autoload.php';na dole bootstrap.php.
M-Dahab,
3

Powinieneś używać OpenSSL ponad, mcryptponieważ jest aktywnie rozwijany i utrzymywany. Zapewnia lepsze bezpieczeństwo, łatwość konserwacji i przenośność. Po drugie, znacznie szybciej wykonuje szyfrowanie / deszyfrowanie AES. Domyślnie używa dopełnienia PKCS7, ale możesz określić, OPENSSL_ZERO_PADDINGczy jest to potrzebne. Aby użyć 32-bajtowego klucza binarnego, możesz określić, aes-256-cbcktóry jest bardziej oczywisty niż MCRYPT_RIJNDAEL_128.

Oto przykład kodu wykorzystujący Mcrypt:

Nieuwierzytelniona biblioteka szyfrowania AES-256-CBC napisana w Mcrypt z dopełnieniem PKCS7.

/**
 * This library is unsafe because it does not MAC after encrypting
 */
class UnsafeMcryptAES
{
    const CIPHER = MCRYPT_RIJNDAEL_128;

    public static function encrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = mcrypt_get_iv_size(self::CIPHER);
        $iv = mcrypt_create_iv($ivsize, MCRYPT_DEV_URANDOM);

        // Add PKCS7 Padding
        $block = mcrypt_get_block_size(self::CIPHER);
        $pad = $block - (mb_strlen($message, '8bit') % $block, '8bit');
        $message .= str_repeat(chr($pad), $pad);

        $ciphertext = mcrypt_encrypt(
            MCRYPT_RIJNDAEL_128,
            $key,
            $message,
            MCRYPT_MODE_CBC,
            $iv
        );

        return $iv . $ciphertext;
    }

    public static function decrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = mcrypt_get_iv_size(self::CIPHER);
        $iv = mb_substr($message, 0, $ivsize, '8bit');
        $ciphertext = mb_substr($message, $ivsize, null, '8bit');

        $plaintext = mcrypt_decrypt(
            MCRYPT_RIJNDAEL_128,
            $key,
            $ciphertext,
            MCRYPT_MODE_CBC,
            $iv
        );

        $len = mb_strlen($plaintext, '8bit');
        $pad = ord($plaintext[$len - 1]);
        if ($pad <= 0 || $pad > $block) {
            // Padding error!
            return false;
        }
        return mb_substr($plaintext, 0, $len - $pad, '8bit');
    }
}

A oto wersja napisana przy użyciu OpenSSL:

/**
 * This library is unsafe because it does not MAC after encrypting
 */
class UnsafeOpensslAES
{
    const METHOD = 'aes-256-cbc';

    public static function encrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = openssl_cipher_iv_length(self::METHOD);
        $iv = openssl_random_pseudo_bytes($ivsize);

        $ciphertext = openssl_encrypt(
            $message,
            self::METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        return $iv . $ciphertext;
    }

    public static function decrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = openssl_cipher_iv_length(self::METHOD);
        $iv = mb_substr($message, 0, $ivsize, '8bit');
        $ciphertext = mb_substr($message, $ivsize, null, '8bit');

        return openssl_decrypt(
            $ciphertext,
            self::METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );
    }
}

Źródło: Jeśli wpisujesz słowo MCRYPT w swoim kodzie PHP, robisz to źle .

kenorb
źródło
2

Używam tego na PHP 7.2.x, działa dobrze dla mnie:

public function make_hash($userStr){
        try{
            /** 
             * Used and tested on PHP 7.2x, Salt has been removed manually, it is now added by PHP 
             */
             return password_hash($userStr, PASSWORD_BCRYPT);
            }catch(Exception $exc){
                $this->tempVar = $exc->getMessage();
                return false;
            }
        }

a następnie uwierzytelnij skrót za pomocą następującej funkcji:

public function varify_user($userStr,$hash){
        try{
            if (password_verify($userStr, $hash)) {
                 return true;
                }
            else {
                return false;
                }
            }catch(Exception $exc){
                $this->tempVar = $exc->getMessage();
                return false;
            }
        }

Przykład:

  //create hash from user string

 $user_password = $obj->make_hash2($user_key);

i aby uwierzytelnić ten hash, użyj następującego kodu:

if($obj->varify_user($key, $user_key)){
      //this is correct, you can proceed with  
    }

To wszystko.

Abdul Rahman
źródło
1

Jak wspomniano, nie należy przechowywać haseł użytkowników w formacie, który można odszyfrować. Odwracalne szyfrowanie zapewnia hakerom łatwą drogę do znalezienia haseł użytkowników, co obejmuje również narażenie kont użytkowników w innych witrynach, jeśli używają tam tego samego hasła.

PHP udostępnia parę potężnych funkcji do losowego, jednokierunkowego szyfrowania mieszającego - password_hash()i password_verify(). Ponieważ skrót jest automatycznie losowany, hakerzy nie mają możliwości wykorzystania wstępnie skompilowanych tabel skrótów haseł do odtworzenia hasła. Ustaw tę PASSWORD_DEFAULTopcję, a przyszłe wersje PHP będą automatycznie używać silniejszych algorytmów do generowania skrótów haseł bez konieczności aktualizowania kodu.

Thoracius Appotite
źródło
1

Powinieneś użyć openssl_encrypt()funkcji.

rqLizard
źródło
Czy szyfrowanie openssl w php 7 ma "serce"?
TheCrazyProfessor
13
dlaczego OP miałby używać openssl_encrypt? Podaj trochę szczegółów i tło
Martin
0

Udało mi się przetłumaczyć mój obiekt Crypto

  • Uzyskaj kopię php za pomocą mcrypt, aby odszyfrować stare dane. Poszedłem do http://php.net/get/php-7.1.12.tar.gz/from/a/mirror , skompilowałem go, a następnie dodałem rozszerzenie ext / mcrypt (konfiguracja; make; make install). Myślę, że musiałem dodać linię extenstion = mcrypt.so do pliku php.ini. Seria skryptów służących do tworzenia pośrednich wersji danych z niezaszyfrowanymi danymi.

  • Zbuduj klucz publiczny i prywatny dla openssl

    openssl genrsa -des3 -out pkey.pem 2048
    (set a password)
    openssl rsa -in pkey.pem -out pkey-pub.pem -outform PEM -pubout
  • Aby zaszyfrować (używając klucza publicznego) użyj openssl_seal. Z tego, co przeczytałem, openssl_encrypt przy użyciu klucza RSA jest ograniczone do 11 bajtów mniej niż długość klucza (patrz http://php.net/manual/en/function.openssl-public-encrypt.php komentarz Thomasa Horstena)

    $pubKey = openssl_get_publickey(file_get_contents('./pkey-pub.pem'));
    openssl_seal($pwd, $sealed, $ekeys, [ $pubKey ]);
    $encryptedPassword = base64_encode($sealed);
    $key = base64_encode($ekeys[0]);

Prawdopodobnie mógłbyś przechowywać surowy plik binarny.

  • Aby odszyfrować (używając klucza prywatnego)

    $passphrase="passphrase here";
    $privKey = openssl_get_privatekey(file_get_contents('./pkey.pem'), $passphrase);
    // I base64_decode() from my db columns
    openssl_open($encryptedPassword, $plain, $key, $privKey);
    echo "<h3>Password=$plain</h3>";

PS Nie możesz zaszyfrować pustego ciągu („”)

PPS Dotyczy to bazy danych haseł, a nie sprawdzania poprawności użytkownika.

Joshua Goldstein
źródło