Tra*_*PUK 7 .net c# database encryption wpf
我有一个访问数据库的内部WPF客户端应用程序.
该应用程序是支持团队的核心资源,因此包括客户端的远程访问/登录信息.目前这个数据库不能通过网络界面等获得,但有一天很可能.
远程访问信息包括客户端网络的用户名和密码,以便我们可以远程支持客户的软件应用程序.我需要将用户名和密码存储在数据库中,并为支持顾问提供访问权限,以便他们可以登录客户端系统然后提供支持.希望这是有道理的.
所以困境是我不想在数据库中以明文形式存储用户名和密码,以确保如果数据库遭到入侵,我就不会向任何获取数据库的人提供访问我们客户端网络的权限.
我已经看过密码的双向加密,但正如他们所说,双向与明文没有太大的不同,就好像你可以解密它一样,攻击者也可以......最终.这里的问题是我已经设置了一个方法来使用存储在应用程序中的salt和密码,我使用了存储在db中的salt,但都有它们的弱点,即如果应用程序被反映它暴露了盐等
如何保护我的数据库中的用户名和密码,但仍然能够让我的支持顾问查看应用程序中的信息,以便他们可以使用它来登录?
这显然与存储用户密码不同,因为这是一种方式,因为我不需要知道它们是什么.但我确实需要知道客户端的远程访问密码是什么,因为我们需要在远程访问密码时输入密码.
任何人都有一些关于什么是最好的方法的理论?
更新 我正在尝试构建的功能是我们的CRM应用程序,它将存储客户端的远程访问详细信息.CRM系统提供呼叫/问题跟踪功能,在调查问题的过程中,支持顾问需要远程访问.然后,他们将查看客户端的远程访问详细信息并建立连接
有几种方法可以做到这一点; 最佳解决方案将取决于您的支持团队如何访问客户端站点,支持团队中有多少成员以及应用程序的体系结构.
做这样的事情的最好方法是使用像Kerberos这样的东西.这样,支持团队的成员就不必被委托给客户的密码 - 他们可以写下来的密码,以后用来攻击客户.支持团队可以立即撤销成员的访问权限,而无需客户采取任何行动.
但是,我猜这是一个更危险的系统,团队成员通过远程桌面,SSH或其他类似方式获取密码来访问客户端系统.在这种情况下,当向团队成员透露客户密码时,会承担很大的责任.
就个人而言,我不会接受这种风险.并不是说我不相信我的团队,更重要的是我不能相信我的客户.如果在他们的网站上发生了某些事情(或者即使他们只是假装发生了某些事情),突然之间我就是一个嫌疑人.我宁愿设计一个系统,没有人可以访问单独行动的客户系统.这可以保护客户免受我团队中的坏苹果的侵害,并保护我免受诬告.
无论如何,一种方法是为每个团队成员生成密钥.这些可能是基于密码的对称加密密钥,但是必须集中保存一些密钥.更好的是使用像RSA这样的非对称算法.然后只集中保存团队成员的公钥.
从客户端收到新密码时,使用需要副本的每个团队成员的公钥对其进行加密.此加密密码可以存储在数据库中,并在每次请求时提供给团队成员,也可以主动推送给团队成员以供他们存储.在任何一种情况下,当需要时,密码用团队成员持有的私钥解密(在用他们选择的密码加密的密钥存储区中).
这有不利之处.重申上述观点,团队成员可以访问客户端密码.他们值得信任吗?如果客户端存在与此系统无关的安全漏洞,但又想将责任归咎于某人,该怎么办?其次,虽然服务器上没有存储解密密钥,但仍需要为每个团队成员的公钥建立信任.否则,攻击者可能会将自己的流氓公钥放入集合中并接收可以解密的密码.
我们公司也出现类似的情况,数据库管理员希望在他们之间维护一个凭据池。
我原本打算发布这个想法,但埃里克森抢先了我。然而,发布一些伪代码来详细说明可能是值得的,所以我想我回答问题的时间并没有完全浪费......
你需要的东西:
首先,让我们设置数据库模式。这些表将很快被演示。
CREATE TABLE users (
user_id INTEGER,
authentication_hash BINARY,
authentication_salt BINARY,
public_key BINARY,
encrypted_private_key BINARY,
decryption_key_salt BINARY,
PRIMARY KEY(user_id)
)
CREATE TABLE secrets (
secret_id INTEGER,
-- WHATEVER COLUMNS YOU REQUIRE TO ACCURATELY MODEL YOUR PASSWORDS (CLIENT INFO, ETC)
PRIMARY KEY(secret_id)
)
CREATE TABLE granted_secrets (
secret_id INTEGER,
recipient_id INTEGER,
encrypted_data BINARY,
PRIMARY KEY(secret_id, recipient_id),
FOREIGN KEY(secret_id) REFERENCES secrets(secret_id)
FOREIGN KEY(recipient_id) REFERENCES users(user_id)
)
Run Code Online (Sandbox Code Playgroud)
用户必须先注册才能开始使用该系统。
function register_user(user_id, user_password) {
authentication_salt = generate_random_salt()
authentication_hash = hash(authentication_salt, user_password);
(public_key, private_key) = asymmetric_cipher_generate_random_key_pair();
decryption_key_salt = generate_random_salt()
decryption_key = derive_key(decryption_key_salt, user_password)
encrypted_private_key = symmetric_cipher_encrypt(
input => private_key,
key => decryption_key
)
// IMPORTANT: The decryption_key_hash is never stored
execute("INSERT INTO users (user_id, authentication_hash, authentication_salt, public_key, encrypted_private_key, decryption_key_salt) VALUES (:user_id, :authentication_hash, :authentication_salt, :public_key, :encrypted_private_key, :decryption_key_salt)")
}
Run Code Online (Sandbox Code Playgroud)
用户可以登录系统。
function authenticate_user(user_id, user_password)
correct_authentication_hash = query("SELECT authentication_hash FROM users WHERE user_id = :user_id")
authentication_salt = query("SELECT authentication_salt FROM users WHERE user_id = :user_id")
given_authentication_hash = hash(authentication_salt, user_password)
return correct_authentication_hash == given_authentication_hash
Run Code Online (Sandbox Code Playgroud)
然后可以将秘密授予接收用户。
function grant_secret(secret_id, secret_data, recipient_id) {
recipient_public_key = query("SELECT public_key FROM users WHERE user_id = :recipient_id")
encrypted_secret_data = asymmetric_cipher_encrypt(
input => secret_data,
public_key => recipient_public_key
)
execute("INSERT INTO granted_secrets (secret_id, recipient_id, encrypted_data) VALUES (:secret_id, :recipient_id, :encrypted_secret_data)")
}
Run Code Online (Sandbox Code Playgroud)
最后,已被授予访问秘密的用户(接收者)可以检索它。
void retrieve_secret(secret_id, recipient_id, recipient_password)
encrypted_recipient_private_key = query("SELECT encrypted_private_key FROM users WHERE user_id = :recipient_id")
recipient_decryption_key_salt = query("SELECT decryption_key_salt FROM users WHERE user_id = :recipient_id")
recipient_decryption_key = derive_key(recipient_decryption_key_salt, recipient_password)
recipient_private_key = symmetric_cipher_decrypt(
input => encrypted_recipient_private_key,
key => recipient_decryption_key
)
encrypted_secret_data = query("SELECT encrypted_data FROM granted_secrets WHERE secret_id = :secret_id AND recipient_id = :recipient_id")
secret_data = asymmetric_cipher_decrypt(
input => encrypted_secret_data,
private_key => recipient_private_key
)
return secret_data
Run Code Online (Sandbox Code Playgroud)
希望这能有所帮助。它确实帮助我充实了我的想法。