mirror of
https://github.com/bitwarden/android.git
synced 2024-12-24 09:58:27 +03:00
Support for encrypt-then-mac
This commit is contained in:
parent
9879f7fa0a
commit
7bc38a35e8
2 changed files with 66 additions and 8 deletions
|
@ -18,7 +18,7 @@ namespace Bit.App.Models
|
||||||
EncryptedString = encryptedString;
|
EncryptedString = encryptedString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CipherString(string initializationVector, string cipherText)
|
public CipherString(string initializationVector, string cipherText, string mac = null)
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(initializationVector))
|
if(string.IsNullOrWhiteSpace(initializationVector))
|
||||||
{
|
{
|
||||||
|
@ -31,13 +31,32 @@ namespace Bit.App.Models
|
||||||
}
|
}
|
||||||
|
|
||||||
EncryptedString = string.Format("{0}|{1}", initializationVector, cipherText);
|
EncryptedString = string.Format("{0}|{1}", initializationVector, cipherText);
|
||||||
|
|
||||||
|
if(!string.IsNullOrWhiteSpace(mac))
|
||||||
|
{
|
||||||
|
EncryptedString = string.Format("{0}|{1}", EncryptedString, mac);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string EncryptedString { get; private set; }
|
public string EncryptedString { get; private set; }
|
||||||
public string InitializationVector { get { return EncryptedString?.Split('|')[0]; } }
|
public string InitializationVector => EncryptedString?.Split('|')[0] ?? null;
|
||||||
public string CipherText { get { return EncryptedString?.Split('|')[1]; } }
|
public string CipherText => EncryptedString?.Split('|')[1] ?? null;
|
||||||
public byte[] InitializationVectorBytes { get { return Convert.FromBase64String(InitializationVector); } }
|
public string Mac
|
||||||
public byte[] CipherTextBytes { get { return Convert.FromBase64String(CipherText); } }
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var pieces = EncryptedString?.Split('|') ?? new string[0];
|
||||||
|
if(pieces.Length > 2)
|
||||||
|
{
|
||||||
|
return pieces[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public byte[] InitializationVectorBytes => Convert.FromBase64String(InitializationVector);
|
||||||
|
public byte[] CipherTextBytes => Convert.FromBase64String(CipherText);
|
||||||
|
public byte[] MacBytes => Mac == null ? null : Convert.FromBase64String(Mac);
|
||||||
|
|
||||||
public string Decrypt()
|
public string Decrypt()
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,6 +106,9 @@ namespace Bit.App.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] EncKey => Key?.Take(16).ToArray();
|
||||||
|
public byte[] MacKey => Key?.Skip(16).Take(16).ToArray();
|
||||||
|
|
||||||
public CipherString Encrypt(string plaintextValue)
|
public CipherString Encrypt(string plaintextValue)
|
||||||
{
|
{
|
||||||
if(Key == null)
|
if(Key == null)
|
||||||
|
@ -121,10 +124,14 @@ namespace Bit.App.Services
|
||||||
var plaintextBytes = Encoding.UTF8.GetBytes(plaintextValue);
|
var plaintextBytes = Encoding.UTF8.GetBytes(plaintextValue);
|
||||||
|
|
||||||
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
|
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
|
||||||
var cryptoKey = provider.CreateSymmetricKey(Key);
|
// TODO: Turn on whenever ready to support encrypt-then-mac
|
||||||
|
var cryptoKey = provider.CreateSymmetricKey(false ? EncKey : Key);
|
||||||
var iv = WinRTCrypto.CryptographicBuffer.GenerateRandom(provider.BlockLength);
|
var iv = WinRTCrypto.CryptographicBuffer.GenerateRandom(provider.BlockLength);
|
||||||
var encryptedBytes = WinRTCrypto.CryptographicEngine.Encrypt(cryptoKey, plaintextBytes, iv);
|
var encryptedBytes = WinRTCrypto.CryptographicEngine.Encrypt(cryptoKey, plaintextBytes, iv);
|
||||||
return new CipherString(Convert.ToBase64String(iv), Convert.ToBase64String(encryptedBytes));
|
// TODO: Turn on whenever ready to support encrypt-then-mac
|
||||||
|
var mac = false ? ComputeMac(encryptedBytes, iv) : null;
|
||||||
|
|
||||||
|
return new CipherString(Convert.ToBase64String(iv), Convert.ToBase64String(encryptedBytes), mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Decrypt(CipherString encyptedValue)
|
public string Decrypt(CipherString encyptedValue)
|
||||||
|
@ -141,9 +148,17 @@ namespace Bit.App.Services
|
||||||
throw new ArgumentNullException(nameof(encyptedValue));
|
throw new ArgumentNullException(nameof(encyptedValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(encyptedValue.Mac != null)
|
||||||
|
{
|
||||||
|
var computedMac = ComputeMac(encyptedValue.CipherTextBytes, encyptedValue.InitializationVectorBytes);
|
||||||
|
if(computedMac != encyptedValue.Mac)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("MAC failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
|
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
|
||||||
var cryptoKey = provider.CreateSymmetricKey(Key);
|
var cryptoKey = provider.CreateSymmetricKey(encyptedValue.Mac != null ? MacKey : Key);
|
||||||
var decryptedBytes = WinRTCrypto.CryptographicEngine.Decrypt(cryptoKey, encyptedValue.CipherTextBytes,
|
var decryptedBytes = WinRTCrypto.CryptographicEngine.Decrypt(cryptoKey, encyptedValue.CipherTextBytes,
|
||||||
encyptedValue.InitializationVectorBytes);
|
encyptedValue.InitializationVectorBytes);
|
||||||
return Encoding.UTF8.GetString(decryptedBytes, 0, decryptedBytes.Length).TrimEnd('\0');
|
return Encoding.UTF8.GetString(decryptedBytes, 0, decryptedBytes.Length).TrimEnd('\0');
|
||||||
|
@ -155,6 +170,30 @@ namespace Bit.App.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string ComputeMac(byte[] ctBytes, byte[] ivBytes)
|
||||||
|
{
|
||||||
|
if(MacKey == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(MacKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ctBytes == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(ctBytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ivBytes == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(ivBytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256);
|
||||||
|
var hasher = algorithm.CreateHash(MacKey);
|
||||||
|
hasher.Append(ivBytes.Concat(ctBytes).ToArray());
|
||||||
|
var mac = hasher.GetValueAndReset();
|
||||||
|
return Convert.ToBase64String(mac);
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] MakeKeyFromPassword(string password, string salt)
|
public byte[] MakeKeyFromPassword(string password, string salt)
|
||||||
{
|
{
|
||||||
if(password == null)
|
if(password == null)
|
||||||
|
|
Loading…
Reference in a new issue