Bảo mật và mật mã học

Phần học này vào năm ngoái đã giới thiệu cho các bạn cách sử dụng máy tính một cách an toàn và bảo mật hơn. Năm nay, chúng tôi sẽ tập trung vào các khái niệm an toàn thông tin (security) và mật mã học (cryptography). Chúng sẽ giúp ta hiểu rõ thêm về các công cụ được giới thiệu trước đây trong khóa học, ví dụ như việc dùng hàm băm (hash functions) trong Git hoặc trong hàm tạo khóa (Key Derivation Functions), hoặc áp dụng các hệ thống mã hóa đối xứng (symmetric) và bất đối xứng (asymmetric) trong trình SSH.

Cần lưu ý rằng phần học này không thể thay thế cho một khóa học đầy đủ và toàn diện về an toàn máy tính (6.858) hay mã hóa học(6.857 và 6.875). Đừng bao giờ đụng đến an toàn thông tinh nếu như bạn chưa hiểu về nó. Đặc biệt cần lưu ý đến việc tự tạo các hàm mã hóa nếu như bạn không phải là một chuyên gia!

Phần học này sẽ cho bạn cái nhìn đơn giản hóa (nhưng theo tôi là thực dụng) về các khái niệm mật mã học. Phần học này là chắc chắn không đủ kiến thức để bạn có thể tư thiết kế các hệ thống bảo mật và giao thức mật mã học.Tuy nhiên, chúng tôi hy vọng sẽ cho bạn kiến thức bao quát nhất về các chương trình và giao thức mà bạn đã và đang sử dụng.

Entropy

Entropy là một đơn vị đo độ hỗn độn (randomness). Nó rất hữu dụng trong việc đo lường độ mạnh của mật khẩu của bạn.

XKCD 936: Password Strength

Như bạn thấy trong truyện tranh ở trên XKCD comic, mật khẩu “correcthorsebatterystaple” an toàn hơn mật khẩu “Tr0ub4dor&3”. Làm sao ta khẳng định được điều này?

Entropy được đo theo đơn vị bits, và khi được lựa một kết quả ngẫu nhiên trong phân phối đồng nhất (uniformly random), thì entropy sẽ bằng log_2(# số kết quả có thể). Tung một đồng xu cho ta 1 bit entropy. Tung xúc xắc (6 mặt) cho ta khoản ~2.58 bits entropy

Chúng ta có thể giả định rằng kẻ xấu biết về mô hình (model - ý nói về ký tự hợp thành mật khẩu) của mật khấu, nhưng không hề biết gì về độ ngẫu nhiên dùng để chọn mật khẩu đó.

Bao nhiêu bits entropy thì là đủ? Đó hoàn toàn tùy theo mô hình mối nguy (threat model) của bạn. Đối với việc tấn công mật khẩu online (Online guessing - việc đoán mật khẩu ngay tại giao diện đăng nhập), như truyện tranh XKCD đã chỉ ra, tầm 40 bits entropy là rất tốt. Còn để phòng ngừa việc bị tấn công offline (Offline guessing - khi hacker có được một chuỗi băm của password của bạn và tìm cách giải mã nó), một mật khẩu mạnh hơn (tầm 80 bits hay hơn) là cần thiết

Hàm băm (Hash functions)

Hàm băm mật mã học (cryptographic hash function) là một hàm toán học để chuyển đổi một dữ liệu với kíck cỡ bất kỳ thành một kích cỡ được quy đinh. Hàm băm được mô tả khái quát như sau:

hash(value: array<byte>) -> vector<byte, N>  (với một N đã được định trước)

Một ví dụ về hàm băm là SHA1, được dùng trong Git. Nó có thể băm nhỏ thông tin thành một chuỗi 160 bit thông tin (40 kí tự thập lục phân). Ta có thể thử băm SHA1 bằng câu lệnh sha1sum:

$ printf 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ printf 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ printf 'Hello' | sha1sum 
f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0

Một cách khái quát hơn, hàm băm là một hàm rất khó để đảo ngược (hard-to-invert), nhìn rất ngẫu nhiên (vì thêm một chữ vào chuỗi cần mã hóa sẽ tạo ra một chuỗi băm hoàn toàn khác) tuy nhiên lại tất định (deterministic). Đây là những mô tả về mô hình hoàn hảo của hàm băm. Hàm băm có những đặc tính:

Lưu ý: mặc dù hữu dụng nhưng SHA-1 không còn là một hàm băm tốt. Bạn cũng có thể tham khảo về vòng đời của các hàm băm ở đây. Tuy vậy, việc lựa chọn một hàm băm tốt là hoàn toàn ngoài mục đích của phần học này. Nếu bạn muốn hiểu thêm điều này, bạn cần phải học mật mã học hay an toàn thông tinh một cách chính quy hơn.

Ứng Dụng

Hàm tạo khóa (Key derivation functions)

Một khái niệm liên quan đến các hàm băm mật mã là các hàm tạo khóa (gọi tắt là KDF). Các hàm này được dùng trong nhiều ứng dụng như tạo các kết quả với cùng kich cỡ để làm khóa (key) dùng trong các thuật toán mật mã khác. Thường thì các hàm KDF được thiết kể rất tốn thời gian và điều này giúp làm chậm hơn các cuộc tấn công offline, thử hết (brute-force). <!–

Key derivation functions

A related concept to cryptographic hashes, key derivation functions (KDFs) are used for a number of applications, including producing fixed-length output for use as keys in other cryptographic algorithms. Usually, KDFs are deliberately slow, in order to slow down offline brute-force attacks. –>

Ứng Dụng

Mật mã học đối xứng

Bảo mật nội dung của một tin nhắn chắc chắn là khái niệm đầu tiên mà bạn biết về mật mã học. Mật mã học bất đối xứng có thể làm điều này bằng các chức năng sau đây:

keygen() -> key  (đây là một hàm tạo số ngẫu nhiên)

encrypt(plaintext: array<byte>, key) -> array<byte>  (the ciphertext)
decrypt(ciphertext: array<byte>, key) -> array<byte>  (the plaintext)

*encrypt, decrypt là hàm mã hóa và hàm giải mã
**plaintext là nội dung chưa mã hóa
***ciphertext là nội dung mã hóa

Hàm mã hóa có tính chất là nếu biết kết quả mã hóa, sẽ rất khó để đoán nội dung chưa mã hóa nếu không có khóa dùng trong mã hóa. Hàm giải mã thì chắc chắn phải có tính chất decrypt(encrypt(m, k), k) = m.

Một ví dụ về mật mã đối xứng là AES.

Ứng Dụng

Mật mã học bất đối xứng

Thuật ngữ “bất đối xứng” nhắc đến việc phương pháp này cần hai chìa khóa với hai chứng năng khác nhau. Loại thứ nhất là chìa khóa riêng (private key), cần được giữ bí mật. Loại còn lại là chìa khóa chung và có thể được chia sẻ một cách thoải mái và không hề ảnh hưởng đến bảo mật thông tin (khác với việc không được chia sẻ chìa khóa trong bảo mật đối xứng). Mật mã bất đối xứng gồm các hàm sau để mã hóa/ giải mã hay để kí/ xác nhận chữ kí:

keygen() -> (public key, private key)  (đây là một hàm tạo số ngẫu nhiên)

encrypt(plaintext: array<byte>, public key) -> array<byte>  (the ciphertext)
decrypt(ciphertext: array<byte>, private key) -> array<byte>  (the plaintext)

sign(message: array<byte>, private key) -> array<byte>  (the signature)
verify(message: array<byte>, signature: array<byte>, public key) -> bool  (true nếu chữ kí là là xác thực và ngược lại là false)

*signature là chữ kí số

Hàm encrypt/decrypt có chức năng như trong mật mã học đối xứng. Tin nhắn có thể được mã hóa bằng chìa khóa chung. Kết quả mã hóa sau đó sẽ khó được sử sụng để đoán nội dung chưa được mã hóa nếu ta không có chìa khóa riêng. Hàm giải mã có thuộc tính decrypt(encrypt(m, public key), private key) = m.

Mật mã học đối xứng và bất đối xứng có thể được hiểu như các loại khóa ngoài đời thực. Mật mã học đối xứng thì giống như khóa cửa: ai có khóa thì khóa/ mở khóa được. Còn bất đối xứng thì như loại khóa số: bạn có thể đưa ổ khóa số đã mở cho ai đó (chìa khóa chung), họ sẽ cho tin nhắn vào trong hộp và khóa lại bằng ổ này, sau đó chỉ có bạn - người biết mật mã (chìa khóa riêng) có thể mở được ổ khóa.

Hàm kí và xác nhận chữ kí thì có tác dụng như chữ kí tay của chúng ta. Sẽ rất khó để nhái chữ kí. Không cần biết nội dung của tin nhắn, nếu không có chìa khóa riêng, sẽ rất khó để tạo ra một chữ kí số để kết quả của hàm verify(message, signature, public key) là true. Và tất nhiên, hàm xác thực chữ kí có tính chất đúng đắn sau: verify(message, sign(message, private key), public key) = true.

Ứng dụng

Truyền dẫn chìa khóa

Bảo mật bất đối xứng thật sự tuyệt vời, nhưng đi cùng với nó là những thách thức trong việc chia sẻ khóa chung hay việc định danh khóa chung với một đối tượng đời thực. Có rất nhiều lời giải cho bài toán này. Ứng dụng nhắn tin Signal có một lời giải đơn giản: tin tưởng trong lần dùng đầu và cho phép trao đổi chìa khóa chung ngoài luồng (bạn phải tự xác thực số điện thoại của đối tượng bạn nhắn tin ngoài đời). PGP thì có một phương pháp khác, gọi là “mạng lưới của sự tin cậy” (web of trust). Keybase thì lại có một lời giải khác cho việc chứng thực xã hội (social proof). Mỗi phương pháp có cái hay riêng; chúng tôi - những người tạo khóa học này thì thích cách của Keybase nhất. <!–

Key distribution

Asymmetric-key cryptography is wonderful, but it has a big challenge of distributing public keys / mapping public keys to real-world identities. There are many solutions to this problem. Signal has one simple solution: trust on first use, and support out-of-band public key exchange (you verify your friends’ “safety numbers” in person). PGP has a different solution, which is web of trust. Keybase has yet another solution of social proof (along with other neat ideas). Each model has its merits; we (the instructors) like Keybase’s model. –>

Case studies

Phần mềm quản lý mật khẩu

Đây là một công cụ hữu dụng mà mỗi người nên thử (vài ví dụ như KeePassXC, pass,hay 1Password). Những phần mềm này cho bạn sự tiện lợi để tạo các mật khẩu an toàn với entropy cao cho mỗi tài khoản đăng nhập. Chúng còn có thể lưu giữ các mật khẩu của bạn cùng một chỗ với bảo mật bằng mật mã đối xứng cùng chìa khóa tạo ra từ các hàm KDF và mật khẩu mà bạn cung cấp.

Dùng các chương trình này cũng hạn chế việc lập lại mật khẩu (giúp bạn an toàn hơn khi một trong những trang web có cùng mật khẩu bị tấn công). Điều tốt hơn nữa là bạn chỉ cần phải nhớ một mật khẩu an toàn duy nhất.

Bảo mật hai lớp (2FA)

Phương pháp bảo mật 2 lớp yêu cầu bạn dùng một mật khẩu (“cái bạn biết”) cùng với một trình xác thực 2FA (như YubiKey - “cái bạn sở hữu”) để bảo vệ bạn khỏi việc bị ăn cắp mật khẩu và các cuộc tấn công giả mạo (phishing). <!–

Two-factor authentication

Two-factor authentication (2FA) requires you to use a passphrase (“something you know”) along with a 2FA authenticator (like a YubiKey, “something you have”) in order to protect against stolen passwords and phishing attacks. –>

Mã hóa ổ cứng

Mã hóa toàn bộ ổ đĩa của máy tính của bạn là một cách bảo vệ thông tin của bạn dễ dàng trong trường hợp bị mất cắp. Bạn có thể dùng cryptsetup + LUKS trên Linux, BitLocker trên Windows, hoặc FileVault trên macOS. Những trình này sẽ mã hóa nguyên ổ đĩa bằng mật mã đối xứng với chìa khóa được bảo vệ bằng mật khẩu của bạn. <!–

Full disk encryption

Keeping your laptop’s entire disk encrypted is an easy way to protect your data in the case that your laptop is stolen. You can use cryptsetup + LUKS on Linux, BitLocker on Windows, or FileVault on macOS. This encrypts the entire disk with a symmetric cipher, with a key protected by a passphrase. –>

Tin nhắn bảo mật

Dùng Signal hay Keybase. Đây là những chương trình được bảo mật theo qui trình đầu cuối (end-to-end) bằng phương pháp mã hóa bất đối xứng. Tuy nhiên việc lấy chìa khóa chung từ đối tác của bạn là cái đáng nói ở đây. Nếu bạn muốn bảo mật tốt, bạn cần xác thực chìa khóa chung của đối tác ngoài luồng trao đổi ngoài đời thực (với Signal hay Keybase), hoặc phải tin tưởng bằng chứng minh xã hội (social proofs - với Keybase). <!–

Private messaging

Use Signal or Keybase. End-to-end security is bootstrapped from asymmetric-key encryption. Obtaining your contacts’ public keys is the critical step here. If you want good security, you need to authenticate public keys out-of-band (with Signal or Keybase), or trust social proofs (with Keybase). –>

SSH

Chúng tôi đã có bài học về SSH và chìa khóa trong SSH ở một bài học trước. Bây giờ hãy phân tích về mặt mật mã học của vấn đề này.

Khi bạn chạy trình ssh-keygen, nó sẽ tạo một cặp khóa bất đối xứng, public_key, private_key. Chúng được tạo lập một cách hoàn toàn ngẫu nhiên, bằng entropy được cung cấp từ hệ điều hành (từ nhũng hoạt động phần cứng, v.v.). Chìa khóa chung thì được lưu giữ nguyên vẹn vì nó không cần phải bí mật. Còn chìa khóa riêng thì cần được bảo mật trên ổ cứng của bạn. Vì vậy ssh-keygen sẽ đòi hỏi người dùng cung cấp một mật khẩu và dùng nó để tạo một chìa khóa mới dùng để mã hóa chìa khóa riêng bằng bảo mật đối xứng.

Trong thực tế, một khi máy chủ biết chìa khóa chung của máy người dùng (được lưu giữ trong .ssh/authorized_keys), máy người dùng kết nối có thể chứng minh danh tính bằng chữ kí bất đối xứng. Việc này được thực hiện qua quy trình thách đố-chứng minh (challenge-respone) . Quy trình này được hiểu khái quát là khi máy chủ gửi một số ngẫu nhiên đến máy đầu cuối của người dùng. Máy này sẽ kí tin nhắn và gửi lại máy chủ, nơi kiểm chứng chữ kí với các chìa khóa chung mà nó lưu giữ sẽ được diễn ra. Nếu thành công, việc này sẽ chứng minh rằng máy đẩu cuối đang nắm giữ chìa khóa riêng thuộc cùng cặp với chìa khóa chung mà máy chủ đang lưu giữ trong file .ssh/authorized_keys của máy chủ. Kết quả là máy chủ SSH chấp thuận cho máy người dùng đăng nhập vào.

Một vài thông tin hữu dụng

Bài tập

  1. Entropy
    1. Cho mật khẩu được cấu thành từ 4 từ viết thường trong từ điển Anh Ngữ. Biết rằng mỗi từ được lựa một cách ngẫu, đều nhau từ từ điển 100,000 từ. Ví dụ là “correcthorsebatterystaple`. Entropy của mật khẩu này là bao nhiêu bits?
    2. Cho một cách chọn mật khẩu khác trên: tạo mật khẩu dài 8 kí tự (cả hoa cả thường). Ví dụ như rg8Ql34g. Mật khẩu này có entropy là bao nhiêu?
    3. Trong hai mật khẩu trên, cái nào bảo mật hơn?
    4. Nếu hacker có thể đoán được 10,000 mật khẩu mỗi giây, sẽ mất bao lâu để đoán được các mật khẩu trên?
  2. Hàm băm mật mã: Tải file hình của Debian từ một link phụ (ví dụ từ máy chủ Argentina) Kiểm chứng kết quả hàm băm (từ câu lệnh sha256sum) với kết quả băm được đăng trên trang chủ chính thức của Debian (file này được lưu giữ trên debian.org, nếu bạn đã tải file trên đường link phụ của Argentina).

  3. Mật mã đối xứng Mã hóa một file bằng AES qua câu lệnh OpenSSL: openssl aes-256-cbc -salt -in {input filename} -out {output filename}. Hãy xem nội dung file mã hóa bằng cat hay hexdump. Sau đó giải mã file bằng openssl aes-256-cbc -d -in {input filename} -out {output filename} và kiểm tra xem nội dung trước khi mã hóa và sau giải mã là giống nhau (bằng câu lệnh cmp).

  4. Mật mã bất đối xứng
    1. Hãy cài đặt chìa khóa SSH trên một máy tính mà bạn có thể đăng nhập được. Hãy chắc chắn rằng chìa khóa riêng của bạn được mã hóa bằng một mật khẩu.
    2. Cài đặt GPG
    3. Gửi Anish một thư điện tử bảo mật qua chìa khóa chung
    4. Kí một commit trong Git với git commit -S hay tạo một Git tag với chữ kí bằng git tag -s. Xác thực chữ kí này trên commit bằng git show --show-signature hoặc trên tag bằng git tag -v.

Edit this page.

Licensed under CC BY-NC-SA.