Attempting to use SHA1 hashing to send password to Google - c#

I am currently working on a program with Google's Directory API to reset the password of someone in my domain. I have it all working, but I would like to send an encrypted password to Google instead of plaintext.
Since the API seems limited in what I can use to encrypt, I'm trying to use SHA-1 to do so. The problem is, when I encrypt it in SHA-1, Google doesn't accept it.
Here is my original code of what I was sending to Google:
//create a template of the user to update
var body = new Google.Apis.Admin.Directory.directory_v1.Data.User();
//Encrypt the password using SHA1
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(model.NewPassword);
SHA1 sha = new SHA1CryptoServiceProvider();
byte[] password = sha.ComputeHash(bytes);
//Put the password and hash function into the request body
body.HashFunction = "SHA-1";
body.Password = password.ToString();
//send the request
var request = users.Update(body, email);
request.execute();
When I run this, it throws an error saying the password is invalid.
when I change it so that it is sending strictly hex, like so
//create a template of the user to update
var body = new Google.Apis.Admin.Directory.directory_v1.Data.User();
//Encrypt the password using SHA1
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(model.NewPassword);
SHA1 sha = new SHA1CryptoServiceProvider();
byte[] password = sha.ComputeHash(bytes);
//Convert the hashcode to Hex
System.Text.StringBuilder builder = new System.Text.StringBuilder();
for (int i = 0; i < password.Length; i++)
{
builder.Append(password[i].ToString("x2"));
}
//Put the password and hash function into the request
body.HashFunction = "SHA-1";
body.Password = builder.ToString();
//send the request
var request = users.Update(body, email);
request.execute();
Then Google accepts what I've given it, but going into the account, I can't access it, because the password was changed to something completely different.
Am I just encrypting the password incorrectly, or is there something I'm missing?

(Disclaimer: I work for Google, but I haven't looked at this API before.)
Well, the problem when you call password.ToString() is that it's not providing the hex representation - so that's why the first piece of code fails. It looks like it's basically expecting it to be hex. The documentation states:
We recommend sending the password property value as a base 16 bit encoded hash value. If a hashFunction is specified, the password must be a valid hash key.
Now, I suspect the problem with the second piece of code is the way you're converting the original text password to bytes. You're using:
Encoding.Unicode.GetBytes(model.NewPassword)
That's using little-endian UTF-16. While the documentation doesn't state the expected encoding, using UTF-8 would be more common. So I would suggest using
Encoding.UTF8.GetBytes(model.NewPassword)
instead... and then hashing the result and hex-encoding that hash as before.
That's only an educated guess, but it's worth a try.

Related

C# Checking HMAC SHA256 from API

I'm trying to validate a hmac sha256 key that an API sends to me in a header. I don't fully understand how to validate this, can anoyone point me in the right direction?
From the API reference:
Every central webhook POST contains a header field
"X-Signature-SHA256" with the signature value of the signed body's
payload. The JSON body is signed with the HMAC SHA256 algorithm based
on RFC2104, with the "Client Secret" as the signing key.
The following awnser is pretty clear & helpfull:
https://stackoverflow.com/a/12253723/4179234
However I feel like I'm missing a string/message that I need to encrypt to get the same hmac sha256 key, as I only have the api client secret to use as a key for the hasing but no message.
Following part is taken from the above stackoverlow awnser, so I convert the api client secret to byte[] and use it for the first input var. But what should message be then in this case?
private static byte[] HashHMAC(byte[] key, byte[] message)
{
var hash = new HMACSHA256(key);
return hash.ComputeHash(message);
}

MimeKit encrypt Message with AES

I want du encrypt and sign a mail with MimeKit.
Generating the Message works:
CmsRecipient CmsRecipient = new CmsRecipient("mail.cer");
CmsRecipient.EncryptionAlgorithms = new EncryptionAlgorithm[] { EncryptionAlgorithm.Aes192 };
to1.Add(CmsRecipient);
var signed = MultipartSigned.Create(ctx, signer, multipart);
var encrypted = ApplicationPkcs7Mime.Encrypt(ctx, to1, signed);
message.Body = MultipartSigned.Create(ctx, signer, encrypted);
In Outlook they arrive encrypted with: 168 Bit 3DES
But I need AES 265. How can I manage this?
I can set signing to RSA/SHA512 with
signer.DigestAlgorithm = DigestAlgorithm.Sha512;
but not the encryption.
Edit: Updated to my Solution
The CmsSigner specifies the DigestAlgorithm, but it's the CmsRecipient that specifies which encryption algorithm(s) that the recipient supports.
The way that the encryption algorithm is chosen by MimeKit is that it figures out the best encryption algorithm supported by each recipient and then uses that.
In other words, if you are encrypting to 5 recipients and all of them support AES256, then MimeKit will use AES256. But if one of the recipients only supports, for example, 3DES (and all of the other recipients also support 3DES as well as AES256), then 3DES is chosen instead.

Encrypt passwords existing in Database sql windowsForms

I have a database of logins and passwords. I wouldn't like that anyone who has access to the database can see everybody's password. How can I encrypt the passwords in the database?
In other words, I want the fields pwd (password) to be encrypted in the database but it is automatically decrypted when I enter it in the LoginForm.
I have found a method that encrypt the strings input but it doesn't solve my issue.
static string Encrypt(string value)
{
using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{
UTF8Encoding utf8 = new UTF8Encoding();
byte[] data = md5.ComputeHash(utf8.GetBytes(value));
return Convert.ToBase64String(data);
}
}
private void BtnEncrypt_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtPass.text))
{
MessageBox.Show("Please enter your password !");
}
texResult.Text=Encrypt(txtPass.Text);
}
Please, can somebody help me.
Thanks in advance.
You can Encrypt your password using your Encrypt function and store the Encrypted password in your database.
But Decrypting the password, is not a good option. Password Encryption should be one way.
To check whether the password is available in your database, you can Encrypt the password entered by user by using the same Encrypt function, then match that Encrypted password to encrypted password you have in your database.
Thanks
It is easy to muddle encryption with hashing. What you are asking about is encryption - encryption lets you turn your password into an apparently random sequence of characters which can then be decrypted to get the original password back. What you should be using (and some have suggested) is hashing.
There are lots of examples of how to do encryption/decryption on the net, just search. This is the first one that came up for me: http://www.codeproject.com/Articles/14150/Encrypt-and-Decrypt-Data-with-C Tempting as it is to copy and paste the code from there, I won't because this isn't what you should be doing. For storing user passwords in a database it is much better to use password hashing (with salt) than to store encrypted passwords. Why? because then if your system is hacked it is impossible for an attacker to recover people's passwords - all your accounts might still be compromised but given that people often use the same password for more than one system you won't be compromising your users.
A hash is a one way function, so you can't get the original password back. When someone wants to login you simply generate a hash and then compare it with the one you have stored in the database. If you want to read more about this and why you should be using it then this is a good start: https://crackstation.net/hashing-security.htm If you would like to jump in and get some working code then have a look at Hash and salt passwords in C#.
You can use any complex cryptography technique to encrypt a password and send the password key to be saved in database for corresponding user.
Now when the client tries to login and enters password, sends it to server.
From the server you can again convert the login details and compute the hash and finally send to a stored procedure to compare. If the two strings match, you return true else false as for authentication.
using System.Security.Cryptography;
...
...
...
private const string _alg = "HmacSHA256";
private const string _salt = "rz8LuOtFBXphj9WQfvFh"; // Generated at https://www.random.org/strings
public static string GenerateToken(string username, string password)
{
string hash = string.Join(":", new string[] { username, password });
using (HMAC hmac = HMACSHA256.Create(_alg))
{
hmac.Key = Encoding.UTF8.GetBytes(GetHashedPassword(password));
hmac.ComputeHash(Encoding.UTF8.GetBytes(hash));
hash = Convert.ToBase64String(hmac.Hash);
}
return Convert.ToBase64String(Encoding.UTF8.GetBytes(hash));
}
public static string GetHashedPassword(string password)
{
string key = string.Join(":", new string[] { password, _salt });
using (HMAC hmac = HMACSHA256.Create(_alg))
{
// Hash the key.
hmac.Key = Encoding.UTF8.GetBytes(_salt);
hmac.ComputeHash(Encoding.UTF8.GetBytes(key));
return Convert.ToBase64String(hmac.Hash);
}
}
MD5 is not secure anymore.
When a user register to use your application, hash the password with SHA512 bit with salt. You can find like PWDTK nuget package which we can easily use. Password is what we don't need to know what it means but just plays a secure role. Like some person commented above, when the user try to log-in after user registration, just encrypt the user's input(password) and compare it with that registered in SQL database. Password must be one-way.
After the login result comes up success or fail, the role of password is finished.
As of Winform cases, you need to deeply consider to secure the connectionstring to connect to SQL database. One possible option might be WCF middleware between Winform application and SQL database.
And for last but very importantly, you must use SSL for secure communication.
It seems you might consider these at later stages.

Decrypting forms authentication token (AES, SHA1) in node js

Has anyone had luck decrypting a .NET forms authentication generated cookie in node js using the crypto library?
I'm using AES for encryption and SHA1 for validation in .NET forms authentication mechanism.
I was wondering if someone had this problem before and solved it?
I played with this and made the following code for Node.js:
var crypto = require('crypto');
var iconv = require('iconv-lite');
function hash(password) {
// your validation key from web.config + 00 at the end
var buf = new Buffer('...00', 'hex');
var hmac = crypto.createHmac('sha1', buf);
// convert password from utf8 to UTF16
var pass = iconv.encode(password, 'utf16le');
hmac.update(pass);
return hmac.digest('base64');
}
console.log(hash('test'));
Use it to compare hashes from your database.
It depends on web.config settings.
You can see the source code of Encryp and Decrypt here with all the different possibilities (Framework20SP1, Framework20SP2, etc)
https://github.com/Microsoft/referencesource/blob/master/System.Web/Security/FormsAuthentication.cs
For example, on Framework20SP1 the cookie looks like: Enc(IV+SerializedTicket+Modifier)+HMAC(Enc(IV+SerializedTicket+Modifier))

C# HMAC Implementation

I want my application to encrypt a user password, and at one time password will be decrypted to be sent to the server for authentication. A friend advise me to use HMAC. I wrote the following code in C#:
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] key = encoding.GetBytes("secret");
HMACSHA256 myhmacsha256 = new HMACSHA256(key);
byte[] hashValue = myhmacsha256.ComputeHash(encoding.GetBytes("text"));
string resultSTR = Convert.ToBase64String(hashValue);
myhmacsha256.Clear();
How to decode the password (resultSTR, in this case)?
An HMAC (Hashed Message Authentication Code) is not encryption, it's hash function (in this case SHA-256) plus some secret key. It's lossy, there is no way to derive the plaintext from the HMAC.
If you want to encrypt some secret data, you should consider using the ProtectedData class instead. More infom including sample code at http://msdn.microsoft.com/en-us/library/system.security.cryptography.protecteddata.aspx

Categories

Resources