Làm cách nào để sử dụng mã hóa trong Laravel?

Trong dự án của bạn, bạn có thể lưu trữ một số dữ liệu cá nhân hoặc thông tin xác thực nhạy cảm trong cơ sở dữ liệu của mình. Nếu một người không được phép truy cập vào DB của bạn, tất cả thông tin nhạy cảm này có thể được đọc

Để giải quyết vấn đề này, bạn có thể mã hóa dữ liệu. Bằng cách này, những người không có thẩm quyền không thể đọc nó, nhưng ứng dụng của bạn vẫn có thể giải mã nó khi bạn cần hiển thị hoặc làm việc với dữ liệu

CipherSweet là thư viện phụ trợ được phát triển bởi Paragon Initiative Enterprises để triển khai mã hóa cấp trường có thể tìm kiếm. Nó có thể mã hóa và giải mã các giá trị theo cách rất an toàn. Nó cũng có thể tạo các chỉ mục mù. Một chỉ mục mù có thể được sử dụng để thực hiện một số tìm kiếm được nhắm mục tiêu trên dữ liệu được mã hóa. Bản thân các chỉ số không thể đọc được bởi con người

Chúng tôi vừa phát hành laravel-ciphersweet. Gói này là một trình bao bọc bên ngoài CipherSweet, cho phép bạn dễ dàng sử dụng nó với các mô hình Eloquent của Laravel

Chuẩn bị mô hình của bạn và chọn các thuộc tính sẽ được mã hóa#

Thêm giao diện 

1$message = 'This is my secret message.';

2 

3>>> hash('sha256', $message)

4=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

5 

6>>> hash('sha256', $message)

7=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

4 và đặc điểm 

1$message = 'This is my secret message.';

2 

3>>> hash('sha256', $message)

4=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

5 

6>>> hash('sha256', $message)

7=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

5 vào mô hình mà bạn muốn thêm các trường được mã hóa vào

Bạn sẽ cần triển khai phương thức 

1$message = 'This is my secret message.';

2 

3>>> hash('sha256', $message)

4=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

5 

6>>> hash('sha256', $message)

7=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

6 để định cấu hình CipherSweet

use Spatie\LaravelCipherSweet\Contracts\CipherSweetEncrypted;
use Spatie\LaravelCipherSweet\Concerns\UsesCipherSweet;
use ParagonIE\CipherSweet\EncryptedRow;
use Illuminate\Database\Eloquent\Model;

class User extends Model implements CipherSweetEncrypted
{
    use UsesCipherSweet;
    
    public static function configureCipherSweet(EncryptedRow $encryptedRow): void
    {
        $encryptedRow
            ->addField('email')
            ->addBlindIndex('email', new BlindIndex('email_index'));
    }
}

Đang tạo khóa mã hóa#

Chúng tôi cũng đã thêm một lệnh trợ giúp nhỏ vào gói cho phép bạn tạo khóa mới theo cách được đề xuất bởi Paragon Initiative Enterprises

Khóa mã hóa này được sử dụng để mã hóa các giá trị của bạn

php artisan ciphersweet:generate-key

Mã hóa thuộc tính mô hình #

Khi mọi thứ đã được thiết lập, bạn có thể bắt đầu mã hóa các giá trị mô hình của mình

php artisan ciphersweet:encrypt  

Lệnh sẽ cập nhật tất cả các trường được mã hóa và chỉ mục mù của mô hình

Nếu bạn có nhiều hàng, quá trình này có thể mất nhiều thời gian vì mã hóa là một hoạt động sử dụng nhiều tài nguyên. Đừng lo lắng nếu nó hết thời gian vì một lý do nào đó, lệnh luôn có thể khởi động lại và chỉ cố mã hóa các mô hình khi cần

cập nhật của bạn. tập tin env#

Sau khi các trường đã được mã hóa, bạn nên thêm khóa CipherSweet đã tạo vào. tập tin env

CIPHERSWEET_KEY=

Khóa sẽ được ứng dụng của bạn sử dụng để đọc các giá trị được mã hóa

Tìm kiếm trên các chỉ mục mù #

Mặc dù các giá trị được mã hóa, bạn vẫn có thể tìm kiếm chúng bằng cách sử dụng chỉ mục mù. Các chỉ mục mù sẽ được xây dựng khi bạn chạy lệnh để mã hóa các giá trị mô hình

Gói của chúng tôi cung cấp phạm vi 

1$message = 'This is my secret message.';

2 

3>>> hash('sha256', $message)

4=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

5 

6>>> hash('sha256', $message)

7=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

7 và 

1$message = 'This is my secret message.';

2 

3>>> hash('sha256', $message)

4=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

5 

6>>> hash('sha256', $message)

7=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

8 để tìm kiếm trên các chỉ mục mù

Tham số đầu tiên là cột, tham số thứ hai là tên chỉ mục bạn thiết lập khi gọi

1$message = 'This is my secret message.';

2 

3>>> hash('sha256', $message)

4=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

5 

6>>> hash('sha256', $message)

7=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

9, tham số thứ ba là giá trị thô, gói sẽ tự động áp dụng mọi phép biến đổi và băm giá trị để tìm kiếm trên chỉ mục mù

Kết thúc #

CipherSweet là một thư viện rất mạnh và gói của chúng tôi làm cho nó rất dễ tiếp cận. Tất nhiên, hãy chắc chắn về những cột nào thực sự cần mã hóa và đừng lạm dụng nó, mã hóa tốn nhiều tài nguyên và có một số nhược điểm

Chúng tôi sẽ sử dụng gói này một cách tiết kiệm trong quá trình phát triển SaaS mailcoach sắp tới của chúng tôi. đám mây để bảo vệ thông tin cá nhân sẽ được lưu trữ bởi người dùng của chúng tôi

Tất nhiên, laravel-ciphersweet không phải là gói đầu tiên mà nhóm của chúng tôi đã xây dựng. Trên trang web của công ty chúng tôi, hãy xem tất cả các gói mã nguồn mở của chúng tôi trong danh sách dài này. Nếu bạn muốn hỗ trợ chúng tôi, hãy cân nhắc chọn bất kỳ sản phẩm trả phí nào của chúng tôi

Laravel 6 đã giới thiệu LazyCollection, một loại bộ sưu tập khác khai thác các trình tạo php để tiết kiệm bộ nhớ sử dụng. Mặc dù việc tìm nạp dữ liệu từ cơ sở dữ liệu được quản lý bởi eloquent, nhưng việc tìm nạp dữ liệu dựa trên API Web không được cung cấp. Bài viết này mô tả cách sử dụng điểm cuối api được phân trang để tìm nạp dữ liệu vào phiên bản LazyCollection

này các bạn. Trước khi đi sâu vào, tôi muốn bắt đầu bằng cách nói rằng tôi không phải là chuyên gia về mật mã và kiến ​​thức của tôi về chủ đề này rất hạn chế. Tôi không thể hiện mình là người có kỹ năng cao về mật mã và không nên đưa ra lời khuyên về bất kỳ điều gì liên quan đến mật mã. Điều quan trọng cần lưu ý là bạn không bao giờ nên cố gắng xây dựng các thuật toán mã hóa hoặc băm của riêng mình, mà nên sử dụng các thuật toán đã được thử nghiệm trong trận chiến, bởi vì những người thông minh hơn bạn và tôi đã nghĩ ra những thuật toán này. Bây giờ chúng ta hãy đi vào chủ đề của ngày hôm nay

Bạn có thể biết rằng blog này chủ yếu liên quan đến nội dung của Laravel (hiện tại 😉). Tuy nhiên, bài đăng thứ hai đến bài cuối cùng của tôi là 2 năm trước. Kể từ đó, tôi đã trở thành một kỹ sư và nhà phát triển. Tôi đã mở rộng kiến ​​thức của mình về khoa học máy tính và lập trình. Đó là lý do tại sao tôi muốn đi sâu vào một số thứ thú vị hơn, như hàng đợi, Laravel Horizon, mã hóa, công cụ mẫu và cố gắng làm sáng tỏ tất cả những điều đó cho nhà phát triển Laravel bình thường hoặc bất kỳ ai muốn tìm hiểu thêm

Hôm nay tôi sẽ bắt đầu với mã hóa và băm. Tôi sẽ đề cập đến ý nghĩa của chúng, sự khác biệt là gì, mức độ an toàn của chúng, khi nào sử dụng chúng, ý tưởng đằng sau chúng, có thể là một chút toán học và cách triển khai thực tế trong Laravel. Tôi biết mọi nhà phát triển Laravel đều đã ít nhất một lần gặp phải quá trình băm thông qua Hash facade hoặc trình trợ giúp bcrypt — khi tạo người dùng và băm mật khẩu. Nhưng bạn có biết điều đó làm gì không? . Vì vậy, sự khác biệt là gì?

Hôm nay, tôi sẽ bắt đầu với mã hóa. Chúng tôi sẽ mô tả mã hóa là gì, các loại mã hóa và bắt đầu với mã hóa đối xứng. Trong bài viết tiếp theo, chúng ta sẽ xem xét mã hóa bất đối xứng

mã hóa

Về cơ bản, ý tưởng đằng sau mã hóa là gửi tin nhắn một cách an toàn qua kênh liên lạc không an toàn bằng cách áp dụng các thuật toán mã hóa -- mã hóa và giải mã. Thuật toán cốt lõi là chúng ta lấy tin nhắn $m$ (được gọi là bản rõ), sử dụng một số khóa mã hóa $e$, áp dụng thuật toán mã hóa cho nó $c = E(m, e)$ và nhận được tin nhắn $c$ (được gọi là bản mã . Chúng tôi gửi bản mã đó qua kênh không an toàn tới một số người dùng. Người dùng có thể sử dụng khóa giải mã $d$ và thuật toán giải mã $m = D(c, d)$ để tạo bản rõ gốc từ bản mã

Các loại mã hóa

Nếu chúng tôi sử dụng cùng một khóa để mã hóa và giải mã, $e = d = K$, chúng tôi sẽ nhận được mã hóa đối xứng. Các thuật toán mã hóa đối xứng điển hình là AES và DES

Nhưng nếu chúng tôi không sử dụng cùng một khóa cho cả mã hóa và giải mã, nghĩa là $e \neq d$ (chúng tôi sử dụng hai khóa khác nhau, được gọi là khóa chung và khóa riêng), đây được gọi là mã hóa bất đối xứng. Thuật toán bất đối xứng tiêu biểu là RSA và Diffie-Hellman

Cả hai đều có ưu và nhược điểm và trường hợp sử dụng của chúng. Hãy bắt đầu với mã hóa đối xứng

Mã hóa đối xứng

Như tôi đã đề cập, trong mã hóa đối xứng, các khóa chính xác giống nhau được sử dụng để mã hóa và giải mã một số tin nhắn. Chúng tôi sử dụng khóa mã hóa để mã hóa, gửi tin nhắn đó (nhưng chúng tôi không bao giờ gửi khóa đó) đến người nhận và người nhận đó có thể sử dụng cùng một khóa để giải mã tin nhắn. Đối với bất kỳ ai chặn tin nhắn, bản mã đó sẽ trông giống như một loạt các ký tự ngẫu nhiên và sẽ không biết ý nghĩa của nó

Tính chất

Trong mã hóa đối xứng, có một quy tắc được gọi là nguyên tắc Kerckhoff. Quy tắc đó chỉ ra rằng một hệ thống mật mã phải được bảo mật, ngay cả khi tất cả các chi tiết (bản mã), ngoại trừ khóa, được biết đến công khai. Có nghĩa là, nếu tôi truy xuất một số dữ liệu được mã hóa từ cơ sở dữ liệu của bạn, tôi không thể giải mã tin nhắn đó nếu tôi không có khóa mã hóa của bạn. Tuy nhiên, điều quan trọng cần lưu ý là không có thuật toán mã hóa hoặc băm nào an toàn cho cuộc tấn công vũ phu. Mọi thuật toán đơn lẻ, cho cả mã hóa và băm, đều có thể bị bẻ khóa bằng vũ lực. Vâng, về lý thuyết. Nếu chúng ta mã hóa bằng khóa có kích thước 16 byte và kẻ tấn công có 1 tỷ máy tính và mỗi máy tính có thể kiểm tra 1 tỷ khóa mỗi giây, thì kẻ tấn công sẽ mất 10 nghìn tỷ năm để bẻ khóa. Ừ. bây giờ hãy tưởng tượng các phím thậm chí còn lớn hơn

Có 2 tính chất của hệ mật mã đối xứng

  • Sự khuếch tán — nếu chúng ta chỉ thay đổi một bit trong thông báo gốc (bản rõ) hoặc chỉ một bit trong khóa, thì bản mã sẽ bị thay đổi rất nhiều (theo thống kê, ít nhất 50% bản mã phải khác)

  • Nhầm lẫn - mọi bit từ bản mã phải phụ thuộc vào nhiều hơn một bit từ khóa, nhưng kết nối giữa chúng sẽ bị ẩn

Bằng cách tuân theo các thuộc tính này, chúng ta có thể thấy thuật toán mã hóa được thiết kế phù hợp có thể an toàn như thế nào. Chỉ cần thay đổi một bit trong khóa hoặc bản rõ sẽ ảnh hưởng đến rất nhiều bit trong bản mã

AES

Laravel sử dụng mật mã AES-256-CBC theo mặc định (có thể thấy từ

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

3). Điều đó nghĩa là gì? . Chúng tôi sẽ đề cập đến ý nghĩa của từng điều này. Vì AES được sử dụng rất rộng rãi nên chúng tôi sẽ giải quyết vấn đề đó. Điều đáng chú ý là ký hiệu này, AES-256-CBC không phải là thứ mà Laravel đã nghĩ ra, đó là ký hiệu tiêu chuẩn

AES (Advanced Encryption Standard) là đặc điểm kỹ thuật cho mã hóa. Nó được gọi là mật mã khối, có nghĩa là thông điệp văn bản gốc được tách thành các khối dữ liệu sau đó tất cả chúng được vận hành riêng. AES nhóm bản rõ thành các khối 16 byte (128 bit). Vì vậy, nếu bạn có một chuỗi có độ dài 64, khi mã hóa, chuỗi đó sẽ được chia thành 4 phần gồm 16 ký tự. Mỗi khối được chuyển đổi thành ma trận 4x4 trông giống như thế này

$${\begin{bmatrix}a_{0}&a_{4}&a_{8}&a_{12} \\ a_{1}&a_{5}&a_{9}&a_{13} \\ a_{2}&a_{

AES sau đó chạy một loạt các hoạt động trên mọi khối và lặp lại điều đó nhiều lần. Những lần lặp lại đó được gọi là lần lặp, hoặc vòng. Có rất nhiều lần lặp trên mỗi khối (ví dụ: 14 vòng cho khóa 32 byte). Tổng quan chung về AES là thế này

Làm cách nào để sử dụng mã hóa trong Laravel?

Trong AES, bạn cắm một số giá trị văn bản gốc, nó chạy một loạt các hoạt động và tạo ra bản mã sau một số vòng cụ thể. Để giải mã dữ liệu, AES sẽ chỉ cần chạy ngược các thao tác tương tự này. Điều này là lạ, phải không? . Ngay cả khi bạn biết chính xác các hoạt động sẽ chạy, với các giá trị chính xác mà nó sẽ thay thế, bạn vẫn không thể giải mã bản mã trừ khi bạn có khóa. Như bạn có thể thấy trong hình ảnh, các hành động thiết yếu mà AES sử dụng (theo trình tự) là (hình ảnh được lấy từ Wikipedia)

  • SubBytes - mỗi byte từ ma trận được thay thế bằng một giá trị khác. Giá trị này được xác định bằng cách sử dụng bảng tra cứu được xác định trước $S$

Làm cách nào để sử dụng mã hóa trong Laravel?

  • ShiftRows - mọi hàng trong ma trận (ngoại trừ hàng đầu tiên) được dịch chuyển sang trái. Hàng thứ hai được dịch chuyển một lần, hàng thứ ba hai lần, v.v.

Làm cách nào để sử dụng mã hóa trong Laravel?

  • MixColumns — thao tác này lấy một cột và nhân trái nó với một số ma trận được xác định trước, sau đó thay thế toàn bộ cột bằng các giá trị đã được tính toán

Làm cách nào để sử dụng mã hóa trong Laravel?

  • AddRoundKey — mỗi byte trong ma trận được kết hợp với một byte của khóa bằng thao tác bitwise xor tạo ra ma trận 4x4 mới

Làm cách nào để sử dụng mã hóa trong Laravel?

Các bước này được lặp lại nhiều lần cho đến khi khối rất khó hiểu được tạo ra. Còn một số thao tác phím khác (mở rộng phím, v.v.), nhưng chúng tôi sẽ không đề cập đến những thao tác này trong bài viết này. Như bạn có thể thấy, chúng tôi không bao giờ sử dụng bất kỳ thao tác ngẫu nhiên nào để thao tác với khối, mà thay vào đó là một tập hợp các bảng và giá trị được xác định rõ ràng. Có bất kỳ nhược điểm tốc độ nào khi sử dụng mã hóa không? . Điều đó có nghĩa là AES rất, rất nhanh trên tất cả các máy tính vì CPU có hỗ trợ của bên thứ nhất cho điều đó

Tôi rất thú vị khi sử dụng các phép toán logic và toán học đơn giản như dịch chuyển bit, XOR theo bit, thay thế, chúng ta có thể tạo ra một bản mã rất khó hiểu mà thực tế không thể đảo ngược về giá trị ban đầu

Đây là loại tổng quan cấp cao về cách thức hoạt động của AES. Tôi sẽ không tìm hiểu quá nhiều về toán học vì nó rất phức tạp, nhưng điều quan trọng là phải biết những điều cơ bản. Làm thế nào để sau đó chúng tôi thực sự mã hóa an toàn một tin nhắn có độ dài bất kỳ? . Có những thứ khác, chẳng hạn như EBC (Sách mã điện tử) mã hóa các khối sau đó chỉ cần nối chúng lại, nhưng thực sự không nên sử dụng EBC vì những lý do tôi sẽ không tham gia

Chế độ CBC (Cipher Block Chaining)

Ở chế độ CBC, AES sẽ XOR từng khối với khối bản mã trước đó trước khi mã hóa một khối. Điều này có nghĩa là mọi bản mã đều phụ thuộc vào từng khối bản rõ đã được mã hóa trước bản hiện tại. Khi mã hóa khối đầu tiên, vì chúng tôi không có bản mã nào trước đó để XOR, nên chúng tôi XOR với chuỗi byte ngẫu nhiên. Khác với khóa, đây là giá trị ngẫu nhiên đầu tiên chúng tôi gặp phải. Chuỗi byte ngẫu nhiên này được gọi là IV hoặc vectơ khởi tạo. Đối với AES, IV là 16 byte ngẫu nhiên. Tổng quan về cách thức hoạt động của chế độ CBC có thể được nhìn thấy trong hình ảnh bên dưới (và quá trình giải mã giống hệt nhau chỉ ngược lại)

Làm cách nào để sử dụng mã hóa trong Laravel?

Thật tuyệt, giờ chúng ta đã biết cách mã hóa toàn bộ tin nhắn để nhận được bản mã. Giờ thì sao? . Giả sử ai đó gửi cho bạn một tin nhắn được mã hóa và bạn thực sự sở hữu cùng một khóa bí mật. Bạn có thể giải mã tin nhắn? . Bạn không có khối IV đó. Đây là vấn đề đầu tiên của chúng tôi, người gửi cần gửi cho chúng tôi IV cũng như bản mã. Bây giờ hãy tưởng tượng rằng bạn cũng biết chính xác IV. Bạn có thể giải mã tin nhắn bây giờ? . bạn có thực sự chắc chắn rằng tin nhắn đã được gửi không bị giả mạo bởi kẻ tấn công độc hại không?

Đó là lý do tại sao chúng tôi sử dụng một thứ gọi là chữ ký điện tử để xác minh tính xác thực của tin nhắn. Về cơ bản, có một mã gọi là MAC (Mã xác thực thư) được gửi cùng với bản mã và IV. Mã này có thể được sử dụng để xác minh tính xác thực

xác minh

MAC có thể được tạo bằng các phương pháp khác nhau, ví dụ như sử dụng hàm băm. Về cơ bản, hàm băm là hàm một chiều (rất dễ tính toán theo một hướng và rất khó để phá vỡ theo hướng khác) tạo ra một thông báo tóm tắt (băm) của một tin nhắn. Nó không thể được tính toán theo hướng ngược lại, nghĩa là đưa ra một thông báo tóm tắt, bạn không thể tìm thấy thông báo gốc. Bản chất của hàm băm là nó trông rất ngẫu nhiên, giống như hàm băm bạn nhận được hoàn toàn vô nghĩa, tuy nhiên, có những thao tác đã được thử nghiệm rất kỹ lưỡng được sử dụng để tạo hàm băm

Do thực tế là việc tạo một hàm băm không phải là ngẫu nhiên, nên bạn thực sự có thể xác minh rằng hai hàm băm bằng nhau, vì mọi thông báo mà bạn băm tạo ra cùng một thông báo mỗi khi bạn chạy hàm băm. Để đảm bảo điều này là đúng, hãy xem đoạn mã bên dưới (hãy tự mình thử, bạn sẽ nhận được kết quả tương tự). Tại sao điều này lại khác đối với trình băm mật khẩu Laravel?

1$message = 'This is my secret message.';

2 

3>>> hash('sha256', $message)

4=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

5 

6>>> hash('sha256', $message)

7=> "20bee756d7b4d0a39a665b7b22b908779477b35ec63190914c8f70f08dd06387"

Khi tận dụng hàm băm để tạo MAC, chúng ta cần một hàm băm có khóa. Đó là một chức năng thực sự nhận khóa bí mật làm một trong các đầu vào và thông báo phụ thuộc vào khóa đó. Cái này được gọi là HMAC và PHP có triển khai riêng cho các hàm băm HMAC

Đối với đầu vào hàm băm HMAC, chúng ta có thể nối bản mã với IV, tạo hàm băm bằng cách sử dụng giá trị đó, sau đó chuyển hàm băm đó dọc theo bản mã và IV. Khi giải mã, chúng ta có thể áp dụng cùng một hàm băm trên IV và bản mã (sử dụng cùng một khóa bí mật) và đảm bảo 2 giá trị băm bằng nhau. Nếu 2 giá trị băm giống nhau, chúng tôi có thể chắc chắn rằng thông báo không bị giả mạo. Làm thế nào kẻ tấn công có thể tạo ra cùng một hàm băm? . Khá khó để bẻ khóa, phải không?

Triển khai trong Laravel

Bây giờ chúng ta đã đề cập đến những điều cơ bản (vâng, đó chỉ là những điều cơ bản) về mã hóa, hãy đi sâu vào Laravel để xem cách mã hóa được triển khai ở đó. Như chúng tôi đã lưu ý, bằng cách nào đó chúng tôi cần chuyển IV và hàm băm cùng với bản mã. Hệ thống mã hóa đối xứng của Laravel nằm trong lớp

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

4. Bạn cũng có thể sử dụng các hàm trợ giúp

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

5 và

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

6. Họ chỉ gọi các phương thức tương ứng của lớp Mã hóa. Nếu chúng ta đi sâu vào lớp, trước hết chúng ta có thể thấy khóa mã hóa và mật mã trong hàm tạo của lớp. Laravel, theo mặc định, chuyển các giá trị này từ tệp cấu hình (được liên kết trong

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

7). Các giá trị này là

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

8 và

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

9. Khóa ứng dụng được tải từ biến môi trường
php artisan ciphersweet:generate-key
20. Vâng, đây là điểm của biến APP_KEY kỳ diệu mà mọi ứng dụng của bạn cần

Khóa và tạo khóa

Tôi chắc chắn rằng APP_KEY của bạn trông giống như thế này.

php artisan ciphersweet:generate-key
21. Chúng tôi cũng biết rằng khóa mã hóa cần phải là chuỗi byte ngẫu nhiên, để làm cho nó rất khó đoán và vì chúng tôi biết rằng rất khó để biểu diễn byte dưới dạng văn bản, chúng tôi có thể sử dụng mã hóa
php artisan ciphersweet:generate-key
22 để chuyển đổi các byte này thành một khối văn bản. Laravel thêm tiền tố vào khóa được mã hóa bằng tiền tố
php artisan ciphersweet:generate-key
23 để nó biết cách phân tích nó. Điều này có thể được nhìn thấy từ phương pháp
php artisan ciphersweet:generate-key
24 trong

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

7. Khi phân tích cú pháp khóa, Laravel truy xuất mọi thứ sau tiền tố và giải mã nó trở lại một chuỗi byte

Cách tạo khóa hoạt động (

php artisan ciphersweet:generate-key
26) là chúng tôi tạo khóa mã hóa có kích thước mà mật mã chúng tôi sử dụng

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

Bạn có nhớ khóa phải lớn như thế nào đối với AES-256-CBC không? . Đối với AES-128-CBC, chúng tôi sử dụng 16 byte. Bây giờ, hãy tìm hiểu phương thức

php artisan ciphersweet:generate-key
27 của Encrypter

php artisan ciphersweet:generate-key
2

Chà, ai mà ngờ được chứ?

Việc thực hiện mã hóa

Bây giờ chúng ta đã biết điểm của APP_KEY là gì và chúng ta đã tạo khóa bí mật mà chúng ta sẽ sử dụng để mã hóa, chúng ta có thể xem cách mã hóa được triển khai trong Laravel. Điều này được thực hiện thông qua phương thức

php artisan ciphersweet:generate-key
29 trên lớp Encrypter. Tham số thứ hai,
php artisan ciphersweet:encrypt  
40, chỉ đơn giản xác định xem giá trị có được đánh số thứ tự trước khi mã hóa hay không. Không quan trọng ngay bây giờ

Bạn nhớ các bước CBC, phải không?

Nếu chúng ta đào sâu vào codebase, điều đầu tiên chúng ta thấy là

php artisan ciphersweet:encrypt  
4

Điều này cho tôi biết rằng Laravel đang sử dụng triển khai OpenSSL, đây là tiêu chuẩn vàng để triển khai mã hóa. Mát mẻ. Chúng ta thấy hàm

php artisan ciphersweet:encrypt  
41 được gọi là. Hàm này chỉ đưa ra độ dài của vectơ khởi tạo (IV) cho mật mã. Đối với AES-256-CBC, vectơ này lớn đến mức nào? . Vì vậy, Laravel chỉ cần tạo 16 byte ngẫu nhiên và lưu trữ nó trong biến
php artisan ciphersweet:encrypt  
42

Bước tiếp theo là. ?

php artisan ciphersweet:encrypt  
8

Một lần nữa, chúng tôi sử dụng chức năng của OpenSSL để mã hóa dữ liệu. Hàm này sẽ nhận được các giá trị sau (hãy thử tự đoán xem nó cần giá trị nào)

  • bản rõ (
    php artisan ciphersweet:encrypt  
    
    43)
  • mật mã (AES-256-CBC) (
    php artisan ciphersweet:encrypt  
    
    44)
  • khóa mã hóa (
    php artisan ciphersweet:encrypt  
    
    45)
  • IV (
    php artisan ciphersweet:encrypt  
    
    42)

Phương pháp này thực hiện mã hóa và tạo ra bản mã dựa trên tất cả các giá trị này. Vì vậy, bạn có thể thấy, không phải chúng tôi tự mã hóa dữ liệu, chúng tôi LUÔN sử dụng các giải pháp đã được thử nghiệm thực tế. Phương thức này cũng trả về

php artisan ciphersweet:encrypt  
47 nếu mã hóa không thể hoàn thành, vì vậy Laravel sẽ kiểm tra điều đó

Bây giờ chúng ta đã tạo bản mã, chúng ta cần ký nó bằng MAC, phải không?

CIPHERSWEET_KEY=
4

Đó là chính xác những gì nó làm. Chúng tôi

php artisan ciphersweet:generate-key
22 mã hóa IV (vì đây chỉ là 16 byte ngẫu nhiên), nối IV và bản mã sau đó băm nó. Trong trường hợp này, Laravel sử dụng hàm băm SHA256 có khóa thông qua hàm
php artisan ciphersweet:encrypt  
49 của PHP. Hàm này khác với hàm
php artisan ciphersweet:encrypt  
80 ở chỗ nó tạo hàm băm bằng HMAC mà chúng ta đã biết

Khi MAC được tạo, chúng tôi đã hoàn tất. Chúng tôi chỉ cần giảm giá trị này thành một chuỗi duy nhất có thể được gửi qua kênh không an toàn. Cách Laravel thực hiện điều này là tạo một JSON từ IV, MAC và bản mã

CIPHERSWEET_KEY=
8

Giá trị JSON này sau đó được mã hóa base64 và được trả về từ phương thức. Chuẩn rồi. Điều này có nghĩa là một khi bạn nhận được giá trị xấu xí khổng lồ đó từ bộ mã hóa, thì đó là phiên bản được mã hóa base64 của JSON

CIPHERSWEET_KEY=
9

Chúng tôi có mọi thứ chúng tôi cần, thật tuyệt. Bây giờ, vì mã hóa đối xứng sử dụng một khóa duy nhất, chúng ta có thể chuyển cùng giá trị đó cho phương thức

php artisan ciphersweet:encrypt  
81 trong Bộ mã hóa và xem cách thức hoạt động của nó

Việc thực hiện giải mã

Chúng tôi đã biết rằng mã cơ sở 64 của JSON được chứa khi bạn

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

5 một giá trị. Giả sử đây là điều tương tự được truyền cho phương thức

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

6. Bạn có thử đoán xem phương pháp này sẽ trông như thế nào không? . Chà, trước tiên chúng tôi giải mã và giải nén JSON. Hãy tự mình thử điều này

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

3

Sau khi giải nén, chúng tôi có thể xác minh tin nhắn bằng cách tự tính toán MAC và so sánh MAC được gửi trong tải trọng. May mắn thay, PHP cung cấp phương pháp

php artisan ciphersweet:encrypt  
84 để so sánh 2 giá trị băm

Nếu chúng ta đào sâu vào phương thức

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

6, chúng ta sẽ thấy rằng dòng đầu tiên trong phương thức giải mã là như sau

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

6

php artisan ciphersweet:encrypt  
86 giải mã thông báo base64, giải mã JSON thành mảng và chỉ cần xác thực mọi thứ chúng tôi cần để giải mã đều có trong mảng. Đó là IV, giá trị, MAC và xác minh rằng IV có kích thước phù hợp (16 byte). Tuy nhiên, phương pháp này cũng có cái hay

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

0

Trước khi tìm hiểu phương pháp

php artisan ciphersweet:encrypt  
87, hãy thử đoán xem nó sẽ như thế nào? . Hãy nhớ rằng, cùng một lớp đó có một phương thức
php artisan ciphersweet:encrypt  
80 nối IV và bản mã

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

1

hoan hô. Chúng tôi biết chính xác những gì mọi phương pháp làm và làm thế nào nó làm điều đó. Sau khi tin nhắn được xác minh, chúng tôi biết nó không bị giả mạo. Chúng tôi chỉ có thể giải mã bằng khóa mã hóa của mình và IV, sau đó chỉ cần trả lại văn bản gốc đó bằng cách sử dụng cùng triển khai của OpenSSL

1$key = base64_encode(

2 Encrypter::generateKey(config('app.cipher'))

3);

4 

5// write this to .env

6"APP_KEY=base64:".$key

2

Tóm lược

Đây gần như là những gì tôi muốn trình bày về mã hóa đối xứng. Như bạn có thể nhớ, có các thuật toán bất đối xứng sử dụng các khóa bí mật khác nhau để mã hóa và giải mã. Chúng tôi sẽ giải quyết những vấn đề này trong phần tiếp theo của loạt bài này

Bây giờ bạn đã biết rằng mã hóa rất an toàn và rất nhanh, không có lý do gì mà bạn không sử dụng nó. Cách tôi sử dụng là tôi mã hóa dữ liệu trước khi lưu trữ trong cơ sở dữ liệu và giải mã nó sau khi truy xuất từ ​​cơ sở dữ liệu (hoặc tự động bằng cách sử dụng

php artisan ciphersweet:encrypt  
89 Eloquent cast). Điều này rất quan trọng đối với dữ liệu nhạy cảm như tên, số điện thoại, địa chỉ, khóa API, khóa SSH được lưu trữ trong cơ sở dữ liệu, đôi khi là cả mật khẩu

Ví dụ, hãy nghĩ về Laravel Forge. Forge cần lưu trữ các khóa SSH của máy chủ trong cơ sở dữ liệu, mật khẩu cơ sở dữ liệu của bạn để nó có thể đưa nó vào trang web của bạn. env, mã thông báo DigitalOcean của bạn để nó có thể tạo máy chủ mới cho bạn. Băm những giá trị này không phải là một giải pháp cho những vấn đề này, vì nó không thể truy xuất được sau này. Nếu Forge băm mã thông báo DigitalOcean của bạn, nó sẽ không thể kết nối với API của nó sau này. Đó là lý do tại sao nó nên mã hóa dữ liệu và giải mã sau khi cần. Tuy nhiên, nếu ai đó hack Forge và truy cập cơ sở dữ liệu của nó, nó sẽ không thể giải mã thông tin nhạy cảm mà không có APP_KEY của nó. Đây cũng là nhược điểm của mã hóa đối xứng — nếu ai đó nhận được quyền truy cập vào khóa mã hóa của bạn, dữ liệu của bạn sẽ bị xâm phạm

Cảm ơn bạn đã đọc, nếu bạn có bất kỳ câu hỏi nào, vui lòng gửi tin nhắn trực tiếp cho tôi trên Twitter, @ jcrnkovic95. Tôi nhắc lại một lần nữa, bài viết này đề cập đến ý tưởng rất đơn giản đằng sau mã hóa và AES và chỉ đề cập đến những điều cơ bản. Theo dõi bài viết tiếp theo về mã hóa bất đối xứng và xem cách bạn thực sự sử dụng mã hóa, cả đối xứng và bất đối xứng, mỗi ngày. Nó sẽ không bao gồm quá nhiều Laravel, nhưng nó sẽ bao gồm chứng chỉ SSL, máy chủ Forge của bạn và hơn thế nữa

Làm cách nào để sử dụng mã hóa trong Laravel?

Việc mã hóa một giá trị có thể được thực hiện bằng cách sử dụng trình trợ giúp mã hóa trong bộ điều khiển của lớp Laravel . Các giá trị này được mã hóa bằng mật mã OpenSSL và AES-256. Tất cả các giá trị được mã hóa được ký bằng mã Xác thực Thư (MAC) để kiểm tra mọi sửa đổi của chuỗi được mã hóa.

Làm cách nào để mã hóa và giải mã ID trong Laravel?

Nếu bạn muốn mã hóa và giải mã các giá trị mà không cần tuần tự hóa, bạn có thể sử dụng các phương thức EncryptString và DecryptString của Crypt facade. .
sử dụng Chiếu sáng\Hỗ trợ\Mặt tiền\Crypt;
$encrypted = Mật mã. cryptString('Xin chào thế giới. ' );
$decrypted = Mật mã. decryptString($encrypted);

Làm cách nào để mã hóa và giải mã mật khẩu trong Laravel?

Để làm điều đó, hãy mở các tuyến đường/web. php và thêm vào như sau. Lộ trình. get('mã hóa', EncryptionController@encrypt'); . get('decrypt', EncryptionController@decrypt'); Lộ trình đầu tiên là /encrypt route sẽ tạo ra một chuỗi được mã hóa cho chúng ta và lộ trình thứ hai sẽ giải mã chuỗi đó.

Laravel sử dụng loại mã hóa nào?

Bộ mã hóa của Laravel sử dụng OpenSSL để cung cấp mã hóa AES-256 và AES-128 .