add pbkdf2 key stretching

This commit is contained in:
Kyle Spearrin 2018-06-13 22:41:18 -04:00
parent a607a7f3ef
commit 7cac07c185
2 changed files with 61 additions and 4 deletions

View file

@ -82,8 +82,25 @@ namespace Bit.App.Services
var encKeyCs = new CipherString(encKey);
try
{
var decBytes = DecryptToBytes(encKeyCs, Key);
_encKey = new SymmetricCryptoKey(decBytes);
byte[] decEncKey = null;
if(encKeyCs.EncryptionType == EncryptionType.AesCbc256_B64)
{
decEncKey = DecryptToBytes(encKeyCs, Key);
}
else if(encKeyCs.EncryptionType == EncryptionType.AesCbc256_HmacSha256_B64)
{
var newKey = StretchKey(Key);
decEncKey = DecryptToBytes(encKeyCs, newKey);
}
else
{
throw new Exception("Unsupported EncKey type");
}
if(decEncKey != null)
{
_encKey = new SymmetricCryptoKey(decEncKey);
}
}
catch
{
@ -462,8 +479,19 @@ namespace Bit.App.Services
public CipherString MakeEncKey(SymmetricCryptoKey key)
{
var bytes = Crypto.RandomBytes(512 / 8);
return Encrypt(bytes, key);
var encKey = Crypto.RandomBytes(64);
// TODO: Remove hardcoded true/false when we're ready to enable key stretching
if(false && key.Key.Length == 32)
{
var newKey = StretchKey(key);
return Encrypt(encKey, newKey);
}
else if(true || key.Key.Length == 64)
{
return Encrypt(encKey, key);
}
throw new Exception("Invalid key size.");
}
// Some users like to copy/paste passwords from external files. Sometimes this can lead to two different
@ -477,5 +505,15 @@ namespace Bit.App.Services
.Replace("\n", " ") // New line => space
.Replace(" ", " "); // No-break space (00A0) => space
}
private SymmetricCryptoKey StretchKey(SymmetricCryptoKey key)
{
var newKey = new byte[64];
var encKey = Crypto.HkdfExpand(key.Key, Encoding.UTF8.GetBytes("enc"), 32);
var macKey = Crypto.HkdfExpand(key.Key, Encoding.UTF8.GetBytes("mac"), 32);
encKey.CopyTo(newKey, 0);
macKey.CopyTo(newKey, 32);
return new SymmetricCryptoKey(newKey);
}
}
}

View file

@ -206,5 +206,24 @@ namespace Bit.App.Utilities
return code.ToString().PadLeft(6, '0');
}
// ref: https://tools.ietf.org/html/rfc5869
public static byte[] HkdfExpand(byte[] prk, byte[] info, int size)
{
var hashLen = 32; // sha256
var okm = new byte[size];
var previousT = new byte[0];
var n = (int)Math.Ceiling((double)size / hashLen);
for(int i = 0; i < n; i++)
{
var t = new byte[previousT.Length + info.Length + 1];
previousT.CopyTo(t, 0);
info.CopyTo(t, previousT.Length);
t[t.Length - 1] = (byte)(i + 1);
previousT = ComputeMac(t, prk);
previousT.CopyTo(okm, i * hashLen);
}
return okm;
}
}
}