mirror of
https://github.com/bitwarden/mobile
synced 2025-12-15 15:53:44 +00:00
centralized crypto utils. keystore with rsa.
This commit is contained in:
@@ -10,6 +10,7 @@ using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Plugin.Settings.Abstractions;
|
||||
using Bit.App.Models.Api;
|
||||
using Bit.App.Utilities;
|
||||
|
||||
namespace Bit.App.Services
|
||||
{
|
||||
@@ -27,7 +28,6 @@ namespace Bit.App.Services
|
||||
private SymmetricCryptoKey _key;
|
||||
private SymmetricCryptoKey _encKey;
|
||||
private SymmetricCryptoKey _legacyEtmKey;
|
||||
private SymmetricCryptoKey _previousKey;
|
||||
private IDictionary<string, SymmetricCryptoKey> _orgKeys;
|
||||
private byte[] _privateKey;
|
||||
|
||||
@@ -257,14 +257,7 @@ namespace Bit.App.Services
|
||||
throw new ArgumentNullException(nameof(plainBytes));
|
||||
}
|
||||
|
||||
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
|
||||
var cryptoKey = provider.CreateSymmetricKey(key.EncKey);
|
||||
var iv = WinRTCrypto.CryptographicBuffer.GenerateRandom(provider.BlockLength);
|
||||
var encryptedBytes = WinRTCrypto.CryptographicEngine.Encrypt(cryptoKey, plainBytes, iv);
|
||||
var mac = key.MacKey != null ? ComputeMacBase64(encryptedBytes, iv, key.MacKey) : null;
|
||||
|
||||
return new CipherString(key.EncryptionType, Convert.ToBase64String(iv),
|
||||
Convert.ToBase64String(encryptedBytes), mac);
|
||||
return Crypto.AesCbcEncrypt(plainBytes, key);
|
||||
}
|
||||
|
||||
public string Decrypt(CipherString encyptedValue, SymmetricCryptoKey key = null)
|
||||
@@ -298,8 +291,8 @@ namespace Bit.App.Services
|
||||
throw new ArgumentNullException(nameof(encyptedValue));
|
||||
}
|
||||
|
||||
if(encyptedValue.EncryptionType == Enums.EncryptionType.AesCbc128_HmacSha256_B64 &&
|
||||
key.EncryptionType == Enums.EncryptionType.AesCbc256_B64)
|
||||
if(encyptedValue.EncryptionType == EncryptionType.AesCbc128_HmacSha256_B64 &&
|
||||
key.EncryptionType == EncryptionType.AesCbc256_B64)
|
||||
{
|
||||
// Old encrypt-then-mac scheme, swap out the key
|
||||
if(_legacyEtmKey == null)
|
||||
@@ -315,21 +308,7 @@ namespace Bit.App.Services
|
||||
throw new ArgumentException("encType unavailable.");
|
||||
}
|
||||
|
||||
if(key.MacKey != null && !string.IsNullOrWhiteSpace(encyptedValue.Mac))
|
||||
{
|
||||
var computedMacBytes = ComputeMac(encyptedValue.CipherTextBytes,
|
||||
encyptedValue.InitializationVectorBytes, key.MacKey);
|
||||
if(!MacsEqual(key.MacKey, computedMacBytes, encyptedValue.MacBytes))
|
||||
{
|
||||
throw new InvalidOperationException("MAC failed.");
|
||||
}
|
||||
}
|
||||
|
||||
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
|
||||
var cryptoKey = provider.CreateSymmetricKey(key.EncKey);
|
||||
var decryptedBytes = WinRTCrypto.CryptographicEngine.Decrypt(cryptoKey, encyptedValue.CipherTextBytes,
|
||||
encyptedValue.InitializationVectorBytes);
|
||||
return decryptedBytes;
|
||||
return Crypto.AesCbcDecrypt(encyptedValue, key);
|
||||
}
|
||||
|
||||
public byte[] RsaDecryptToBytes(CipherString encyptedValue, byte[] privateKey)
|
||||
@@ -362,65 +341,6 @@ namespace Bit.App.Services
|
||||
return decryptedBytes;
|
||||
}
|
||||
|
||||
private string ComputeMacBase64(byte[] ctBytes, byte[] ivBytes, byte[] macKey)
|
||||
{
|
||||
var mac = ComputeMac(ctBytes, ivBytes, macKey);
|
||||
return Convert.ToBase64String(mac);
|
||||
}
|
||||
|
||||
private byte[] ComputeMac(byte[] ctBytes, byte[] ivBytes, byte[] macKey)
|
||||
{
|
||||
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 mac;
|
||||
}
|
||||
|
||||
// Safely compare two MACs in a way that protects against timing attacks (Double HMAC Verification).
|
||||
// ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/
|
||||
private bool MacsEqual(byte[] macKey, byte[] mac1, byte[] mac2)
|
||||
{
|
||||
var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha256);
|
||||
var hasher = algorithm.CreateHash(macKey);
|
||||
|
||||
hasher.Append(mac1);
|
||||
mac1 = hasher.GetValueAndReset();
|
||||
|
||||
hasher.Append(mac2);
|
||||
mac2 = hasher.GetValueAndReset();
|
||||
|
||||
if(mac1.Length != mac2.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i = 0; i < mac2.Length; i++)
|
||||
{
|
||||
if(mac1[i] != mac2[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public SymmetricCryptoKey MakeKeyFromPassword(string password, string salt)
|
||||
{
|
||||
if(password == null)
|
||||
@@ -471,7 +391,7 @@ namespace Bit.App.Services
|
||||
|
||||
public CipherString MakeEncKey(SymmetricCryptoKey key)
|
||||
{
|
||||
var bytes = WinRTCrypto.CryptographicBuffer.GenerateRandom(512 / 8);
|
||||
var bytes = Crypto.RandomBytes(512 / 8);
|
||||
return Encrypt(bytes, key);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user