join on encrypted field - sql-server

I have a requirement to encrypt the customer's membership number in our database. So okay, we're using MS SQL Server, I figured I use encryptbypassphrase, change every place that writes this field to encrypt and every place that reads it to decrypt, etc.
Except ... there are places in the DB where the field is used to link multiple records. I was thinking no problem, I just change the join from "join blahblah on a.member_number=b.member_number", to "join blahblah on a.member_number_encrypted=b.member_number_encrypted". But this doesn't work, because I discovered that if I encrypt the same value twice, I don't get the same encrypted value. I guess it's adding some salt in there or something. And I don't want to say "join blahblah on decryptbypassphrase(#pw, a.member_number_encrypted)=decryptbypassphrase(#pw, b.member_number_encrypted), as that would turn an index lookup into a full-file search. I thought it would be ugly to have to index on the much bigger encrypted value, but ...
So ... Is there some way to force encryptbypassphrase to always encrypt the same input to the same output? Or does this mean that it is simply not practical to join on an encrypted field in most cases?
Or am I missing something?

What you are looking for is deterministic encryption.
You can achieve deterministic encryption by using a hash of plaintext as your IV, thus, you will get the same ciphertext every time you encrypt a given plaintext. Please see this article for reference.
If you are using/can use MS SQL Server 2016 you should look at Always Encrypted feature. Depending on what operations you want to do on your data. Always Encrypted will make your task easier, since it supports deterministic encryption. Few links that will help you.
Getting Started with Always Encrypted
This feature will make it easier to test Always Encrypted without writing an app
Configure Always Encrypted using SQL Server Management Studio
I have briefly explained the security guarantee provided by Always Encrypted here

Related

Ensure SQL Server sensitive data authenticity

I have an odd question that needs a creative answer.
I have code a program that writes sensitive data on a SQL Server Table with 3 columns.
Every time this program starts I need to check this data.
The problem is that I need a way to check that the data on this 3 fields was writed by my process and not manipulated nor copied externally or by other process.
So if the data on any of the 3 fields was modiffied externally, my code should not recognize the data. Also, if the data was copied from other server, neither should be recornized.
What I have in mind:
1) Create a secret private key with unique data from SQL Instance.
2) Create a binary field on the table.
3) When the data is witted, fill the binary field with PwdEncrypt function and private key as data.
4) When data is readed, use PwdCompare to check if the data on binary field match private key.
Now, how can I ensure that other fields are not modified?
I need this to work on several servers that use from SQL Server Express 2008 R2 to SQL Server Standard 2016
Thanks!
Your approach is pretty much correct, but you don't need anything asymmetric here, a simple HMAC will do.
When modifying any row of a table that requires data authenticity, concatenate the binary values of all fields that you want authenticated and run the final binary string through an HMAC with a secret key stored only with your process.
Do the same again when checking to see if the row is valid and compare the two resulting hashes using a time-safe check. If they don't match, something has been tampered with.

How to changed Encrypted data to Decrypted in Sql server

I try more time to change in sql, encrypted data to decrypted..
Anybody know this solution,pls reply me..
my password shown as this format 0C6EB14DB9C05361B517EA553E77C977
but datatype was varchar
I want to need to encrypt this data
I suppose you are using PWDENCRYPT to encrypt your data. If so, then it is impossible to recover you password, because is makes a hash so you cannot reverse the hashed string. It is the idea of the hash algorithm to make it impossible. If you want to compare your input values with your encrypted values you can use PWDCOMPARE function.

Encryption on the fly

here is something interesting that I have been asked. It has to do with the encryption of data in a non encrypted database.
The story has as follows. We have a database, not encrypted and also none column encrypted in any of its tables. Now, we'd like to control the trafic of the data depending on who is asking for this. Let me explain more clear:
We have a table with the name: table1
This table has one column with the name: SName
We'd like to reach the following result. A user connected to the SQL Server Management Studio if runs the following query:
select * from table1
to take no result or if he/she takes a result, this result to be scrambled.
Now from inside the application the table should exchange data from/to the application in the normal mode.
Do you know if there is a setting, or an implementation or an external tool that can provide this functionality?
I think that this is quite interesting case!
Thank you.
Use permissions to stop that person reading the table at all.
Or use a VIEW to hide the table and have a WHERE clause in that that applies a filter silently: this could refer to another table with a list of approved users.
This isn't really an encryption (well, obfuscation in this case) issue.

How would I encrypt string data in SQL server 2008 while keeping the ability to query over it?

I have a database that will be hosted by a third party. I need to encrypt strings in certain columns, but I do not want to loose the ability to query over the encrypted columns.
I have limited control over the SQL instance (I have control over the database I own, but not to any administrative functions.)
I realize that I can use a .net encryption library to encrypt the data before it is inserted into the table, but I would then loose the ability to query the data with sql.
I like using SQL Server's key management: http://technet.microsoft.com/en-us/library/bb895340.aspx . After you have a key setup then its really easy to use:
To insert records you do this:
insert into PatientTable values ('Pamela','Doc1',
encryptByKey(Key_GUID('secret'),'111-11-1111'),
encryptByKey(Key_GUID('secret'),'Migraine'))
To select the record back out its really simple:
select Id, name, Docname
from PatientTable where SSN=encryptByKey(Key_GUID('secret'),SSN)
The cipher text will always be the same so it is much more efficient to compare the cipher text's instead of going though and decrypting each one.
if you use the same encryption key you could encrypt your search query string and match against that. Say my password is runrun i encrypt it to ZAXCXCATXCATXCA then when i want to search for a user with password runrun encrypt it first and it will match the table entry.
AFAIK, Most RDBMS do not support this, what I usually see is either:
A) The DB query API encrypts the data with a key that only the local server knows before it is sent to the remote db and decrypts when it's received.
or
B) The remote database stores everything encrypted with a key that it knows (probably at run time, given physically by an admin, or it's given the key with the query).
A will let you use the database without letting the owners know what's being stored, but you wont be able to do queries on the actual encrypted data other than maybe equality. B only protects against physical server theft (server has to be off though or they can get the key from memory...).
What I assume you want is called Private Information Retrieval. It's a fairly young field, I don't think you're going to find a decent implementation at the moment.
You could generate a hash (such as Md5 ) and store the hash value in the db. When you query you can select * from [my table] where value = {md5 hash}

SQL Server PWDEncrypt value comparison

I think what I am about to ask is impossible, however, figured it was worth a shot here.
We have an application that makes use of SQL Servers PWDEncrypt and PWDCompare functions.
Part of the system creates duplicates of users (same logon and password). Due to a bug in the system, instead of copying the binary stored PWDEncrypt of a password it performed another PWDEncrypt of the password. Therefore the binary values do not match.
Is it possible to find out if the two binary values are hashes of the same password?
e.g. PWDEncrypt('abc') = PWDEncrypt('abc')
If I can do this then it means I can find out how many users this bug has actually affected rather than having to deal with thousands!
EDIT: To clarify, PWDEncrypt('abc') = PWDEncrypt('abc') will NOT return true as the passwords are hashed to different values.
Whilst I know its impossible to obtain the password from the hash, PWDCOMPARE('abc', PWDENCRYPT('abc')) works, therefore, internally SQL Server must be doing more than just hashing the password you're comparing and check the values are the same.
It seems that Joel's statement is correct in SQL Server 2000 , but not in SQL Server 2005.
When you generate the hashes together in the same statement in 2000, they end up with the same salt (random seed number at the beginning) which makes them identical.
In 2005 a different salt is always generated, so they never match
if you try this on SQL Server 2000:
PRINT PWDEncrypt('abc')
PRINT PWDEncrypt('abc')
PRINT PWDEncrypt('aaa')
PRINT PWDEncrypt('bbb')
you always have the same salt at the beginning of the hash, where as in 2005 its always different. Also notice that in SQL Server 2005, the hash is shorter as it no longer maintains a copy of the hash in uppercase for case in-sensitive password compatibility.
If you can generate the hash with the same salt, then you can compare them (which means trying a brute force or dictionary attack) Have a look at this article on how to do it. It shows you how to crack SQL Server password in C using the CryptCreateHash function.
Just try with a function that implements pwdencrypt('YourPa$$w0rd') to store it and then another one that returns a BIT 0/1 with the builtin fct pwdcompare('The EnteredPassWord', (Select Pwd From dbo.Users Where Uid = 'UserName'))
That's it ;-)
You can just type SELECT CASE WHEN PWDEncrypt('abc') = PWDEncrypt('abc') THEN 1 ELSE 0 END into a query window and see the result.

Resources