is possible decrypt this type of password generated by Meteor application.
My idea is to use the same credentials (email and password) for my application in C #
As noted in other answers, you cannot decrypt the passwords, but you can very well use the Meteor database to authenticate in a different system.
This is how to do it:
In your other system, first find libraries that provide SHA256 and bcrypt implementations.
Then take the password as entered by the user, and first compute a SHA256 digest hash from it.
Then feed this hash string to bcrypt using number of rounds = 10 (This is the Meteor default).
Now compare the result from bcrypt with the services.password.bcrypt from the MongoDB database of Meteor. If they match, the user provided the correct password.
For reference, the Meteor implementation is here. It is quite simple and well commented.
The very purpose of hashing and encrypting your password is to make decrypting them unpractical.
However, you can reuse the bcrypt(hash(password)) from your meteor app and check against it in another application, provided you use the same scheme.
Is that a bcrypt hash? It depends on the size of the key as Blowfish as a variable sized key. If it's 32 bits. Sure, you could do it with some serious computing power and a few hours. It it is a 128bit key, you'd be long long dead (and so would the universe as we know it) before it every finishes brute forcing. Blowfish does have a minor vulnerability for weak keys though. I would rethink your implementation.
I encountered a similar use case where I was writing a C# application that would validate users created through a Meteor.js application. The code I got to work was this (using System.Security.Cryptography and BCrypt.Net-Next):
string sha256_hash(string value) {
StringBuilder stringBuilder = new StringBuilder();
using (SHA256 hash = SHA256.Create()) {
Encoding enc = Encoding.UTF8;
Byte[] resultingHash = hash.ComputeHash(enc.GetBytes(value));
foreach (Byte b in resultingHash) {
stringBuilder.Append(b.ToString("x2"));
}
}
return stringBuilder.ToString();
}
// First compute SHA256 hash
string sha256hash = sha256_hash("my_password");
// Let BCrypt.Net rehash and check if it matches Meteor's hash
if (BCrypt.Net.BCrypt.Verify(sha256hash, dbPassword) == true) {
Console.WriteLine("Valid!");
}
Related
I'd like to know if there is a standard code to generate a SHA256 hash using a key. I've come across several types of code, however, they don't generate the same output.
Code found at JokeCamp
private string CreateToken(string message, string secret)
{
secret = secret ?? "";
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
Here's another one that I found
private static string ComputeHash(string apiKey, string message)
{
var key = Encoding.UTF8.GetBytes(apiKey);
string hashString;
using (var hmac = new HMACSHA256(key))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
hashString = Convert.ToBase64String(hash);
}
return hashString;
}
The code generated by both of these are different to what is generated by http://www.freeformatter.com/hmac-generator.html#ad-output
I'll be using the SHA256 for one of our external API's where consumers would hash the data and send it to us. So we just want to make sure we use a standard approach so that they send us the correct hash. Also, I would like to know if there are any well-known nugets for this. I've also tried to find a solution with Bouncy Castle, however, I couldn't find one that uses a key to hash.
The difference is because of the character encodings (ASCII vs UTF-8 in your examples). Note that the hashing algorithm takes an array of bytes, and you do the conversion from a string to that byte-array beforehand.
Your question "whats the standard code" probably hasnt an answer, id say that if you expect the input to contain content from just the ASCII character-space, go for that, if not go for UTF-8. Either way - communicate it to your users
If you want to look at it from a usability perspective and make it the optimal for your users - go for both. Hash the content both ways and check agains the users incoming hash, but it all depends on your evaluation on clock-cycles vs security vs usability (you can have two)
They are almost equivalent.
The difference is how the encoding for the string is established.
In the first portion of code it assumes ASCII, whereas in the second portion it assumes UTF-8. It is possible that the string used another encoding which is none of those.
But regardless of that, the idea is to understand what is the goal of this operation. The truly relevant things in this context are:
Given equal input, output should be the same
There should be no way to retrieve the plaintext only by knowing the output (within a reasonable amount of time)
After hashing, you no longer require the original input in plaintext.
A secure cryptographic hashing function (meaning not older functions like MD5) achieves that.
Then, if your data store where hashes are stored is compromised, the attacker would only have a hash which cannot be used to retrieved the original plaintext. This is why hashing is used rather than encryption, encryption is a reversible operation (through decryption).
Then, within the system, if you've made the decision to use one encoding, you need to keep that decision consistent across all components in your system so they can interoperate.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I've been searching all over google just for a simple encryption and decryption method to store passwords. I'm not looking for a very complex encryption so I guess that's what is making it hard to find.
Does anyone have any simple encryption and decryption methods they could share with me?
You should hash your passwords using SHA256 for example. To check password validity, you hash the password received from the user and compare it with the hash stored in your database.
That said, you should ensure passwords are sent over SSL or they could be captured. If your own OS is not secured, the passwords could be captured in clear text as they arrive.
You would be better off using Windows Integrated Authentication when your web site is on the Intranet. For the Internet, OAuth might prove to be a better option.
Thanks to #philsoady for pointing out https://security.stackexchange.com/questions/35250/hmacsha512-versus-rfc2898derivebytes-for-password-hash for further reading.
As oscar132 explained in a comment, you shouldn't try and reinvent membership.
ASP.NET has a really good membership provider as a default option that requires not that much configuration. It has everything you need for good password management: User management, password resets, integrated web controls,...
It also does not do the terribly unsafe method of encryption, but instead hashes the passwords using the already recommended SHA256 method, with the option to use custom providers for enhanced cryptoalgorithms like PBKDF2 or bcrypt.
And even if your project already is underway, it's not that hard to add support for it. Visual Studio has default support for upgrading a asp.net website to an asp.net web forms application that implements membership.
Why you should use hashing rather than encryption:
If you use encryption, then you will need to have a key. This key can be taken and used to decrypt your passwords. Most likely, people within your organization will have access to this key. This means there is potential for everyone to know your users' passwords.
What does Hashing do differently?
Hashing is designed to be a one way linear transform. Therefore, you cannot go backwards and get the actual password. A simple hashing algorithm can be demonstrated in the following manner: use the remainder of dividing a password by 6. Lets say that your password is 10. You will store 4 in the database, as 10/6 has a remainder of 4. If you see 4 in the database, you cannot go backwards and figure out that you had 10, because it could also have been 4, or 16 (or infinitely many others). However, by passing in 10 you can verify that this is the same as the 4 stored in the database. You may notice an inherent flaw here. If you use 16 as your password it will still match in the database. This is known as a collision.
It is recommended that you use a hashing algorithm larger than SHA128 (output of 128 bits) because it is computationally infeasible to search until you find a collision. SHA algorithms are designed for speed, so these should still be fast enough for you (you said it was light weight). As an addition, some people generate sets of known popular passwords and their hashes (more commonly referred to as rainbow tables) which are used to quickly cross-reference against stored values.
For more security, creating a unique value (commonly referred to as salt) for each user which you should append to the beginning or end of your password before you hash. For example, the salt value is salt and the password is password, so we would hash saltpassword and store the result. Then when the user logs in again, we would compare the generated hash against the stored value. The reason this is better is in the scenario where two users have the same password, they will have two different unique hashes.
A small code sample:
using System.Security.Cryptography;
private string HashPassword(string password, string salt)
{
string hashedString = CryptoConfig.CreateFromName("SHA256")
.ComputeHash(salt+password);
return hashedString;
}
Basically, using encryption means that passwords can be discovered. Using hashing means that you cannot feasibly found out what they are, just find a potential collision (unless you are really lucky).
Not a SO question really but incase others find this.
Some do and donts. Home grown sites can be lacking here.
Don't Store passwords, Store one-way hashes. Encode them if possible.
Don't Use HMacSHA* as the algorithm, USE BCRPT, SCRYPT or RFC2898DerivedBytes(PBKDF2) for PASSWORDS. SHA is too fast and not suitable for password hashing.
Use a SALT
Prefer standard well tested and accepted tools eg in your environment ASP.Net Identity
Always use SSL when requesting a users password
If you Must (are you really sure) Encrypt and Decrypt have a machine Key / decryption key policy. The encryption is only as good as the key's safety.
If serious application consider using SCyrpt for c#
The bare minimum in standard c# to encode a password should be something like
the following using Rfc2898.
a) Store the encoded password and random SALT in you database.
b) Use a cost that takes at least 250 msecs.
c) compare the user provided password with stored SALT to the same routine and compare hashes.
private string PasswordEncode(string password, byte[] salt ) {
var deriver2898 = new Rfc2898DeriveBytes(password, salt,64000); // approx 300msecs
byte[] hash = deriver2898.GetBytes(20); //
// return hash;
// If you dont like storing bytes, use a string
return Convert.ToBase64String(hash);
}
// himalayan pink rock salt... the best kind
public byte[] GenerateSalt(int size = 64) {
using (var crypto = new RNGCryptoServiceProvider()) {
var bytes = new byte[size];
crypto.GetBytes(bytes); //get a bucket of very random bytes
return bytes;
}
}
if you at this stage are still convinced you need to Encrypt then use one of the symmetric algorithms from Microsoft. EG AesManaged
/// <summary>
/// Encrypt using preferred provider.
/// </summary>
/// <typeparam name="T">AesManaged,TripleDESCryptoServiceProvider,RijndaelManaged</typeparam>
/// <param name="value">Value to be encrypted</param>
/// <param name="decryptionKey">secret key .. see machine key descryptionKey</param>
/// <param name="salt">salt for process</param>
/// <returns></returns>
public string Encrypt<T>(string value, string salt, string decryptionKey)
where T : SymmetricAlgorithm, new() {
var derivedKey = GenerateKey(decryptionKey, salt);
SymmetricAlgorithm algorithm = new T();
byte[] rgbKey = derivedKey.GetBytes(algorithm.KeySize >> 3);
byte[] rgbIv = derivedKey.GetBytes(algorithm.BlockSize >> 3);
ICryptoTransform transform = algorithm.CreateEncryptor(rgbKey, rgbIv);
using (var buffer = new MemoryStream()) {
using (var stream = new CryptoStream(buffer, transform, CryptoStreamMode.Write)) {
using (var writer = new StreamWriter(stream, Encoding.Unicode)) {
writer.Write(value);
}
}
// before finished with the buffer return, now as the stream is now closed
return Convert.ToBase64String(buffer.ToArray());
}
}
public string Decrypt<T>(string text, string salt, string decryptionKey)
where T : SymmetricAlgorithm, new() {
// could catch errors here, and return a null string. ?
// "CryptographicException: Padding is invalid and cannot be removed"
// can occur if there is a coding problem , such as invalid key or salt passed to this routine.
var derivedKey = GenerateKey(decryptionKey, salt);
SymmetricAlgorithm algorithm = new T();
byte[] rgbKey = derivedKey.GetBytes(algorithm.KeySize >> 3);
byte[] rgbIv = derivedKey.GetBytes(algorithm.BlockSize >> 3);
ICryptoTransform transform = algorithm.CreateDecryptor(rgbKey, rgbIv);
using (var buffer = new MemoryStream(Convert.FromBase64String(text))) {
using (var stream = new CryptoStream(buffer, transform, CryptoStreamMode.Read)) {
using (var reader = new StreamReader(stream, Encoding.Unicode)) {
return reader.ReadToEnd(); // error here implies wrong keys supplied , and code or environment problem.. NASTY issue
}
}
}
}
public DeriveBytes GenerateKey(string salt, string decryptionKey) {
// generate the key from the shared secret and the salt
var saltAsByteArray = salt.UTF8StringToByteArray();
var key = new Rfc2898DeriveBytes(decryptionKey, saltAsByteArray);
return key;
}
Sample calls: of encrypt and decrypt. Plus consider,how to get machine key and use as key here
Encrypt<AesManaged>(password, salt, decryptionKey);
Decrypt<AesManaged>(encryptedPassword, salt, decryptionKey);
At the time of registering
string crypt = CryptSharp.Crypter.Sha512.GenerateSalt();
crypt = txtspss.Text.Trim();
crypt = CryptSharp.Crypter.Sha512.Crypt(txtspss.Text, crypt);
At the time of login..
string cpass=dr["strUPass"].ToString();
bool matches = Crypter.CheckPassword(pass,cpass);
if (matches)
{....}
A salt is supposed to be unique. By doing this, someone trying to crack passwords has to do a separate compuation for each password, instead of being able to generate hashes for a million passwords and then check them against the entire stolen password database.
CryptSharp encodes passwords in Modular Crypt Format. Here's the design. Suppose the algorithm is A, the salt is B, and the hash is C. GenerateSalt writes AB, Crypt reads AB and generates C, returning ABC. Underneath, you see, CheckPassword is more or less equivalent to:
Crypter.Crypt(password, crypt) == crypt
Because Crypt reads only AB, if you pass it ABC, it's the same as passing it AB. This is how Crypt does double-duty both generating and checking password hashes.
At registration, GenerateSalt and Crypt, and at log-in, CheckPassword. Many people will tell you this or that about storing salts separately, etc. and this is good general advice, but Modular Crypt Format is designed so everything needed is stored in the same string. It's all taken care of for you.
Oh... Also, in your code, you have a bug. Your line in the middle isn't doing you any good. The following will work correctly:
string crypt = CryptSharp.Crypter.Sha512.GenerateSalt();
crypt = CryptSharp.Crypter.Sha512.Crypt(txtspss.Text.Trim(), crypt);
There is not enough code to say what exactly is wrong, but you should start by using the result of
CryptSharp.Crypter.Sha512.GenerateSalt()
because right now, you just dump it by overwriting the variable in the following line.
SHA512 is a Hashing algorithm, and to make it more secure against attacks like rainbow tables library methods optionally take a salt value.
The same salt value should be present when hashing and when comparing the hash of a new value, and in your code you don't seem to be doing that.
When registering a user; the Salt should be stored in the database and retrieved when logging in so it can be supplied to the CheckPassword function.
Currently writing my own AMF TcpSocketServer. Everything works good so far i can send and recieve objects and i use some serialization/deserialization code. Now i started working on the encryption code and i am not so familiar with this stuff.
I work with bytes , is DES-CBC a good
way to encrypt this stuff? Or are
there other more performant/secure
ways to send my data? Note that
performance is a must :).
When i call: ReadAmf3Object with the decrypter specified i get an: InvalidOperationException thrown by my ReadAmf3Object function when i read out the first byte the Amf3TypeCode isn't specified ( they range from 0 to 16 i believe (Bool, String, Int, DateTime, etc) ). I got Typecodes varying from 97 to 254? Anyone knows whats going wrong? I think it has something to do with the encryption part. Since the deserializer works fine w/o the encryption. I am using the right padding/mode/key?
I used: http://code.google.com/p/as3crypto/ as as3 encryption/decryption library. And i wrote an Async tcp server with some abuse of the threadpool ;)
Anyway here some code:
C# crypter initalization code
System.Security.Cryptography.DESCryptoServiceProvider crypter = new DESCryptoServiceProvider();
crypter.Padding = PaddingMode.Zeros;
crypter.Mode = CipherMode.CBC;
crypter.Key = Encoding.ASCII.GetBytes("TESTTEST");
AS3
private static var _KEY:ByteArray = Hex.toArray(Hex.fromString("TESTTEST"));
private static var _TYPE:String = "des-cbc";
public static function encrypt(array:ByteArray):ByteArray
{
var pad:IPad = new NullPad;
var mode:ICipher = Crypto.getCipher(_TYPE, _KEY, pad);
pad.setBlockSize(mode.getBlockSize());
mode.encrypt(array);
return array;
}
public static function decrypt(array:ByteArray):ByteArray
{
var pad:IPad = new NullPad;
var mode:ICipher = Crypto.getCipher(_TYPE, _KEY, pad);
pad.setBlockSize(mode.getBlockSize());
mode.decrypt(array);
return array;
}
C# read/unserialize/decrypt code
public override object Read(int length)
{
object d;
using (MemoryStream stream = new MemoryStream())
{
stream.Write(this._readBuffer, 0, length);
stream.Position = 0;
if (this.Decrypter != null)
{
using (CryptoStream c = new CryptoStream(stream, this.Decrypter, CryptoStreamMode.Read))
using (AmfReader reader = new AmfReader(c))
{
d = reader.ReadAmf3Object();
}
}
else
{
using (AmfReader reader = new AmfReader(stream))
{
d = reader.ReadAmf3Object();
}
}
}
return d;
}
Define "secure."
DES is more secure than plain text, but due to it's 56-bit keysize, it's not usually used anymore. If you're protecting data against your family, or the casual ease dropper this might be okay.
If people are using DES these days, it's Triple DES which essentially runs DES, three times, on each datablock.
Now a days the symmetric encryption algorithm (which DES is) of choice is AES, which is like the spiritual successor to DES.
AES with a sufficiently large key of 256 (really 512 or higher now a days) is cryptographically secure for most applications.
The few caveats of AES are:
It's still restricted to US Export controls
The NSA can decrypt your information if they want to (yes
this is tin hat thinking)
Regarding your error, first try switching to AES, and see if you still get a problem.
Regarding AES:
Key selection is important, as well as key protection.
Key Selection
If you want to "password" protect your data, using AES, then you need to convert your password into an AES key. This is a common pitfall for many amateur computer security developers. Adobe essentially destroyed all the protection of AES in their PDF's by using an MD5 hash of the users password as the key. Needless to say, you're smarter than all of Adobe's engineers combined, so you won't make that mistake.
The proper way to generate a key from a password is using RFC2898 aka PBKD2 (password based key derivation function). .NET handily has a method that does this: Rfc2898DeriveBytes(). Essentially what this does is cryptographically securely hashes your password, with a supplied salt (more on this in a bit), a number of times, supplied by the user. This provides several layers to protect against brute force attacks against your password (assuming your key is large enough to prevent brute force attacks against it!)
Each iteration of PBKD2 takes a minuscule amount of time to run. The more interation you run (i think the recommend number is > 1000), the more computer time it takes. This time is still less than a human would recognize, but in computer time it's like a century. Thus without knowing the exact iteration count, it makes it a very lengthy process to brute force attack a password.
Salt. Rather than taking a direct hash of your password, a salt adds extra information to your input password, creating a unique hash. This prevents rainbow table attacks, assuming you keep your salt value protected.
Key Storage
The other side to cryptography is key storage. If you are password protecting your data, then you need to securely store the password. The easiest way is to use the OS's built in security. On Windows thats using DPAPI in the registry, and Unix, filepermissions.
AES as a Session Key
If you are looking to securely transmit data across a nonsecure channel (or even adding your own extra security ontop of SSL), you may want to looking at using AES as a session encryption.
Essentially this is two scheme encryption system that works as follows:
You generate a public/private key pair using your favorite assymetric encryption (RSA!) for your server.
Each trusted client is given the public key.
During a session, the client generates a new random AES key of 256 bit or higher.
This AES Session key is encrypted using the public RSA key.
This encrypted data containing the AES session key is sent to the server.
The server decrypts the data using it's private RSA key, and keeps the AES Session key.
During the rest of the session, all data is encrypted with the session AES key.
At the end of the session, the AES key is discarded.
While this does require more handshaking, this gives you the added protection of limiting exposure. Since the AES key is only good for a session, if it's discovered, the damage is only limited to a single session.
DES is a block cipher, so in general it makes working with bytes more tedious. AS3 is a stream cipher used primarily with GSM phone systems, because it's a stream cipher it'll work nicely with bytes.
Personally, I would use RC4 if you really need to use a stream cipher; it's very quick. There's a good implementation here http://dotnet-snippets.com/dns/rc4-encryption-SID577.aspx
There are some very important caveats you should be aware of when using stream ciphers:
1) NEVER re-use an encryption key with a stream cipher.
2) Because you're encrypting one byte at a time, it's hard to determine if the data has been tampered with, so you'll need add a digital signature or HMAC to the stream.
I am looking to encrypt data. I want to generate encryption keys based on a password, and some moving value, like time. The goal is to have the key change, but have anyone that knows the password be able to decrypt. This is happening in C#. I am using the following code to hash the password.
private static string GetPasswordHash(string password)
{
TimeSpan span = (DateTime.UtcNow - new DateTime(1900, 1, 1));
string result = Convert.ToInt32(span.TotalHours).ToString();
result += password;
result += Convert.ToInt32(span.TotalDays).ToString();
result = Convert.ToBase64String(SHA256.Create().ComputeHash(Encoding.ASCII.GetBytes(result)));
return result;
}
I then use that hash, plus a salt to generate a key.
Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(GetPasswordHash(password), salt);
rdb.IterationCount = 1000;
RijndaelManaged rm = new RijndaelManaged();
rm.KeySize = 256;
rm.Key = rdb.GetBytes(32);
rm.IV = rdb.GetBytes(16);
There seem to be issues with the way I am doing this. Some of the computers are in different timezones, or if the hour ticks as I send the data, or if the machines times are slightly off. Are there better suggestions?
The standard strategy is to just send the value (time, etc.) just be sent with the encryption key. Since the value you are using is public knowledge, it is fine if whoever first creates the password provides the "moving value" publicly. See Salt. What you are doing is not a new technique. You also seem to be using Key Strengthening.
You might just send the changing part (unencrypted) along with the encrypted data, so that anyone who knows the secret password can easily reconstruct the password used for encryption. Since the changing part is relatively easy to guess, it wouldn't make it much less secure.
You could find a scheme that generates the same moving value over a window of time, centered on the current time. Thus, if you choose a window of 12 hours, all computers 6 hours behind and 6 hours ahead of yours would generate the same encryption key.
Are you worried that a file with the same data encrypted with the same password looks the same?
You could use set the initialisation vector with the current time, and encrypt using your password.
To decrypt, you use the same IV value (so this has to be stored unencrypted with your file somewhere).
Password based key derivation is already implemented in .net. While I can't see anything wrong with your function GetPasswordHash() its always worth using library functions in crypto as they'll likely be better tested and small errors can completely destroy the security of a system. Here're two links, there are probably others too:
rfc2898derivebytes
passwordderivebytes