如何构建允许多个用户/对象的加密系统

时间:2010-05-16 17:03:57

标签: c# sql sql-server encryption

我正在试图找出如何为我的项目创建最佳解决方案。我在Photoshop中制作了这张简单的图片,试图说明问题以及我想要的方式(如果可能的话)。

Illustrative image

我也试着根据图片来解释它。 首先,我们左边有几个对象,这些对象都使用自己的加密密钥(图片上的EKey)加密,然后存储在数据库中。另一方面,我们将不同的用户置于角色中(一个用户可以处于很多角色中),并且角色与不同的对象相关联。因此,一个人只能访问角色提供的对象。因此,例如,角色A可以访问对象A和B.角色B只能访问对象C,角色C可以访问所有对象。 没什么奇怪的,对吧?不同的角色具有可以访问的不同对象。

现在问题部分。

每个用户必须使用他/她的用户名/密码登录,然后他/她才能访问他/她的角色提供的对象。所有对象都是加密的,所以她需要以某种方式获得解密密钥。我不想将加密密钥存储为服务器上的文本字符串。如果可能,应该使用用户密码(以及角色)或类似密码进行解密。这样,您必须是服务器上的用户才能解密对象并使用它。

我正在考虑建立一个公钥/私钥加密系统,但我仍然坚持如何为不同的用户提供对象的解密密钥。因为我需要能够将用户移入和移出角色,所以添加新用户,添加新角色以及创建/删除对象。

然后会有一个管理员添加一些数据,以允许该角色的用户获取解密密钥来解密对象。

没有什么是静态的,我试图了解如何构建它或者是否有更好的解决方案。

唯一的标准是:

- 加密对象。

- 解密密钥不应存储为文本。

- 不同的用户可以访问不同的对象。

- 不必担任角色。

2 个答案:

答案 0 :(得分:3)

这可以通过使用SQL Server加密基础结构来实现。您使用自己的对称密钥加密每个对象(A,B,C,D)(数据始终使用对称密钥加密,绝不使用非对称密钥加密)。每个角色都有一个非对称密钥或证书,因此存在非对称密钥A,B和C.角色非对称密钥使用角色的密码加密。每个对称密钥由访问它的角色的非对称密钥加密(对称密钥可以多次加密)。当用户进入系统时,它使用角色特定证书/不对称密钥打开其角色的对称密钥。这会将对称密钥放在当前用户的密钥链中,从而可以访问使用这些密钥加密的对象。

这是一个代码演示:

:setvar server .
:setvar dbname cryptdemo

:connect $(server)
use master;

if db_id('$(dbname)') is not null
    drop database [$(dbname)];

create database [$(dbname)];    
go

:connect $(server)
use [$(dbname)];
go 
create certificate RoleA 
encryption by password = '123!#Password'
with subject = 'RoleA'

create certificate RoleB 
encryption by password = '213!#Password'
with subject = 'RoleB'

create certificate RoleC 
encryption by password = '312!#Password'
with subject = 'RoleC'
go

:connect $(server)
use [$(dbname)];
go 
-- Role A has access to Object A and Object B
create symmetric key ObjectA WITH ALGORITHM = AES_256
encryption by certificate RoleA;
create symmetric key ObjectB WITH ALGORITHM = AES_256
encryption by certificate RoleA;
go

:connect $(server)
use [$(dbname)];
go 
-- Role B has access to Object C
create symmetric key ObjectC WITH ALGORITHM = AES_256
encryption by certificate Roleb;
go

:connect $(server)
use [$(dbname)];
go 
-- Role C has access to Objects A, B and C
open symmetric key ObjectA
decryption by certificate RoleA with password = '123!#Password'
alter symmetric key ObjectA 
add encryption by certificate RoleC;

open symmetric key ObjectB
decryption by certificate RoleA with password = '123!#Password'
alter symmetric key ObjectB
add encryption by certificate RoleC;

open symmetric key ObjectC
decryption by certificate RoleB with password = '213!#Password'
alter symmetric key ObjectC
add encryption by certificate RoleC;
go

:connect $(server)
use [$(dbname)];
go 
create table Objects (
    id int not null identity(1,1) primary key, 
    data varbinary(max));
go

:connect $(server)
use [$(dbname)];
go 
-- Role A inserts an Object A and an Object B:
open symmetric key ObjectA
decryption by certificate RoleA with password = '123!#Password'
open symmetric key ObjectB
decryption by certificate RoleA with password = '123!#Password'

insert into Objects (data) values (encryptbykey(Key_GUID('ObjectA'), 'Object A inserted by Role A'));
insert into Objects (data) values (encryptbykey(Key_GUID('ObjectB'), 'Object B inserted by Role A'));
go

:connect $(server)
use [$(dbname)];
go 
-- Role B inserts an Object C
open symmetric key ObjectC
decryption by certificate RoleB with password = '213!#Password'

insert into Objects (data) values (encryptbykey(Key_GUID('ObjectC'), 'Object C inserted by Role B'));
go

:connect $(server)
use [$(dbname)];
go 
-- Role C inserts objects A, B, C
open symmetric key ObjectA
decryption by certificate RoleC with password = '312!#Password'
open symmetric key ObjectB
decryption by certificate RoleC with password = '312!#Password'
open symmetric key ObjectC
decryption by certificate RoleC with password = '312!#Password'

insert into Objects (data) values (encryptbykey(Key_GUID('ObjectA'), 'Object A inserted by Role C'));
insert into Objects (data) values (encryptbykey(Key_GUID('ObjectB'), 'Object B inserted by Role C'));
insert into Objects (data) values (encryptbykey(Key_GUID('ObjectC'), 'Object C inserted by Role C'));
go

:connect $(server)
use [$(dbname)];
go 
-- Role A can see Objects A and B:
open symmetric key ObjectA
decryption by certificate RoleA with password = '123!#Password'
open symmetric key ObjectB
decryption by certificate RoleA with password = '123!#Password'

select id, data, cast(decryptbykey(data) as varchar(max)) as decrypted from Objects ;
go

:connect $(server)
use [$(dbname)];
go 
-- Role B can see Object C
open symmetric key ObjectC
decryption by certificate RoleB with password = '213!#Password'

select id, data, cast(decryptbykey(data) as varchar(max)) as decrypted from Objects ;
go


:connect $(server)
use [$(dbname)];
go 
-- Role C can see Objects A, B and C
open symmetric key ObjectA
decryption by certificate RoleC with password = '312!#Password'
open symmetric key ObjectB
decryption by certificate RoleC with password = '312!#Password'
open symmetric key ObjectC
decryption by certificate RoleC with password = '312!#Password'

select id, data, cast(decryptbykey(data) as varchar(max)) as decrypted from Objects ;
go

这是一个聪明的想法吗?否。加密永远解决访问权限问题的答案。你显然不了解密钥管理和配置,你会做一个无用的伪安全混乱。对不起,你的游行会下雨,但这是必要的。

答案 1 :(得分:1)

听起来您正试图通过使用不同的密钥加密每类资源来实现访问限制,对吗?

在描述它时似乎没有一种好方法来实现该方案。考虑使用单个密钥加密资源。您可能需要向用户公开解密密钥,但如果他们的角色发生更改,则无法在不使用新密钥重新加密对象的情况下撤消访问权限,这可能会使其他用户密钥失效(不一定)。另一种方法是让每个用户拥有一个公钥,并且每个资源都将根据具有访问权限的所有用户的公钥进行加密。但是必须重新加密对象才能添加或删除访问权限。只有在角色更改很少且您不介意重新加密以强制执行访问限制时,您的方法才可行。

您可以考虑将存储加密与受保护的访问分离。数据库可以在total中加密,服务器可以在启动时提示输入密钥(无存储)。访问控制的类型取决于您的中间层的样子,听起来您的管理员可以通过添加和删除数据库权限来更改角色(您能详细说明“登录”是什么类型的组件?操作系统,数据库或自定义服务器软件登录? )。要将对象安全地传输给远程用户,请使用SSH隧道或SSL连接。在这种方法中,对象在光盘上加密,在传输过程中,角色可以自由更改,无需重新加密。