2010-07-12 18 views
10

एक वेब एप्लिकेशन में उपयोगकर्ताओं का संवेदनशील डेटा होता है। न तो वेब एप्लिकेशन का ऑपरेटर और न ही होस्टिंग प्रदाता इस डेटा को देखने में सक्षम होना चाहिए। इसलिए मैं इन डेटा को उपयोगकर्ताओं के प्रवेश पासवर्ड से एन्क्रिप्टेड डीबी में स्टोर करना चाहता था। चूंकि पासवर्ड की आमतौर पर केवल हैश मान वेब एप्लिकेशन द्वारा संग्रहीत किया जाता है, आवेदन वर्ष, भूले हुए पासवर्ड नहीं भेज सकते हैं:कोडिंग रणनीति

dataInDB = encrypt (rawData, user password) 
इस रणनीति यह तथापि संभव नहीं है पासवर्ड रिकवरी के लिए हमेशा की तरह उपयोग के मामले को लागू करने के साथ

उपयोगकर्ता को और एक नए, संयोग पासवर्ड के असाइनमेंट के साथ डीबी में एन्क्रिप्टेड डेटा अब पठनीय नहीं है।

क्या कोई अन्य समाधान है?

+1

+1: बढ़िया सवाल। क्या एक भयानक स्थिति में होना है ... –

उत्तर

7

सम्भावित समाधान (मैं किसी भी विनाश के लिए जिम्मेदार नहीं हूँ):

जब संवेदनशील डेटा को एन्क्रिप्ट करने, कुंजी के रूप में उपयोगकर्ता का पासवर्ड का उपयोग नहीं करते। बल्कि, (अधिमानतः ऐसे PBKDF2 के रूप में एक मानक एल्गोरिथ्म का उपयोग) उपयोगकर्ता का पासवर्ड से कुंजी को प्राप्त। शायद ज़रुरत पड़े उपयोगकर्ता अपना पासवर्ड भूल जाता है, तो आप इस व्युत्पन्न कुंजी (उपयोगकर्ता के जवाब से ली गई एक अलग कुंजी का उपयोग करके एन्क्रिप्ट) की एक प्रति रख सकते हैं। यदि उपयोगकर्ता अपना पासवर्ड भूल जाता है, तो वे अपने सुरक्षा प्रश्न का उत्तर दे सकते हैं। केवल सही उत्तर मूल पासवर्ड कुंजी (मूल पासवर्ड नहीं) को डिक्रिप्ट करेगा। यह आपको संवेदनशील जानकारी को फिर से एन्क्रिप्ट करने का अवसर प्रदान करता है।

मैं (अजगर-esque) छद्म कोड का उपयोग कर प्रदर्शन करेंगे, लेकिन पहले के उपयोगकर्ताओं के लिए एक संभव तालिका को देखो। मत स्तंभों में बस अभी तक पकड़े, वे जल्द ही स्पष्ट हो जाएगा ...

CREATE TABLE USERS 
(
    user_name    VARCHAR, 

    -- ... lots of other, useful columns ... 

    password_key_iterations NUMBER, 
    password_key_salt  BINARY, 
    password_key_iv   BINARY, 
    encrypted_password_key BINARY, 
    question    VARCHAR, 
    answer_key_iterations NUMBER, 
    answer_key_salt   BINARY 
) 

जब यह एक उपयोगकर्ता रजिस्टर करने के लिए समय आता है, वे एक प्रश्न और उत्तर प्रदान करना होगा:

def register_user(user_name, password, question, answer): 
    user = User() 

    # The question is simply stored for later use 
    user.question = question 

    # The password secret key is derived from the user's password 
    user.password_key_iterations = generate_random_number(from=1000, to=2000) 
    user.password_key_salt = generate_random_salt() 
    password_key = derive_key(password, iterations=user.password_key_iterations, salt=user.password_key_salt) 

    # The answer secret key is derived from the answer to the user's security question 
    user.answer_key_iterations = generate_random_number(from=1000, to=2000) 
    user.answer_key_salt = generate_random_salt() 
    answer_key = derive_key(answer, iterations=user.answer_key_iterations, salt=user.answer_key_salt) 

    # The password secret key is encrypted using the key derived from the answer 
    user.password_key_iv = generate_random_iv() 
    user.encrypted_password_key = encrypt(password_key, key=answer_key, iv=user.password_key_iv) 

    database.insert_user(user) 

क्या उपयोगकर्ता अपना पासवर्ड भूल जाना चाहिए, सिस्टम को अभी भी उपयोगकर्ता को अपने सुरक्षा प्रश्न का उत्तर देने के लिए कहा होगा। उनके पासवर्ड बरामद नहीं किया जा सकता है, लेकिन कुंजी पासवर्ड से प्राप्त हो सकता है।

def reset_password(user_name, answer, new_password): 
    user = database.rerieve_user(user_name) 

    answer_key = derive_key(answer, iterations=user.answer_key_iterations, salt=user.answer_key_salt) 

    # The answer key decrypts the old password key 
    old_password_key = decrypt(user.encrypted_password_key, key=answer_key, iv=user.password_key_iv) 

    # TODO: Decrypt sensitive data using the old password key 

    new_password_key = derive_key(new_password, iterations=user.password_key_iterations, salt=user.password_key_salt) 

    # TODO: Re-encrypt sensitive data using the new password key 

    user.encrypted_password_key = encrypt(new_password_key, key=user.answer_key, iv=user.password_key_iv) 

    database.update_user(user) 

बेशक, कुछ सामान्य क्रिप्टोग्राफिक सिद्धांतों को स्पष्ट रूप से यहाँ पर प्रकाश डाला नहीं (सिफर मोड, आदि ...) हैं कि कर रहे हैं: इस प्रणाली के संवेदनशील जानकारी नई पासवर्ड का उपयोग कर फिर से एन्क्रिप्ट करने के लिए अनुमति देता है खुद को परिचित करने के लिए कार्यान्वयन की ज़िम्मेदारी।

आशा है कि यह एक छोटी सी मदद करता है! :) Eadwacer की टिप्पणी

Eadwacer के रूप में की

अद्यतन शिष्टाचार टिप्पणी की:

मैं पासवर्ड (सीमित एन्ट्रापी से सीधे कुंजी पाने और पासवर्ड बदलने के सभी फिर से एन्क्रिप्ट करने की आवश्यकता होगी से बच जाएंगे डेटा)। इसके बजाय, प्रत्येक उपयोगकर्ता के लिए एक यादृच्छिक कुंजी बनाएं और कुंजी को एन्क्रिप्ट करने के लिए पासवर्ड का उपयोग करें। आप सुरक्षा प्रश्नों से प्राप्त कुंजी का उपयोग करके कुंजी को एन्क्रिप्ट भी करेंगे।,

def register_user(user_name, password, question, answer): 
    user = User() 

    # The question is simply stored for later use 
    user.question = question 

    # The randomly-generated data key will ultimately encrypt our sensitive data 
    data_key = generate_random_key() 

    # The password key is derived from the password 
    user.password_key_iterations = generate_random_number(from=1000, to=2000) 
    user.password_key_salt = generate_random_salt() 
    password_key = derive_key(password, iterations=user.password_key_iterations, salt=user.password_key_salt) 

    # The answer key is derived from the answer 
    user.answer_key_iterations = generate_random_number(from=1000, to=2000) 
    user.answer_key_salt = generate_random_salt() 
    answer_key = derive_key(answer, iterations=user.answer_key_iterations, salt=user.answer_key_salt) 

    # The data key is encrypted using the password key 
    user.password_encrypted_data_key_iv = generate_random_iv() 
    user.password_encrypted_data_key = encrypt(data_key, key=password_key, iv=user.password_encrypted_data_key_iv) 

    # The data key is encrypted using the answer key 
    user.answer_encrypted_data_key_iv = generate_random_iv() 
    user.answer_encrypted_data_key = encrypt(data_key, key=answer_key, iv=user.answer_encrypted_data_key_iv) 

    database.insert_user(user) 

अब एक उपयोगकर्ता के पासवर्ड को रीसेट:

CREATE TABLE USERS 
(
    user_name      VARCHAR, 

    -- ... lots of other, useful columns ... 

    password_key_iterations  NUMBER, 
    password_key_salt    BINARY, 
    password_encrypted_data_key BINARY, 
    password_encrypted_data_key_iv BINARY, 
    question      VARCHAR, 
    answer_key_iterations   NUMBER, 
    answer_key_salt    BINARY, 
    answer_encrypted_data_key  BINARY, 
    answer_encrypted_data_key_iv BINARY, 
) 

फिर आप उपयोगकर्ता रजिस्टर देंगी:

यहाँ मेरी समाधान को ध्यान में उनकी उत्कृष्ट सलाह लेने का एक संशोधित संस्करण है ऐसा लगता है:

def reset_password(user_name, answer, new_password): 
    user = database.rerieve_user(user_name) 

    answer_key = derive_key(answer, iterations=user.answer_key_iterations, salt=user.answer_key_salt) 

    # The answer key decrypts the data key 
    data_key = decrypt(user.answer_encrypted_data_key, key=answer_key, iv=user.answer_encrypted_data_key_iv) 

    # Instead of re-encrypting all the sensitive data, we simply re-encrypt the password key 
    new_password_key = derive_key(new_password, iterations=user.password_key_iterations, salt=user.password_key_salt) 

    user.password_encrypted_data_key = encrypt(data_key, key=new_password_key, iv=user.password_encrypted_data_key_iv) 

    database.update_user(user) 

उम्मीद है कि मेरा सिर अभी भी आज रात स्पष्ट रूप से काम कर रहा है ...

+0

धन्यवाद एडम, यह वही है जो मैं ढूंढ रहा हूं। मैं Java Crypto API का उपयोग कर जावा में अगले दिनों के भीतर इस समाधान को लागू करने का प्रयास करूंगा और परिणाम यहां पोस्ट करूंगा। – Dominik

+0

अब तक मेरे लिए एक बात स्पष्ट नहीं है: वेबपैप के सामान्य उपयोग के मामले के लिए (लॉगिन और -डेकिप्टेड-उपयोगकर्ता डेटा देखें) उपयोगकर्ता को सुरक्षा प्रश्न का उत्तर नहीं देना चाहिए। क्या यह सही है, पासवर्ड गुप्त कुंजी, जिसे संवेदनशील डेटा एन्क्रिप्ट करने के लिए प्रयोग किया जाता है, को उसी कुंजी के प्रारंभिक निर्माण के लिए उसी तरह से निकाला जाना चाहिए। और उसी कुंजी को पुन: उत्पन्न करने के लिए, डीबी के भीतर पुनरावृत्तियों और नमक भी संग्रहीत किए जाते हैं। – Dominik

+0

@ डोमिनिक: आप सही हैं, इसलिए हम डेटाबेस में पुनरावृत्तियों और नमक को स्टोर करते हैं। –

संबंधित मुद्दे