Hướng dẫn end to end encryption php - mã hóa end to end php

Tôi đang tìm cách triển khai mã hóa từ đầu đến cuối cho các tin nhắn được gửi giữa người dùng trong ứng dụng Laravel của tôi. Tôi muốn mã hóa các tin nhắn này theo cách mà chúng chỉ có thể xem được bởi người gửi và người nhận (giống như trong các ứng dụng nhắn tin an toàn như WhatsApp). Không ai khác có thể đọc chúng, bao gồm quản trị viên hoặc DBA.

Tôi sẽ đi đâu để tới đó?

Tôi cũng nên đề cập rằng các tin nhắn sẽ được gửi qua trình duyệt đến máy chủ bằng yêu cầu AJAX JavaScript và được đẩy đến người dùng khác bằng thiết lập Node.js / Socket.io.

Đã hỏi ngày 15 tháng 11 năm 2016 lúc 20:35Nov 15, 2016 at 20:35

Hướng dẫn end to end encryption php - mã hóa end to end php

1

2016-08-19 | Bởi: Enrico Zimuel

Gần đây, chúng tôi đã phát hành Zend-Crypt 3.1.0, thành phần mật mã từ Zend Framework. Phiên bản cuối cùng này bao gồm một hệ thống mật mã lai, một tính năng có thể được sử dụng để thực hiện lược đồ mã hóa từ đầu đến cuối trong PHP.

Hệ thống mật mã lai là một cơ chế mật mã sử dụng mã hóa đối xứng (ví dụ: AES) để mã hóa một thông điệp và mật mã khóa công khai (ví dụ: RSA) để bảo vệ khóa mã hóa. Phương pháp này đảm bảo hai lợi thế: tốc độ của thuật toán đối xứng và bảo mật của mật mã khóa công cộng.

Trước khi chúng ta nói về việc triển khai PHP, hãy khám phá cơ chế lai chi tiết hơn. Dưới đây là một sơ đồ thể hiện lược đồ mã hóa lai:

Hướng dẫn end to end encryption php - mã hóa end to end php

Người dùng (người gửi) muốn gửi tin nhắn được bảo vệ cho người dùng khác (người nhận). Anh ấy/cô ấy tạo một khóa phiên ngẫu nhiên (PAD một lần) và sử dụng khóa này bằng thuật toán đối xứng để mã hóa thông báo (trong hình, mật mã khối đại diện cho một thuật toán mã hóa được xác thực). Đồng thời, người gửi mã hóa khóa phiên bằng khóa công khai của máy thu. Hoạt động này được thực hiện bằng thuật toán khóa công khai, ví dụ: RSA. Khi mã hóa được thực hiện, người gửi có thể gửi khóa phiên được mã hóa cùng với thông báo được mã hóa đến máy thu. Người nhận có thể giải mã khóa phiên bằng khóa riêng của mình và do đó giải mã tin nhắn.random session key (one-time pad) and uses this key with a symmetric algorithm to encrypt the message (in the figure, Block cipher represents an authenticated encryption algorithm). At the same time, the sender encrypts the session key using the public key of the receiver. This operation is done using a public-key algorithm, e.g., RSA. Once the encryption is done, the sender can send the encrypted session key along with the encrypted message to the receiver. The receiver can decrypt the session key using his/her private key, and consequently decrypt the message.

Ý tưởng kết hợp mã hóa đối xứng và không đối xứng (khóa công khai) này có thể được sử dụng để thực hiện mã hóa từ đầu đến cuối (E2EE). E2EE là một hệ thống truyền thông mã hóa các tin nhắn được trao đổi bởi hai người dùng với tài sản mà chỉ hai người dùng mới có thể giải mã tin nhắn. Mã hóa đầu cuối đã trở nên khá phổ biến trong những năm qua với việc sử dụng phần mềm phổ biến và các hệ thống nhắn tin đặc biệt, chẳng hạn như WhatsApp. Tổng quát hơn, khi bạn có một phần mềm được sử dụng bởi nhiều người dùng, mã hóa từ đầu đến cuối có thể được sử dụng để bảo vệ thông tin được trao đổi bởi người dùng. Chỉ người dùng mới có thể truy cập (giải mã) thông tin trao đổi; Ngay cả quản trị viên của hệ thống cũng không thể truy cập dữ liệu này.E2EE). An E2EE is a communication system that encrypts messages exchanged by two users with the property that only the two users can decrypt the message. End-to-end encryption has become quite popular in the last years with the usage in popular software, and particularly messaging systems, such as WhatsApp. More generally, when you have a software used by many users, end-to-end encryption can be used to protect information exchanged by users. Only the users can access (decrypt) exchanged information; even the administrator of the system is not able to access this data.

Xây dựng mã hóa từ đầu đến cuối trong PHP

Chúng tôi muốn triển khai mã hóa từ đầu đến cuối cho một ứng dụng web với xác thực người dùng. Chúng tôi sẽ sử dụng Zend-Crypt 3.1.0 để thực hiện các lược đồ mật mã của chúng tôi. Thành phần này của Zend Framework sử dụng tiện ích mở rộng OpenSSL cho PHP cho các nguyên thủy mật mã của nó.

Bước đầu tiên là tạo khóa công khai và riêng tư cho mỗi người dùng. Thông thường, bước này có thể được thực hiện khi thông tin đăng nhập người dùng được tạo. Để tạo ra các cặp khóa, chúng ta có thể sử dụng Zend\Crypt\PublicKey\RsaOptions. Dưới đây là một ví dụ chứng minh cách tạo các khóa công khai và riêng tư để lưu trữ trong hệ thống tập tin:

use Zend\Crypt\PublicKey\RsaOptions;
use Zend\Crypt\BlockCipher;

$username = 'alice';
$password = 'test'; // user's password

// Generate public and private key
$rsaOptions = new RsaOptions();
$rsaOptions->generateKeys([
    'private_key_bits' => 2048
]);
$publicKey  = $rsaOptions->getPublicKey()->toString();
$privateKey = $rsaOptions->getPrivateKey()->toString();

// store the public key in a .pub file
file_put_contents($username . '.pub', $publicKey);

// encrypt and store the private key in a file
$blockCipher = BlockCipher::factory('openssl', array('algo' => 'aes'));
$blockCipher->setKey($password);
file_put_contents($username, $blockCipher->encrypt($privateKey));

Trong ví dụ trên, chúng tôi đã tạo một khóa riêng là 2048 bit. Nếu bạn đang tự hỏi tại sao không phải là 4096 bit, điều này là đáng nghi ngờ và phụ thuộc vào trường hợp sử dụng thực sự. Đối với phần lớn các ứng dụng, 2048 vẫn là kích thước khóa tốt, ít nhất là cho đến năm 2030. Nếu bạn muốn bảo mật nhiều hơn và bạn không quan tâm đến thời gian CPU bổ sung, bạn có thể tăng kích thước chính lên 4096. Chúng tôi khuyên bạn nên đọc phần sau đây Bài đăng trên blog để biết thêm thông tin về kích thước khóa chính:

  • Kích thước khóa RSA: 2048 hoặc 4096 bit?
  • Cuộc tranh luận lớn, 2048 so với 4096, vị trí của Yubico,
  • Hiệu suất HTTPS, 2048-bit so với 4096-bit

Chúng tôi đã không tạo khóa riêng bằng cách sử dụng cụm mật khẩu; Điều này là do phần mở rộng OpenSSL của PHP không hỗ trợ chế độ ADEAD (được xác thực với dữ liệu liên quan); Chế độ AEAD sẽ được hỗ trợ bắt đầu từ Php 7.1, sẽ phát hành mùa thu này.AEAD (Authenticated Encrypt with Associated Data) mode yet; AEAD mode will be supported starting in PHP 7.1, which should release this autumn.

Thuật toán mã hóa mật khẩu mặc định cho OpenSSL là DES-EDE3-CBC bằng cách sử dụng PBKDF2 với các lần lặp 2048 để tạo khóa mã hóa từ mật khẩu của người dùng. Ngay cả khi thuật toán mã hóa này khá tốt, số lần lặp của PBKDF2 không tối ưu; Zend-Crypt cải thiện điều này theo nhiều cách khác nhau, vượt trội. Như đã trình bày ở trên, chúng tôi sử dụng Zend\Crypt\BlockCipher để mã hóa khóa riêng; Lớp này cung cấp mã hóa xác thực mã hóa bằng thuật toán AES-256 để mã hóa và HMAC-SHA-256 để xác thực. Ngoài ra, BlockCipher sử dụng thuật toán PBKDF2 để đưa ra khóa mã hóa từ khóa (mật khẩu) của người dùng. Số lần lặp mặc định cho PBKDF2 là 5000 và bạn có thể tăng nó bằng phương pháp BlockCipher::setKeyIteration().AES-256 algorithm for encryption and HMAC-SHA-256 for authentication. Moreover, BlockCipher uses the PBKDF2 algorithm to derivate the encryption key from the user's key (password). The default number of iterations for PBKDF2 is 5000, and you can increase it using the BlockCipher::setKeyIteration() method.

Trong ví dụ, chúng tôi đã lưu trữ các khóa công khai và riêng tư trong hai tệp có tên tương ứng, $username.pub$username. Vì tệp riêng được mã hóa, sử dụng mật khẩu của người dùng, nên người dùng chỉ có thể truy cập. Đây là một khía cạnh rất quan trọng đối với bảo mật của toàn bộ hệ thống (chúng tôi cho rằng ứng dụng web lưu trữ các băm mật khẩu của người dùng bằng thuật toán an toàn như BCrypt).

Khi chúng tôi có khóa công khai và riêng tư cho người dùng, chúng tôi có thể bắt đầu sử dụng hệ thống mật mã lai do Zend-Crypt cung cấp. Chẳng hạn, hãy tưởng tượng Alice muốn gửi một tin nhắn được mã hóa cho Bob:

use Zend\Crypt\Hybrid;
use Zend\Crypt\BlockCipher;

$sender   = 'alice';
$receiver = 'bob';
$password = 'test'; // bob's password

$msg = sprintf('A secret message from %s!', $sender);

// encrypt the message using the public key of the receiver
$publicKey  = file_get_contents($receiver . '.pub');
$hybrid     = new Hybrid();
$ciphertext = $hybrid->encrypt($msg, $publicKey);

// send the ciphertext to the receiver

// decrypt the private key of bob
$blockCipher = BlockCipher::factory('openssl', ['algo' => 'aes']);
$blockCipher->setKey($password);
$privateKey = $blockCipher->decrypt(file_get_contents($receiver));

$plaintext = $hybrid->decrypt($ciphertext, $privateKey);

printf("%s\n", $msg === $plaintext ? "The message is: $msg" : 'Error!');

Ví dụ trên cho thấy thông tin mã hóa giữa hai người dùng. Tất nhiên, trong trường hợp này, người gửi (Alice) biết tin nhắn vì cô ấy đã viết nó. Nói chung, nếu chúng ta cần lưu trữ bí mật giữa nhiều người dùng, chúng ta cần chỉ định các khóa công khai để được sử dụng để mã hóa.

Thành phần lai của Zend-Crypt hỗ trợ các thông báo mã hóa cho nhiều người nhận. Để làm như vậy, hãy chuyển một loạt các khóa công khai trong tham số $publicKey của

use Zend\Crypt\Hybrid;
use Zend\Crypt\BlockCipher;

$sender   = 'alice';
$receiver = 'bob';
$password = 'test'; // bob's password

$msg = sprintf('A secret message from %s!', $sender);

// encrypt the message using the public key of the receiver
$publicKey  = file_get_contents($receiver . '.pub');
$hybrid     = new Hybrid();
$ciphertext = $hybrid->encrypt($msg, $publicKey);

// send the ciphertext to the receiver

// decrypt the private key of bob
$blockCipher = BlockCipher::factory('openssl', ['algo' => 'aes']);
$blockCipher->setKey($password);
$privateKey = $blockCipher->decrypt(file_get_contents($receiver));

$plaintext = $hybrid->decrypt($ciphertext, $privateKey);

printf("%s\n", $msg === $plaintext ? "The message is: $msg" : 'Error!');
0.

Dưới đây cho thấy việc mã hóa một tệp cho hai người dùng, Alice và Bob.

use Zend\Crypt\Hybrid;
use Zend\Crypt\BlockCipher;

$data    = file_get_contents('path/to/file/to/protect');
$pubKeys = [
  'alice' => file_get_contents('alice.pub'),
  'bob'   => file_get_contents('bob.pub')
];

$hybrid     = new Hybrid();

// Encrypt using the public keys of both alice and bob
$ciphertext = $hybrid->encrypt($data, $pubKeys);

file_put_contents('file.enc', $ciphertext);

$blockCipher = BlockCipher::factory('openssl', ['algo' => 'aes']);

$passwords = [
  'alice' => 'password of Alice',
  'bob'   => 'password of Bob'
];

// decrypt using the private keys of alice and bob, one at time
foreach ($passwords as $id => $pass) {
  $blockCipher->setKey($pass);
  $privateKey = $blockCipher->decrypt(file_get_contents($id));
  $plaintext  = $hybrid->decrypt($ciphertext, $privateKey, null, $id);
  printf("%s for %s\n", $data === $plaintext ? 'Decryption ok' : 'Error', $id);
}

Để giải mã, chúng tôi đã sử dụng mật khẩu mã hóa cứng cho người dùng. Thông thường, mật khẩu của người dùng được cung cấp trong quá trình đăng nhập của ứng dụng web và không nên được lưu trữ dưới dạng dữ liệu vĩnh viễn; Chẳng hạn, mật khẩu của người dùng có thể được lưu trong biến phiên PHP để sử dụng tạm thời. Nếu bạn sử dụng các phiên để lưu mật khẩu của người dùng, hãy đảm bảo rằng dữ liệu được bảo vệ; Thư viện Php-Secure-Session hoặc tiện ích mở rộng Suhosin sẽ giúp bạn làm như vậy.

Để giải mã tệp, chúng tôi đã sử dụng hàm

use Zend\Crypt\Hybrid;
use Zend\Crypt\BlockCipher;

$sender   = 'alice';
$receiver = 'bob';
$password = 'test'; // bob's password

$msg = sprintf('A secret message from %s!', $sender);

// encrypt the message using the public key of the receiver
$publicKey  = file_get_contents($receiver . '.pub');
$hybrid     = new Hybrid();
$ciphertext = $hybrid->encrypt($msg, $publicKey);

// send the ciphertext to the receiver

// decrypt the private key of bob
$blockCipher = BlockCipher::factory('openssl', ['algo' => 'aes']);
$blockCipher->setKey($password);
$privateKey = $blockCipher->decrypt(file_get_contents($receiver));

$plaintext = $hybrid->decrypt($ciphertext, $privateKey);

printf("%s\n", $msg === $plaintext ? "The message is: $msg" : 'Error!');
1, trong đó chúng tôi đã chỉ định
use Zend\Crypt\Hybrid;
use Zend\Crypt\BlockCipher;

$sender   = 'alice';
$receiver = 'bob';
$password = 'test'; // bob's password

$msg = sprintf('A secret message from %s!', $sender);

// encrypt the message using the public key of the receiver
$publicKey  = file_get_contents($receiver . '.pub');
$hybrid     = new Hybrid();
$ciphertext = $hybrid->encrypt($msg, $publicKey);

// send the ciphertext to the receiver

// decrypt the private key of bob
$blockCipher = BlockCipher::factory('openssl', ['algo' => 'aes']);
$blockCipher->setKey($password);
$privateKey = $blockCipher->decrypt(file_get_contents($receiver));

$plaintext = $hybrid->decrypt($ciphertext, $privateKey);

printf("%s\n", $msg === $plaintext ? "The message is: $msg" : 'Error!');
2, cụm mật khẩu
use Zend\Crypt\Hybrid;
use Zend\Crypt\BlockCipher;

$sender   = 'alice';
$receiver = 'bob';
$password = 'test'; // bob's password

$msg = sprintf('A secret message from %s!', $sender);

// encrypt the message using the public key of the receiver
$publicKey  = file_get_contents($receiver . '.pub');
$hybrid     = new Hybrid();
$ciphertext = $hybrid->encrypt($msg, $publicKey);

// send the ciphertext to the receiver

// decrypt the private key of bob
$blockCipher = BlockCipher::factory('openssl', ['algo' => 'aes']);
$blockCipher->setKey($password);
$privateKey = $blockCipher->decrypt(file_get_contents($receiver));

$plaintext = $hybrid->decrypt($ciphertext, $privateKey);

printf("%s\n", $msg === $plaintext ? "The message is: $msg" : 'Error!');
3 và cuối cùng là
use Zend\Crypt\Hybrid;
use Zend\Crypt\BlockCipher;

$sender   = 'alice';
$receiver = 'bob';
$password = 'test'; // bob's password

$msg = sprintf('A secret message from %s!', $sender);

// encrypt the message using the public key of the receiver
$publicKey  = file_get_contents($receiver . '.pub');
$hybrid     = new Hybrid();
$ciphertext = $hybrid->encrypt($msg, $publicKey);

// send the ciphertext to the receiver

// decrypt the private key of bob
$blockCipher = BlockCipher::factory('openssl', ['algo' => 'aes']);
$blockCipher->setKey($password);
$privateKey = $blockCipher->decrypt(file_get_contents($receiver));

$plaintext = $hybrid->decrypt($ciphertext, $privateKey);

printf("%s\n", $msg === $plaintext ? "The message is: $msg" : 'Error!');
4 của PrivateKey. Các tham số này là cần thiết để tìm khóa chính xác để sử dụng trong tiêu đề của thông báo được mã hóa.

SHARE:

Mã hóa nào là tốt nhất cho PHP?

Mã hóa khóa bí mật (hoặc mã hóa đối xứng như cũng đã biết) sử dụng một khóa duy nhất để cả dữ liệu mã hóa và giải mã.Trong quá khứ PHP đã dựa vào McRypt và OpenSSL cho mã hóa khóa bí mật.Php 7.2 đã giới thiệu natri, hiện đại hơn và được coi là an toàn hơn. (or symmetric encryption as it's also known) uses a single key to both encrypt and decrypt data. In the past PHP relied on mcrypt and openssl for secret key encryption. PHP 7.2 introduced Sodium, which is more modern and widely considered more secure.

PHP có thể được sử dụng để mã hóa dữ liệu không?

PHP có thể hỗ trợ bạn trong việc này với một số phần mở rộng, chẳng hạn như OpenSSL và Natri, bao gồm nhiều thuật toán mã hóa.Kịch bản mã hóa dữ liệu trước khi chèn nó vào cơ sở dữ liệu và giải mã nó khi truy xuất.Xem các tài liệu tham khảo để biết thêm các ví dụ về cách thức mã hóa hoạt động.. The script encrypts the data before inserting it into the database, and decrypts it when retrieving. See the references for further examples of how encryption works.

Php có thể giải mã dữ liệu không?

PHP cho phép mã hóa và giải mã một chuỗi với một trong các phần mở rộng mật mã, được gọi là OpenSSL.Để ngắn gọn, nó có thể được sử dụng để mã hóa và giải mã dữ liệu.. To be short, it can be used to encrypt and decrypt data.

Kết thúc là gì

Mã hóa từ đầu đến cuối chỉ đảm bảo bạn và người bạn giao tiếp có thể đọc hoặc nghe những gì được gửi, và không ai ở giữa, thậm chí không có WhatsApp.ensures only you and the person you're communicating with can read or listen to what is sent, and nobody in between, not even WhatsApp.