2010-08-24 10 views
10

Estoy buscando aplicar el cifrado de nivel de columna SQL utilizando claves simétricas. Los pasos iniciales necesarios para crear la clave maestra de la base de datos, certificados y claves simétricas parece sencillo y he probado con éxito el cifrado/descifrado de datos utilizando claves simétricas.Columnas SQL cifradas en WHERE Cláusula

Sin embargo, una vez que los datos están encriptados, no sé cuál es la mejor manera de consultarlos. P.ej.

SELECT PlainTextA, PlainTextB, PlainTextC 
WHERE CONVERT(varchar, DECRYPTBYKEY(EncyptedColumn)) = @SearchTerm 

seguramente resultaría en una exploración de tabla completa?

Otra opción que pensé que podría funcionar es encriptar los criterios de búsqueda primero, p. Ej.

SELECT PlainTextA, PlainTextB, PlainTextC 
WHERE EncyptedColumn = ENCRYPTBYKEY(KEY_GUID('KeyName'), @SearchTerm) 

pero esto no funciona, ya que el valor cifrado generado siempre es diferente.

Cualquier sugerencia sería muy apreciada.

Respuesta

10

La forma más típica es la de almacenar tanto el valor cifrado y un hash unidireccional de la valor. Cuando busca un valor específico, debe buscar el hash. De esta manera se puede consultar de manera eficiente, w/o tener que descifrar cada fila con el fin de encontrar el valor que le interesa:

create table Table (
EncryptedColumn varbinary(max), 
HashValue binary(20), 
PlainA int, 
PlainB varchar(256), 
PlainC Datetime); 

create index ndxTableHash on Table(HashValue); 

select PlainA, plainB, PlainC 
from table 
where HashValue = HashBytes('SHA1', @searchTerm); 

En teoría, puede tener un conflicto hash de una vez en una luna azul, ser paranoico-seguro se agrega un doble control de la columna descifrado:

select PlainA, plainB, PlainC 
from table 
where HashValue = HashBytes('SHA1', @searchTerm) 
and DecryptByKey(..., EncryptedColumn) = @searchTerm; 

véase también Indexing encrypted data y SQL Server 2005: searching encrypted data.

+2

Por cierto, la única cosa que no debes hacer ** es salar el hash con un valor específico de fila (PK): estarías exactamente de vuelta en el cuadrado 1, sin saber qué buscar. Para estos escenarios, * puede * eliminar el hash con un * valor global * del sitio. Esto es suficiente para evitar los ataques de tablas del arco iris, pero mantiene los datos explorables. Sin embargo, tenga en cuenta que dos filas distintas con contenido idéntico * tendrán * el mismo hash, por lo que está exponiendo cierta información, pero esta es la definición de tener los datos buscables. –

+0

"Tenga en cuenta que dos filas distintas con contenido idéntico tendrán el mismo hash": esta fue mi principal preocupación con el uso de hash, ya que reduce el nivel de seguridad; sin embargo, la tabla en la que estoy trabajando tendrá de 4 a 5 columnas encriptadas y Solo agrego una columna hash correspondiente para una de esas, entonces puede ser accecible. –

+0

Tenga en cuenta que la colisión hash en la tabla está sujeta al ataque de cumpleaños (meet-in-the-middle) por lo que es significativamente más alta de lo que la intuición lo pondría. Todavía SHA1 tiene un espacio de direcciones bastante grande a 20 bytes. –

2

Una opción que tiene es agregar una nueva columna a la tabla (o tener una vista WITH SCHEMABINDING con una columna calculada en ella, e indexar eso) con un HASH unidireccional del valor de búsqueda. No tiene que ser un hash fuerte - something as simple as CHECKSUM will work. Luego hash el valor de búsqueda en tu búsqueda y lo filtra mediante el hash, que está indexado. De esta forma, puede exponer algo que se pueda buscar e indexar, sin exponer realmente el valor en sí.

Sin embargo, si hay otra manera de hacer esto directamente, me gustaría saber lo que es :)

+0

Gracias por la respuesta y el enlace. ¿Asumo que también sería mejor saltear el valor antes de hash usando la tecla principal como sal? –

+1

No, no querrás perder el valor, a menos (como dice Remus) es una especie de "sal global", y entonces no es realmente una sal. Si saltea sus valores, su búsqueda de índice se vuelve imposible, porque la sal es diferente para cada fila. – SqlRyan

-1

Otra opción es utilizar una vista que contiene una columna de valores descifrados y buscar registros de acuerdo con ella.

SELECT PlainTextA, PlainTextB, PlainTextC from TheView 
WHERE DecryptedColumn = @SearchTerm