views:

94

answers:

2

Hello!

I am trying to figure out how to create an optimal solution for my project. I made this simple picture in Photoshop to try to illustrate the problem and how i want it (if possible).

Illustrative image

Ill also try to explain it based on the picture. First off we have a couple of objects to the left, these objects all get encrypted with their own encryption key (EKey on the picture) and then stored in the database. On the other side we have different users placed into roles (one user can be in a lot of roles) and the roles are associated with different objects. So one person only has access the to the objects that the role provides. So for instance Role A might have access to Object A and B. Role B have access only to Object C and Role C have access to all objects. Nothing strange in that, right? Different roles have different objects that they can access.

Now to the problem part.

Each user has to login with his/her username/password and then he/she gets access to the objects that his/her roles provide. All the objects are encrypted so she needs to get a decryption key somehow. I don't want to store the encryption key as a text string on the server. It should be, if possible, decrypted using the users password (along with the role) or similar. That way you have to be a user on the server in order to decrypt an object an to work with it.

I was thinking about making a public/private key encryption system, but i am kinda stuck on how to give the different users the decryption key to the objects. Since i need to be able to move users to and from roles, add new users, add new roles and create/delete objects.

There will be one administrator that then adds some data to allow the users in that role to get the decryption key to decrypt the object.

Nothing is static and i am trying to get a picture of how this can be built or if there is a far better solution.

The only criteria are:

-Encrypted objects.

-Decryption key should not be stored as text.

-Different users have access to different objects.

-Does NOT have to have roles.

A: 

It sounds like you are trying to implement access restrictions through encryption of each class of resource with a different key, correct?

There doesn't seem to be a good way to implement the scheme as you describe it. Consider having the resources encrypted by a single key. You would necessarily need to expose the decrypt key to users, but if their roles change there is no way to revoke access without re-encrypting the objects with a new key, which may invalidate other users keys (not necessarily). Another, approach would be to have each user have a public key, and each resource would be encrypted against the public keys of all users with access. But objects would have to be re-encrypted to add or remove access. Your approach is only viable if role changes are rare and you don't mind re-encrypting to enforce access restrictions.

You could consider decoupling storage encryption and protected access. A database can be encrypted in total, and the server could prompt for the key at startup (no storage). The type of access control depends what your middle layer looks like, it sounds your administrator could change roles by adding and removing database privileges (Could you elaborate on what kind of component 'Login' is? OS, DB, or custom server software login?). To transmit objects securely to remote users, use an SSH tunnel or SSL connection. In this approach, objects are encrypted on disc and during transmission and roles can be freely changed without having to re-encrypt.

academicRobot
+1  A: 

This is possible by using the SQL Server cryptographic infrastructure. You encrypt each object (A, B, C, D) with its own symmetric key (data is always encrypted with a symmetric key, never with an asymmetric one). Each role has an asymmetric key, or a certificate, so there are asymmetric keys A, B and C. The role asymmetric key(s) are encrypted with the role's password. Each symmetric key is encrypted by the asymmetric keys of the roles that have acces to it (symmetric keys can be encrypted multiple times). When a user enters the system, it opens the symmetric key(s) of its role, using the role specific certificate/assymetric key. This places the symmetric keys in the current user's keychain, giving access to the objects encrypted with these keys.

Here is a code demo:

: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

Is this a smart think to do though? No. Encryption is never the answer to address access rights problems. You obviously don't understand key management and provisioning, and you'll make a useless pseudo-secure mess. Sorry to rain on your parade, but is necessary.

Remus Rusanu