i have a database table with a 88digits hash and a 16digits salt. i know the clear password because its my own testuser.
this user, password, hash and salt was created within a website / commercial tool.
I am trying to build my own .net website and would like to use the same user/password database table.
I tried different ways in .net and i found out that based on the length of the hash(88) is has to be a sha512 hashing.
i read the existing salt from the table and build a hash from password and salt. the outcome is different to the existing hash in the database table.
i believe my "sha512managed" is wrong or the commercial tool uses not only password + salt to create the hash. maybe the use Encoding.Unicode.GetBytes(string.Concat("text" + password, salt)) or something.
i there any whay to figure this out?
Related
I need to encrypt some columns in my MS SQL database (name, ssn ...) and I have been looking at column encryption as described by a few sites such as:
Encrypting Column Level Data in SQL Server
and
Introduction to SQL Server Encryption and Symmetric Key Encryption Tutorial.
I've been able to use an Trigger on insert to encrypt a column and I can decrypt the column within SQL Studio using:
OPEN SYMMETRIC KEY TestTableKey
DECRYPTION BY PASSWORD = 'Pa$$w0rd'
CONVERT(VARCHAR(50),DECRYPTBYKEY(EncryptSecondCol)) AS DecryptSecondCol
FROM TestTable
But how do I access the data from my application? I still want to be able to search for names. The only thing I can think of is using a Stored Procedure and sending the decryption password as a parameter in the LINQ statement so the stored procedure can decrypt the data and then execute the query.
Am I on the right track?
I'm new to this so I welcome other useful suggestions.
Yes, I have seen stored procedures to decrypt encrypted text. I've also seen stored procedures to encrypt text, which I prefer to Triggers because I don't like Triggers - see these answers.
However, I prefer to put encryption logic in my application layer - using, for example, the Enterprise Library Encryption Code. The passphrase and salt are easily encrypted in the config file using the Enterprise Library console.
Is there a specific reason for doing this work in the database? If you must do it that way, you could use EL to protect your passphrase and pass that into the stored procedure you've written.
If you are using MS SQL Server Enterprise or Developer editions, you can use TDE:
TDE
I personally think SQL column encryption is a huge waste ;-), but must implement it due to a customer push. So my questions are:
What actually does it do -- Will an admin see encrypted data, but the application will see cleartext data?
What happens to the data when it gets backed up? I assume that backups remain encrypted, in which case are they usable if we need to recover onto a different server?
Where does the encryption key actually come from?
Can I specify a fixed encryption key, so that at least the database recovery will easily work on an server I move to. I really don't want some magical key algorithm, which shoots me in the foot in the future when the key suddenly is not available.
If the customer is pushing for column encryption but you don't know where the the key will actually come from, your customer is wasting his money and you are wasting his time. Even more so if you are even thinking about fixed keys.
There is an exhaustive explanation on MSDN explaining the key encryption hierarchy. All the schemes have the key chain rooted either in the DPAPI for the case where the service itself must access the encrypted storage w/o any key provided by the user, either in a password explicitly provided by the user.
Encryption is a measure put in place to mitigate specific security threats. Depending on what those threats are (they are nowhere specified in your post) column level encryption may be the right answer, but almost always deploying Transparent Database Encryption is a much better solution.
There is no encryption scheme that can hide the content from an administrator that desires to see the content. Period. Every solution that claims the contrary is snake oil.
http://msdn.microsoft.com/en-us/library/ms179331.aspx
You can create a symmetric key to encrypt the data and can use a string to create it (with the KEY_SOURCE option) that will enable you to recreate it later (this isn't in the linked sample bit is in the docs). This has to be opened to access the actual data. This is protected by a certificate which is in turn protected by the database master key. DO NOT lose the password for your database master key. The Database master key is protected by a server key, so if you restore to another server you must open your database master key with the password and reencrypt with the new server's service master key.
If you created the symmetric key with a static string (KEY_SOURCE option), then you can recreate it with a different certificate and database master key and still access your encrypted data.
-- backup service master key tied to computer (used to decrypt database master password,
-- if this is the same on two servers you can move the database between them)
BACKUP SERVICE MASTER KEY TO FILE = 'C:\ServiceMasterKey.smk'
ENCRYPTION BY PASSWORD = 'topsecret'
go
-- create database master key
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'dbpassword'
go
-- create certificate to use to encrypt symmetric key
CREATE CERTIFICATE TestCertificate WITH SUBJECT = 'Test Certificate',
EXPIRY_DATE = '01/01/2016'
go
-- create symmetric key to encrypt data
CREATE SYMMETRIC KEY TestKey WITH ALGORITHM = TRIPLE_DES,
KEY_SOURCE ='pass_phrase' ENCRYPTION BY CERTIFICATE TestCertificate
go
create table CCInfo (ID int, Plain varchar(16), Encrypted varbinary(128))
go
insert into CCInfo (ID, Plain) values (1, '1234567890ABCDEF')
insert into CCInfo (ID, Plain) values (2, '1234123412341234')
insert into CCInfo (ID, Plain) values (3, '1234567890ABCDEF')
insert into CCInfo (ID, Plain) values (4, '1111111123456789')
go
-- encrypt credit card data
OPEN SYMMETRIC KEY TestKey DECRYPTION BY CERTIFICATE TestCertificate
update CCInfo set Encrypted = EncryptByKey(Key_GUID('TestKey'), Plain)
CLOSE SYMMETRIC KEY TestKey
go
-- check that data is the same
OPEN SYMMETRIC KEY TestKey DECRYPTION BY CERTIFICATE TestCertificate
select ID, Plain, Encrypted, convert(varchar(16), DecryptByKey(Encrypted)) as Decrypted
from CCInfo
CLOSE SYMMETRIC KEY TestKey
A couple things to note:
This is called "Cell-level" encryption, and it is a manual process - you can't just mark a column as "encrypted"
It may require access to Certificate Services, which carries its own set of challenges and overhead (I'm not positive about this, it may depend on whether you use AD)
To answer your specific questions:
Nobody sees unencrypted data directly in the database - you must use a stored procedure to encrypt and decrypt the data. The column itself must be converted to a varbinary column. I believe access can be controlled based on both the key and the stored procedures.
The data is backed up as a varbinary column.
The encryption key is generated in the database by someone with appropriate permissions
I think so? The latter part of this encryption tutorial should give you an idea of what's entailed.
More information can be found in the MSDN Database Encryption documentation.
I have a bit of code that needs to run with elevated privileges (more that I want the rest of my code running at).
I have my code that sets up the Impersonation working, but it requires a username, domain and password. As my code is in C#.net I know that the password can be found by anyone determined enough.
Is there a way to encrypt the password in my code? Or otherwise secure this password and still be able to pass it in?
Here is the code I am calling:
using (new Impersonator("UserNameGoesHere", "DomainNameGoesGere", "Password Goes Here"))
{
uint output;
NetUserAdd(AUTHENTICATION_SERVER, 1, ref userinfo, out output);
return output;
}
I would love an example that shows how to fix this to not show my password in plain text.
I am using Visual Studio 2008, .NET 3.5 SP1, and running on Windows Server 2003.
Vaccano,
I would recommend investigating the data protection API (DPAPI) for what you're attempting to achieve. It is considered part of the solution in many best practice approaches to reversibly storing passwords needed by applications.
A good article discussing the DPAPI (and other techniques + concerns) can be found here:
http://msdn.microsoft.com/en-us/magazine/cc164054.aspx
With C# 2.0, P/Invoking isn't even required; managed wrappers exist:
http://blogs.freshlogicstudios.com/Posts/View.aspx?Id=41ca5a99-ddc0-4d0a-9919-2ce10bf50c7e
I hope this helps!
You have multiple options here.
You can hash the password the very first time and store the hash to a file. Now the next time, you want to execute the code with elevated privileges, you need to accept/retype the password and re-compute the hash and match it with the stored hash. Only if it matches will you execute your code in elevation modes. You could hash using SHA. Please look at System.Crytography namespace for examples on hashing.
Second option is to encrypt the password using algorithms like AES. However you will need to have a key to do this and you will have to worry about securing this key.
Third option is to use DPAPI and encrypt the password but not worry about securing the keys - much easier option than 2.
I would recommend 1 if you do not mind re-entering the password every time the application starts. If that is not a possibility, I would suggest going with 3 and use DPAPI.
Here are some links to get you started.
1.http://www.obviex.com/samples/dpapi.aspx
2. http://www.obviex.com/samples/Encryption.aspx
You can use safe-config nuget package. Internally it uses data protection api to encrypt and decrypt data.
//Save some configuration data at folder data\temp\
var configManager = new ConfigManager()
.WithOptions(DataProtectionScope.CurrentUser)
.Set("password", "my-massword")
.AtFolder(#"data\temp\")
.Save();
...
//Load configuration data
var loadedValue = new ConfigManager()
.AtFolder(#"data\temp\")
.Load()
.Get<string>("password");
I need to store and encrypt a password in a (preferably text) file, that I later need to be able to decrypt. The password is for another service that I use, and needs to be sent there in clear text (over SSL). This is not something I can change. What are best practices in this area? How can achieve some degree of protection of the password from malicious users?
My platform is WinForms with C#/.NET 3.5.
Thanks.
I am assuming that you want to encrypt the password as it will be on the users machine and they will (possibly) be able to find it and use it? If so you are basically screwed - no matter what you do, since it is in the users domain they will be able to get it and figure out the encryption and get the password for the encryption (remember that using Reflector - and it's clones - isn't out of the reach of most) and decrypt it and they have it. In short all you are doing is obfuscating the password, not securing it.
What I would recommend is actually move it out of the users control. For example put up a web service which communicates with the client and returns the password securely when requested. This also allows you to change the password, if needed in future as well as provides you with a way to validate legitimate users.
Why you need to decrypt the password? Usually a salted hash of the password is stored and compared. If you encrypt/decrypt the password you have the password as plain text again and this is dangerous. The hash should be salted to avoid duplicated hash if the some users have the same passwords. For the salt you can take the user name.
HashAlgorithm hash = new SHA256Managed();
string password = "12345";
string salt = "UserName";
// compute hash of the password prefixing password with the salt
byte[] plainTextBytes = Encoding.UTF8.GetBytes(salt + password);
byte[] hashBytes = hash.ComputeHash(plainTextBytes);
string hashValue = Convert.ToBase64String(hashBytes);
You can calculate the salted hash of the password and store that within your file. During the authentication you calculate the hash from the user entries again and compare this hash with the stored password hash.
Since it should be very difficult (its never impossible, always a matter of time) to get the plain text from a hash the password is protected from reading as plain text again.
Tip: Never store or send a password unencrypted. If you get a new password, encrypt is as soon as possible!
System.Security.Cryptography.ProtectedData in the System.Security assembly uses some Windows APIs to encrypt data with a password only it knows.
One possibly use of this would be to have a Windows service that actually does the operation requiring the password. The application that the user interacts with calls into the service via remoting or WCF. As long as the service used DataProtectionScope.CurrentUser and the service user is different from the logged on user, the password should be pretty safe.
This of course assumes that the users are running as limited users who cannot modify the service or run program as the service's user.
Because you are using WinForms and .Net, your code is going to be visible in MSIL - even if obfuscated, and therefore your decryption code is visible.
Who are you trying to hide the password from? Is the user of the app not supposed to know the password?
I think you are going to need to do some user validation, and I would be tempted to put keys to the decryption in a separate database and provide some other mechanism to get that out which should require authentication. That way you can get the decryption code out of the winforms app.
I would also suggest a separate service which runs to regularly change the encryption decryption keys and updates all passwords in the database.
Encrypted in AES if you must store it in a text file.
AES is better known as Rijndael in c#
http://www.obviex.com/samples/Encryption.aspx
Better place would be the registry, since it would protect other users of the machine getting to it.
Still not the best storing it anywhere that a user might be able to get to is dangerous a 1/2 way decent developer can load up your app in reflector and find your key.
Or there is System.Security.Cryptography.ProtectedData that someone else suggested.
The best you could do on a machine is create a certificate and encrypt/decrypt with it loaded and locked down in the machine's keystore. (Still have to deal with the certificate password being in your code)
I just implemented something like this for storing a user supplied password. I converted the encrypted result to a base 64 encoded string, so that I could easily store it in my application's user settings.
From your question, it seems that your malicious user is actually using your application, so this will only provide obfuscation. Though no key would be revealed through the use of Reflector, the plain text would be visible in a debugger.
static byte[] entropy = { 65, 34, 87, 33 };
public string Password
{
get
{
if (this.EncryptedPassword == string.Empty)
{
return string.Empty;
}
var encrypted = Convert.FromBase64String(this.EncryptedPassword);
var data = ProtectedData.Unprotect(encrypted, entropy, DataProtectionScope.CurrentUser);
var password = Encoding.UTF8.GetString(data);
return password;
}
set
{
if (value == string.Empty)
{
this.EncryptedPassword = string.Empty;
return;
}
var data = Encoding.UTF8.GetBytes(value);
var encrypted = ProtectedData.Protect(data, entropy, DataProtectionScope.CurrentUser);
var stored = Convert.ToBase64String(encrypted);
this.EncryptedPassword = stored;
}
}
Do not store the password as part of the code. Aside from the issues of decompilation and relying on security through obscurity, if you change the password you need to recompile and redistribution your application.
Store the password as a webservice or in a database that the application has access to. You're communicating with a service over the web, so you will be connected, after all.
One of the most important thing is the permissions on the file. Even if the content is encrypted you need to make sure that only the processes that need access to the file can read it.
Since you must send the password in unencrypted form over the network, there is nothing you can do to protect it 100%.
AES is good enough if you need to store locally, and talking about disasms, network sniffers etc is not particulary good contra-argument becuase the same thing can be done with any program (sure, ASM is harder then CIL but its a minior point).
Such password protecting is good enough to prevent casual pick up, not to prevent decoding by proffesionals.
I am creating a program that needs to store the user's data in encrypted form. The user enters a password before encryption and is required to supply the password again to retrieve the data. Decryption takes a while if there is a lot of data.
Now, I want to check that the user has entered the correct password before doing the decryption. This check needs to be fast, and the decryption process is not.
How can I check the password before actually completing the decryption process ? I thought about storing a hash of the password as the first few bytes of an encrypted file - this would be easy and fast enough - but I am not sure whether it compromises security ?
I am using .NET and the built in cryptography classes.
Well, a cryptographic hash shouldn't compromise security as long as it is salted and has reasonable complexity; personally, though, I'd probably try to set it up so that data corruption (due to incorrect password) is obvious early on...
Any possibility of injecting checksums in the data at regular intervals? Or if the stream represents records, can you read it with an iterator (IEnumerable<T> etc) so that it reads lazily and breaks early?
(edit) Also - forcing it to decrypt a non-trivial chunk of data (but not the entire stream) before it can tell if the password was right should be enough to make it hard to brute-force. If it only has to work with the first 128 bytes (or whatever) that might be fast enough to make it worth-while trying (dictionary etc). But for regular usage (one try, password either right or wrong) it should have no performance impact.
I suppose you are using the password as a salt for the encryption/decryption process. The simplest approach would be to encrypt some standard phrase or may be the password that user provided as the input string with the same password as salt for the encryption process. When the user wants to decrypt the data take that password as salt for your decyption process and use ot to decrypt the encrypted password. If you get the password back then the user has provided the correct password and you can continue the decryption process otherwise notify the user that his password is incorrect.
The process would be:
User gived PASSWORD and DATA for enryption.
You encrypt the PASSWORD with PASSWORD as the salt. and store it as ENCRYPTED_PASSWORD.
Encrypt the DATA with PASSWORD and store it.
The user comes back gives you the PASSWORD.
You decrypt ENCRYPTED_PASSWORD with PASSWORD as salt.
If the result is equal to PASSWORD you decrypt the DATA otherwise you notify the user.