diff --git a/src/App/Services/CryptoService.cs b/src/App/Services/CryptoService.cs index 8f90da048..78d1b1fb7 100644 --- a/src/App/Services/CryptoService.cs +++ b/src/App/Services/CryptoService.cs @@ -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); + } } } diff --git a/src/App/Utilities/Crypto.cs b/src/App/Utilities/Crypto.cs index 55a1cf48a..3cf6b9a6a 100644 --- a/src/App/Utilities/Crypto.cs +++ b/src/App/Utilities/Crypto.cs @@ -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; + } } }