2017-07-21 89 views
6

Tôi muốn lưu trữ một số dữ liệu được mã hóa, ví dụ như trình quản lý mật khẩu, nơi mật khẩu chủ của bạn mở tất cả mật khẩu ứng dụng/trang web cơ bản.Thay đổi mật khẩu chính được sử dụng để mã hóa

Nhìn xung quanh tôi tìm thấy một số ví dụ như this, nhưng chúng dường như sử dụng mật khẩu như một phần của mã hóa, tương tự như một muối trong băm. Điều này có nghĩa là để giải mã bạn cần mật khẩu chính xác, vì vậy bạn không bao giờ có thể thay đổi mật khẩu. Điều này dường như không tuyệt vời từ quan điểm bảo mật/khả năng sử dụng; nếu một PW bị xâm phạm, bạn phải làm lại toàn bộ cơ sở dữ liệu theo một PW khác.

Bạn sẽ tạo một hệ thống nơi bạn có thể thay đổi mật khẩu chính? Bạn có thực hiện kiểm tra đăng nhập đơn giản không và sau đó sử dụng chuỗi để mã hóa/giải mã? Sẽ không phải là bản chất tĩnh cộng với lưu trữ của chuỗi đó là không an toàn?

Tôi biết một số PHP và một smidge của Javascript, vì vậy nếu bạn có ví dụ trong những ngôn ngữ đó sẽ được tốt đẹp, nhưng một lời giải thích cao cấp chung hơn cũng rất nhiều đánh giá cao.

+1

'Đây phương tiện để giải mã bạn cần chính xác như nhau '- vâng, vâng, bạn sẽ giải mã như thế nào nếu không có cùng khóa? Bạn đang theo sau một hệ thống mà bạn có thể có N phím để giải mã cùng một văn bản? Đó là chỉ có thể thực hiện được nếu bạn mã hóa cùng một văn bản N lần với N phím vì vậy nếu một phím bị mất, bạn có N-1 phím để giải mã các công cụ trở lại. Tôi cho rằng nó thực sự là ** tốt cho an ninh bởi vì bạn được cho là chỉ có một chìa khóa. Nếu bạn thay đổi khóa, chỉ cần mã hóa lại mọi thứ bằng khóa đó, vấn đề ở đâu? Mã hóa là một con thú hay thay đổi, chính xác thì bạn đang cố gắng giải quyết vấn đề gì? – Mjh

+0

Trực giác nói rằng bạn có thể sử dụng mật khẩu chủ để mã hóa khóa mã hóa thực sự (giống như bạn bảo vệ bằng mật khẩu khóa SSH riêng tư) nhưng việc mã hóa đúng thực sự khó khăn và trực giác thường được thực hiện (ở đây, rất có khả năng khóa mã hóa thực sự được lưu trữ ở đâu đó là một ý tưởng tồi). Trong mọi trường hợp, tôi đồng ý với Mjh rằng bạn có thể chỉnh sửa câu hỏi và với một số chi tiết cụ thể về lý do tại sao chính xác bạn sợ rằng mã hóa lại mọi thứ không phải là một lựa chọn. Chúng ta đang nói về dữ liệu rất lớn? Bạn có lo lắng về tính toàn vẹn dữ liệu nếu hàng loạt tái mã hóa bị treo? –

Trả lời

1

Bạn có thể sử dụng mã hóa khóa công khai, sử dụng khóa công khai để mã hóa dữ liệu và bằng mật khẩu trong khóa riêng của bạn, có thể thay đổi.

Một giải pháp sẽ là: 1) Tạo phím tư nhân và công cộng rsa (trên Ubuntu):

openssl genrsa -des3 -out private.key 1024 
openssl rsa -in private.key -pubout > public.key 

2) Sử dụng khóa công khai để mã hóa:

$key = file_get_contents('/path/to/public.key'); 
openssl_public_encrypt("password", $encryptedData, $key); 

Lưu $ encryptedData để cơ sở dữ liệu của bạn (bạn không thể sử dụng chuỗi này làm mật khẩu băm để khớp với thông tin đăng nhập, vì $ encryptedData có các bit ngẫu nhiên được thêm trước khi mã hóa, bạn sẽ vẫn cần sử dụng hàm băm cho mật khẩu).

3) Sử dụng khóa riêng để giải mã, cung cấp mật khẩu:

$key = openssl_pkey_get_private(file_get_contents('/path/to/private.key'), $password); 

if($key === false) { 
    // false password 
    die; 
} 
openssl_private_decrypt($encryptedData, $decryptedData, $key); 

4) Thay đổi mật khẩu:

openssl rsa -des3 -in private.key -out private.key 

này cung cấp cho bạn 2 lợi thế:

  • riêng mã hóa & ứng dụng giải mã, mã hóa không yêu cầu khóa cá nhân hoặc mật khẩu.
  • Mật khẩu không cần phải được lưu bên trong ứng dụng.

Điều này sẽ đáp ứng yêu cầu chính của bạn về việc có thể thay đổi mật khẩu và không mã hóa lại dữ liệu.

Nếu bạn muốn bảo mật khóa riêng tư hơn (không cho phép php truy cập trực tiếp vào khóa riêng của bạn, điều này rất hữu ích trong trường hợp ứng dụng của bạn bị tấn công), bạn có thể tạo dịch vụ giải mã trong hệ thống của mình. để gửi dữ liệu được mã hóa bằng mật khẩu và nhận dữ liệu được giải mã.

+0

Để bạn biết, giao thức của bạn ở đây là dễ bị tấn công oracle padding, bởi vì 'openssl_private_decrypt()' mặc định là PKCS1v1.5 padding. –

4

Có một số cách tiếp cận hoạt động. Jannes's answer ám chỉ một giải pháp khả thi (mặc dù hãy cẩn thận với vulnerabilities in openssl_private_decrypt()).

Nếu bạn đang sử dụng Defuse Security's PHP encryption library, các phím được bảo vệ bằng mật khẩu bị trừu tượng.(Hiện nay là một open pull request để giải quyết làm "thay đổi mật khẩu" hoạt động liền mạch và dễ sử dụng.)

Xem thêm: https://github.com/defuse/php-encryption/blob/master/docs/classes/KeyProtectedByPassword.md

Làm thế nào bạn sẽ làm cho một hệ thống nơi bạn có thể thay đổi mật khẩu chủ?

Something như thế này:

  1. Tạo một khóa ngẫu nhiên mạnh mẽ. Chúng tôi sẽ gọi số này là secret.
  2. Lấy một khóa riêng biệt từ mật khẩu chính của người dùng và một muối tĩnh (được tạo ra một lần từ trình tạo số ngẫu nhiên an toàn mã hóa). Chúng tôi sẽ gọi số này passwordKey.
    • Argon2id(password, salt) =>passwordKey
  3. Encrypt secret với passwordKey, sử dụng một chế độ AEAD an toàn với một nonce ngẫu nhiên, và lưu trữ các kết quả cùng với muối.
    • $saved = $salt . $nonce . sodium_crypto_secretbox($secret, $nonce, $passwordKey);
  4. Các dữ liệu thực tế bản thân sẽ được mã hóa với secret, không passwordKey.

Nếu bạn cần thay đổi mật khẩu, chỉ cần lặp lại bước 2 và 3 bằng mật khẩu mới (và một muối khác).

Đối với Argon2id, bạn có thể sử dụng sodium_crypto_pwhash() trên PHP 7.2 trở lên.

-1

Bạn đã từng nghĩ đến việc sử dụng GPG chưa?

http://php.net/manual/en/ref.gnupg.php

Hoặc libsoduim PECL mở rộng

https://pecl.php.net/package/libsodium

Sử dụng thử và thử nghiệm crypto vs cán của riêng bạn sẽ giúp bạn tiết kiệm không chỉ thời gian nhưng bảo vệ tài khoản của bạn như mong muốn

+0

Bất kỳ ai bị giảm giá, vui lòng cung cấp giải thích –

Các vấn đề liên quan