2010-07-12 24 views
10

Bir web uygulaması, kullanıcıların hassas verilerini içerir. Ne web uygulamasının operatörü ne de barındırma sağlayıcısı bu verileri görebilmelidir. Bu yüzden bu verileri kullanıcıların giriş şifresiyle şifrelenmiş halde saklamak istedim. Şifrenin genellikle sadece karma değeri web uygulaması tarafından saklandığından, uygulama eski, unutulmuş şifreyi gönderilemez: şifre kurtarma için normal kullanım durumunda uygulamak ancak mümkün değildir Bu strateji ileHassas verilerin korunması için kodlama stratejisi

dataInDB = encrypt (rawData, user password) 

kullanıcıya Ve yeni, rastlantısal bir parolanın atanmasıyla, DB'deki şifrelenmiş veriler artık okunamaz durumdadır.

başka bir çözüm var mı?

+1

+1: Harika bir soru. Ne kadar berbat bir durum ... –

cevap

7

Muhtemel bir çözüm (Ben herhangi bir yıkım sorumlu değilim):

hassas verileri şifreleyerek, anahtar olarak kullanıcının şifresini kullanmayın. Daha doğrusu, , kullanıcının şifresinden anahtarı (tercihen PBKDF2 gibi standart bir algoritma kullanarak) türetmektedir. Sadece kullanıcının şifresini unutması durumunda, bu türetilmiş anahtarın bir kopyasını (kullanıcının yanıtı'dan türetilen farklı bir anahtar kullanılarak şifrelenmiş halde) saklayabilirsiniz. Kullanıcı şifresini unutursa, güvenlik sorularına cevap verebilirler. Sadece doğru cevap numaralı şifreyi (orijinal şifreyi değil) şifresini çözecektir. Bu size hassas bilgileri yeniden şifrelemek için fırsat verir.

(Python-esque) sözde kodunu kullanarak göstereceğim, ancak önce kullanıcılar için olası bir tabloya bakalım. Bir kullanıcı kaydı zamanı geldiğinde henüz sütunlarda yakalanmak, onlar ...

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 
) 

yakında belli olacak etmeyin, onlar bir sorum sağlamak ve cevap vermek zorundadır:

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) 

Kullanıcı parolasını unutursa, sistemden kullanıcıdan güvenlik sorusunu yanıtlamasını istemek zorunda kalır. Onların şifresi kurtarılamaz, ancak şifreden türetilen anahtarı olabilir.

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) 

Tabii ki, (... vb şifreleme modları) açıkça burada vurgulanan değil bazı genel kriptografik ilkeler vardır şunlardır: Bu sistem yeni şifresini kullanarak hassas bilgileri yeniden şifrelemek sağlar Uygulayıcıların kendilerini tanıması için sorumluluk.

Bu biraz yardımcı olur umarız! :) Eadwacer olarak Eadwacer yorumuyla

ait

Güncelleme nezaket yorumladı:

Ben tüm-şifreleyerek yeniden gerektirecektir şifreyi şifre (belirli entropi doğrudan anahtarı türetmek ve değişen önleyeceğini

veri). Bunun yerine, her kullanıcı için rastgele bir anahtar oluşturun ve anahtarı şifrelemek için şifreyi kullanın. Ayrıca, güvenlik sorularından türetilen bir anahtar kullanarak anahtarı şifreleyebilirsiniz.Bir kullanıcının şifresini sıfırlama,

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) 

Şimdi: Bundan sonra aşağıdaki üyeyi beyan ederim

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, 
) 

: Burada

dikkate onun mükemmel tavsiye almak benim çözümün değiştirilmiş versiyonu şunun gibi görünüyor:

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) 

Umarım başım hala bu gece açıkça işliyor ...

+0

Teşekkür ederim Adam, tam da aradığım şey bu. Java Crypto API'sini kullanarak bu çözümü Java'da önümüzdeki günlerde uygulamaya çalışacağım ve sonucu burada yayınlayacağım. – Dominik

+0

Şimdiye kadar benim için bir şey açık değil: Webapp'ın normal kullanım durumu için (giriş ve şifreli kullanıcı verilerine bakın) kullanıcı güvenlik sorusunu yanıtlamamalıdır. Doğru olan, hassas verileri şifrelemek için kullanılan şifre gizli anahtarının, bu anahtarın ilk oluşturulmasında olduğu gibi çıkarılması gerektiğidir. Ve aynı anahtarı çoğaltmak için, tekrarlar ve tuz Db içinde de saklanır. – Dominik

+0

@Dominik: Doğru, bu yüzden veritabanında yinelemeleri ve tuzları saklıyoruz. –