1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-11-29 12:45:20 +01:00

Use CipherByteArray to signify encrypted byte[] (#1366)

* Use CipherByteArray to signify encrypted  byte[]

* Rename CipherString and CipherByteArray to EncString and EncByteArray
This commit is contained in:
Matt Gibson 2021-04-21 15:27:14 -05:00 committed by GitHub
parent 10ea6a86e3
commit a3b4ede8f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 172 additions and 157 deletions

View File

@ -203,7 +203,7 @@ namespace Bit.App.Pages
_vaultTimeoutService.PinProtectedKey); _vaultTimeoutService.PinProtectedKey);
var encKey = await _cryptoService.GetEncKeyAsync(key); var encKey = await _cryptoService.GetEncKeyAsync(key);
var protectedPin = await _storageService.GetAsync<string>(Constants.ProtectedPin); var protectedPin = await _storageService.GetAsync<string>(Constants.ProtectedPin);
var decPin = await _cryptoService.DecryptToUtf8Async(new CipherString(protectedPin), encKey); var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
failed = decPin != Pin; failed = decPin != Pin;
if (!failed) if (!failed)
{ {
@ -272,7 +272,7 @@ namespace Bit.App.Pages
{ {
var protectedPin = await _storageService.GetAsync<string>(Constants.ProtectedPin); var protectedPin = await _storageService.GetAsync<string>(Constants.ProtectedPin);
var encKey = await _cryptoService.GetEncKeyAsync(key); var encKey = await _cryptoService.GetEncKeyAsync(key);
var decPin = await _cryptoService.DecryptToUtf8Async(new CipherString(protectedPin), encKey); var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, _email, var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, _email,
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000)); kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000));
_vaultTimeoutService.PinProtectedKey = await _cryptoService.EncryptAsync(key.Key, pinKey); _vaultTimeoutService.PinProtectedKey = await _cryptoService.EncryptAsync(key.Key, pinKey);

View File

@ -140,7 +140,7 @@ namespace Bit.App.Pages
var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdf, kdfIterations); var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdf, kdfIterations);
var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key); var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key);
Tuple<SymmetricCryptoKey, CipherString> encKey; Tuple<SymmetricCryptoKey, EncString> encKey;
var existingEncKey = await _cryptoService.GetEncKeyAsync(); var existingEncKey = await _cryptoService.GetEncKeyAsync();
if (existingEncKey == null) if (existingEncKey == null)
{ {

View File

@ -1,10 +1,11 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Models.Domain;
namespace Bit.Core.Abstractions namespace Bit.Core.Abstractions
{ {
public interface IAzureFileUploadService public interface IAzureFileUploadService
{ {
Task Upload(string uri, byte[] data, Func<Task<string>> renewalCallback); Task Upload(string uri, EncByteArray data, Func<Task<string>> renewalCallback);
} }
} }

View File

@ -17,11 +17,11 @@ namespace Bit.Core.Abstractions
Task ClearOrgKeysAsync(bool memoryOnly = false); Task ClearOrgKeysAsync(bool memoryOnly = false);
Task ClearPinProtectedKeyAsync(); Task ClearPinProtectedKeyAsync();
Task<byte[]> DecryptFromBytesAsync(byte[] encBytes, SymmetricCryptoKey key); Task<byte[]> DecryptFromBytesAsync(byte[] encBytes, SymmetricCryptoKey key);
Task<byte[]> DecryptToBytesAsync(CipherString cipherString, SymmetricCryptoKey key = null); Task<byte[]> DecryptToBytesAsync(EncString encString, SymmetricCryptoKey key = null);
Task<string> DecryptToUtf8Async(CipherString cipherString, SymmetricCryptoKey key = null); Task<string> DecryptToUtf8Async(EncString encString, SymmetricCryptoKey key = null);
Task<CipherString> EncryptAsync(byte[] plainValue, SymmetricCryptoKey key = null); Task<EncString> EncryptAsync(byte[] plainValue, SymmetricCryptoKey key = null);
Task<CipherString> EncryptAsync(string plainValue, SymmetricCryptoKey key = null); Task<EncString> EncryptAsync(string plainValue, SymmetricCryptoKey key = null);
Task<byte[]> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null); Task<EncByteArray> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null);
Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null); Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null);
Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null); Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null);
Task<SymmetricCryptoKey> GetKeyAsync(); Task<SymmetricCryptoKey> GetKeyAsync();
@ -33,17 +33,17 @@ namespace Bit.Core.Abstractions
Task<bool> HasEncKeyAsync(); Task<bool> HasEncKeyAsync();
Task<string> HashPasswordAsync(string password, SymmetricCryptoKey key); Task<string> HashPasswordAsync(string password, SymmetricCryptoKey key);
Task<bool> HasKeyAsync(); Task<bool> HasKeyAsync();
Task<Tuple<SymmetricCryptoKey, CipherString>> MakeEncKeyAsync(SymmetricCryptoKey key); Task<Tuple<SymmetricCryptoKey, EncString>> MakeEncKeyAsync(SymmetricCryptoKey key);
Task<SymmetricCryptoKey> MakeKeyAsync(string password, string salt, KdfType? kdf, int? kdfIterations); Task<SymmetricCryptoKey> MakeKeyAsync(string password, string salt, KdfType? kdf, int? kdfIterations);
Task<SymmetricCryptoKey> MakeKeyFromPinAsync(string pin, string salt, KdfType kdf, int kdfIterations, Task<SymmetricCryptoKey> MakeKeyFromPinAsync(string pin, string salt, KdfType kdf, int kdfIterations,
CipherString protectedKeyCs = null); EncString protectedKeyEs = null);
Task<Tuple<string, CipherString>> MakeKeyPairAsync(SymmetricCryptoKey key = null); Task<Tuple<string, EncString>> MakeKeyPairAsync(SymmetricCryptoKey key = null);
Task<SymmetricCryptoKey> MakePinKeyAysnc(string pin, string salt, KdfType kdf, int kdfIterations); Task<SymmetricCryptoKey> MakePinKeyAysnc(string pin, string salt, KdfType kdf, int kdfIterations);
Task<Tuple<CipherString, SymmetricCryptoKey>> MakeShareKeyAsync(); Task<Tuple<EncString, SymmetricCryptoKey>> MakeShareKeyAsync();
Task<SymmetricCryptoKey> MakeSendKeyAsync(byte[] keyMaterial); Task<SymmetricCryptoKey> MakeSendKeyAsync(byte[] keyMaterial);
Task<int> RandomNumberAsync(int min, int max); Task<int> RandomNumberAsync(int min, int max);
Task<Tuple<SymmetricCryptoKey, CipherString>> RemakeEncKeyAsync(SymmetricCryptoKey key); Task<Tuple<SymmetricCryptoKey, EncString>> RemakeEncKeyAsync(SymmetricCryptoKey key);
Task<CipherString> RsaEncryptAsync(byte[] data, byte[] publicKey = null); Task<EncString> RsaEncryptAsync(byte[] data, byte[] publicKey = null);
Task SetEncKeyAsync(string encKey); Task SetEncKeyAsync(string encKey);
Task SetEncPrivateKeyAsync(string encPrivateKey); Task SetEncPrivateKeyAsync(string encPrivateKey);
Task SetKeyAsync(SymmetricCryptoKey key); Task SetKeyAsync(SymmetricCryptoKey key);

View File

@ -4,7 +4,7 @@ using Bit.Core.Models.Response;
namespace Bit.Core.Abstractions { namespace Bit.Core.Abstractions {
public interface IFileUploadService { public interface IFileUploadService {
Task UploadCipherAttachmentFileAsync(AttachmentUploadDataResponse uploadData, string fileName, byte[] encryptedFileData); Task UploadCipherAttachmentFileAsync(AttachmentUploadDataResponse uploadData, string fileName, EncByteArray encryptedFileData);
Task UploadSendFileAsync(SendFileUploadDataResponse uploadData, CipherString fileName, byte[] encryptedFileData); Task UploadSendFileAsync(SendFileUploadDataResponse uploadData, EncString fileName, EncByteArray encryptedFileData);
} }
} }

View File

@ -9,12 +9,12 @@ namespace Bit.Core.Abstractions
public interface ISendService public interface ISendService
{ {
void ClearCache(); void ClearCache();
Task<(Send send, byte[] encryptedFileData)> EncryptAsync(SendView model, byte[] fileData, string password, Task<(Send send, EncByteArray encryptedFileData)> EncryptAsync(SendView model, byte[] fileData, string password,
SymmetricCryptoKey key = null); SymmetricCryptoKey key = null);
Task<Send> GetAsync(string id); Task<Send> GetAsync(string id);
Task<List<Send>> GetAllAsync(); Task<List<Send>> GetAllAsync();
Task<List<SendView>> GetAllDecryptedAsync(); Task<List<SendView>> GetAllDecryptedAsync();
Task<string> SaveWithServerAsync(Send sendData, byte[] encryptedFileData); Task<string> SaveWithServerAsync(Send sendData, EncByteArray encryptedFileData);
Task UpsertAsync(params SendData[] send); Task UpsertAsync(params SendData[] send);
Task ReplaceAsync(Dictionary<string, SendData> sends); Task ReplaceAsync(Dictionary<string, SendData> sends);
Task ClearAsync(string userId); Task ClearAsync(string userId);

View File

@ -6,7 +6,7 @@ namespace Bit.Core.Abstractions
{ {
public interface IVaultTimeoutService public interface IVaultTimeoutService
{ {
CipherString PinProtectedKey { get; set; } EncString PinProtectedKey { get; set; }
bool BiometricLocked { get; set; } bool BiometricLocked { get; set; }
Task CheckVaultTimeoutAsync(); Task CheckVaultTimeoutAsync();

View File

@ -30,8 +30,8 @@ namespace Bit.Core.Models.Domain
public string Url { get; set; } public string Url { get; set; }
public string Size { get; set; } public string Size { get; set; }
public string SizeName { get; set; } public string SizeName { get; set; }
public CipherString Key { get; set; } public EncString Key { get; set; }
public CipherString FileName { get; set; } public EncString FileName { get; set; }
public async Task<AttachmentView> DecryptAsync(string orgId) public async Task<AttachmentView> DecryptAsync(string orgId)
{ {

View File

@ -24,12 +24,12 @@ namespace Bit.Core.Models.Domain
BuildDomainModel(this, obj, _map, alreadyEncrypted); BuildDomainModel(this, obj, _map, alreadyEncrypted);
} }
public CipherString CardholderName { get; set; } public EncString CardholderName { get; set; }
public CipherString Brand { get; set; } public EncString Brand { get; set; }
public CipherString Number { get; set; } public EncString Number { get; set; }
public CipherString ExpMonth { get; set; } public EncString ExpMonth { get; set; }
public CipherString ExpYear { get; set; } public EncString ExpYear { get; set; }
public CipherString Code { get; set; } public EncString Code { get; set; }
public Task<CardView> DecryptAsync(string orgId) public Task<CardView> DecryptAsync(string orgId)
{ {

View File

@ -58,8 +58,8 @@ namespace Bit.Core.Models.Domain
public string Id { get; set; } public string Id { get; set; }
public string OrganizationId { get; set; } public string OrganizationId { get; set; }
public string FolderId { get; set; } public string FolderId { get; set; }
public CipherString Name { get; set; } public EncString Name { get; set; }
public CipherString Notes { get; set; } public EncString Notes { get; set; }
public Enums.CipherType Type { get; set; } public Enums.CipherType Type { get; set; }
public bool Favorite { get; set; } public bool Favorite { get; set; }
public bool OrganizationUseTotp { get; set; } public bool OrganizationUseTotp { get; set; }

View File

@ -29,7 +29,7 @@ namespace Bit.Core.Models.Domain
public string Id { get; set; } public string Id { get; set; }
public string OrganizationId { get; set; } public string OrganizationId { get; set; }
public CipherString Name { get; set; } public EncString Name { get; set; }
public string ExternalId { get; set; } public string ExternalId { get; set; }
public bool ReadOnly { get; set; } public bool ReadOnly { get; set; }

View File

@ -24,13 +24,13 @@ namespace Bit.Core.Models.Domain
else else
{ {
domainPropInfo.SetValue(domain, domainPropInfo.SetValue(domain,
dataObjProp != null ? new CipherString(dataObjProp as string) : null, null); dataObjProp != null ? new EncString(dataObjProp as string) : null, null);
} }
} }
} }
protected void BuildDataModel<D, O>(D domain, O dataObj, HashSet<string> map, protected void BuildDataModel<D, O>(D domain, O dataObj, HashSet<string> map,
HashSet<string> notCipherStringList = null) HashSet<string> notEncryptedStringList = null)
where D : Domain where D : Domain
where O : Data.Data where O : Data.Data
{ {
@ -41,13 +41,13 @@ namespace Bit.Core.Models.Domain
var domainPropInfo = domainType.GetProperty(prop); var domainPropInfo = domainType.GetProperty(prop);
var domainProp = domainPropInfo.GetValue(domain); var domainProp = domainPropInfo.GetValue(domain);
var dataObjPropInfo = dataObjType.GetProperty(prop); var dataObjPropInfo = dataObjType.GetProperty(prop);
if (notCipherStringList?.Contains(prop) ?? false) if (notEncryptedStringList?.Contains(prop) ?? false)
{ {
dataObjPropInfo.SetValue(dataObj, domainProp, null); dataObjPropInfo.SetValue(dataObj, domainProp, null);
} }
else else
{ {
dataObjPropInfo.SetValue(dataObj, (domainProp as CipherString)?.EncryptedString, null); dataObjPropInfo.SetValue(dataObj, (domainProp as EncString)?.EncryptedString, null);
} }
} }
} }
@ -62,7 +62,7 @@ namespace Bit.Core.Models.Domain
{ {
var domainPropInfo = domainType.GetProperty(propName); var domainPropInfo = domainType.GetProperty(propName);
string val = null; string val = null;
if (domainPropInfo.GetValue(domain) is CipherString domainProp) if (domainPropInfo.GetValue(domain) is EncString domainProp)
{ {
val = await domainProp.DecryptAsync(orgId, key); val = await domainProp.DecryptAsync(orgId, key);
} }

View File

@ -0,0 +1,12 @@
namespace Bit.Core.Models.Domain
{
public class EncByteArray
{
public byte[] Buffer { get; }
public EncByteArray(byte[] encryptedByteArray)
{
Buffer = encryptedByteArray;
}
}
}

View File

@ -6,11 +6,11 @@ using System.Threading.Tasks;
namespace Bit.Core.Models.Domain namespace Bit.Core.Models.Domain
{ {
public class CipherString public class EncString
{ {
private string _decryptedValue; private string _decryptedValue;
public CipherString(EncryptionType encryptionType, string data, string iv = null, string mac = null) public EncString(EncryptionType encryptionType, string data, string iv = null, string mac = null)
{ {
if (string.IsNullOrWhiteSpace(data)) if (string.IsNullOrWhiteSpace(data))
{ {
@ -37,7 +37,7 @@ namespace Bit.Core.Models.Domain
Mac = mac; Mac = mac;
} }
public CipherString(string encryptedString) public EncString(string encryptedString)
{ {
if (string.IsNullOrWhiteSpace(encryptedString)) if (string.IsNullOrWhiteSpace(encryptedString))
{ {

View File

@ -22,8 +22,8 @@ namespace Bit.Core.Models.Domain
BuildDomainModel(this, obj, _map, alreadyEncrypted); BuildDomainModel(this, obj, _map, alreadyEncrypted);
} }
public CipherString Name { get; set; } public EncString Name { get; set; }
public CipherString Value { get; set; } public EncString Value { get; set; }
public FieldType Type { get; set; } public FieldType Type { get; set; }
public Task<FieldView> DecryptAsync(string orgId) public Task<FieldView> DecryptAsync(string orgId)

View File

@ -21,7 +21,7 @@ namespace Bit.Core.Models.Domain
} }
public string Id { get; set; } public string Id { get; set; }
public CipherString Name { get; set; } public EncString Name { get; set; }
public DateTime RevisionDate { get; set; } public DateTime RevisionDate { get; set; }
public Task<FolderView> DecryptAsync() public Task<FolderView> DecryptAsync()

View File

@ -36,24 +36,24 @@ namespace Bit.Core.Models.Domain
BuildDomainModel(this, obj, _map, alreadyEncrypted); BuildDomainModel(this, obj, _map, alreadyEncrypted);
} }
public CipherString Title { get; set; } public EncString Title { get; set; }
public CipherString FirstName { get; set; } public EncString FirstName { get; set; }
public CipherString MiddleName { get; set; } public EncString MiddleName { get; set; }
public CipherString LastName { get; set; } public EncString LastName { get; set; }
public CipherString Address1 { get; set; } public EncString Address1 { get; set; }
public CipherString Address2 { get; set; } public EncString Address2 { get; set; }
public CipherString Address3 { get; set; } public EncString Address3 { get; set; }
public CipherString City { get; set; } public EncString City { get; set; }
public CipherString State { get; set; } public EncString State { get; set; }
public CipherString PostalCode { get; set; } public EncString PostalCode { get; set; }
public CipherString Country { get; set; } public EncString Country { get; set; }
public CipherString Company { get; set; } public EncString Company { get; set; }
public CipherString Email { get; set; } public EncString Email { get; set; }
public CipherString Phone { get; set; } public EncString Phone { get; set; }
public CipherString SSN { get; set; } public EncString SSN { get; set; }
public CipherString Username { get; set; } public EncString Username { get; set; }
public CipherString PassportNumber { get; set; } public EncString PassportNumber { get; set; }
public CipherString LicenseNumber { get; set; } public EncString LicenseNumber { get; set; }
public Task<IdentityView> DecryptAsync(string orgId) public Task<IdentityView> DecryptAsync(string orgId)
{ {

View File

@ -24,10 +24,10 @@ namespace Bit.Core.Models.Domain
} }
public List<LoginUri> Uris { get; set; } public List<LoginUri> Uris { get; set; }
public CipherString Username { get; set; } public EncString Username { get; set; }
public CipherString Password { get; set; } public EncString Password { get; set; }
public DateTime? PasswordRevisionDate { get; set; } public DateTime? PasswordRevisionDate { get; set; }
public CipherString Totp { get; set; } public EncString Totp { get; set; }
public async Task<LoginView> DecryptAsync(string orgId) public async Task<LoginView> DecryptAsync(string orgId)
{ {

View File

@ -21,7 +21,7 @@ namespace Bit.Core.Models.Domain
BuildDomainModel(this, obj, _map, alreadyEncrypted); BuildDomainModel(this, obj, _map, alreadyEncrypted);
} }
public CipherString Uri { get; set; } public EncString Uri { get; set; }
public UriMatchType? Match { get; set; } public UriMatchType? Match { get; set; }
public Task<LoginUriView> DecryptAsync(string orgId) public Task<LoginUriView> DecryptAsync(string orgId)

View File

@ -21,7 +21,7 @@ namespace Bit.Core.Models.Domain
LastUsedDate = obj.LastUsedDate.GetValueOrDefault(); LastUsedDate = obj.LastUsedDate.GetValueOrDefault();
} }
public CipherString Password { get; set; } public EncString Password { get; set; }
public DateTime LastUsedDate { get; set; } public DateTime LastUsedDate { get; set; }
public Task<PasswordHistoryView> DecryptAsync(string orgId) public Task<PasswordHistoryView> DecryptAsync(string orgId)

View File

@ -15,11 +15,11 @@ namespace Bit.Core.Models.Domain
public string AccessId { get; set; } public string AccessId { get; set; }
public string UserId { get; set; } public string UserId { get; set; }
public SendType Type { get; set; } public SendType Type { get; set; }
public CipherString Name { get; set; } public EncString Name { get; set; }
public CipherString Notes { get; set; } public EncString Notes { get; set; }
public SendFile File { get; set; } public SendFile File { get; set; }
public SendText Text { get; set; } public SendText Text { get; set; }
public CipherString Key { get; set; } public EncString Key { get; set; }
public int? MaxAccessCount { get; set; } public int? MaxAccessCount { get; set; }
public int AccessCount { get; set; } public int AccessCount { get; set; }
public DateTime RevisionDate { get; set; } public DateTime RevisionDate { get; set; }

View File

@ -10,7 +10,7 @@ namespace Bit.Core.Models.Domain
public string Id { get; set; } public string Id { get; set; }
public string Size { get; set; } public string Size { get; set; }
public string SizeName { get; set; } public string SizeName { get; set; }
public CipherString FileName { get; set; } public EncString FileName { get; set; }
public SendFile() : base() { } public SendFile() : base() { }

View File

@ -8,7 +8,7 @@ namespace Bit.Core.Models.Domain
{ {
public class SendText : Domain public class SendText : Domain
{ {
public CipherString Text { get; set; } public EncString Text { get; set; }
public bool Hidden { get; set; } public bool Hidden { get; set; }
public SendText() : base() { } public SendText() : base() { }

View File

@ -8,6 +8,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Models.Domain;
using Bit.Core.Utilities; using Bit.Core.Utilities;
namespace Bit.Core.Services namespace Bit.Core.Services
@ -28,9 +29,9 @@ namespace Bit.Core.Services
}; };
} }
public async Task Upload(string uri, byte[] data, Func<Task<string>> renewalCallback) public async Task Upload(string uri, EncByteArray data, Func<Task<string>> renewalCallback)
{ {
if (data.Length <= MAX_SINGLE_BLOB_UPLOAD_SIZE) if (data?.Buffer?.Length <= MAX_SINGLE_BLOB_UPLOAD_SIZE)
{ {
await AzureUploadBlob(uri, data); await AzureUploadBlob(uri, data);
} }
@ -40,7 +41,7 @@ namespace Bit.Core.Services
} }
} }
private async Task AzureUploadBlob(string uri, byte[] data) private async Task AzureUploadBlob(string uri, EncByteArray data)
{ {
using (var requestMessage = new HttpRequestMessage()) using (var requestMessage = new HttpRequestMessage())
{ {
@ -51,7 +52,7 @@ namespace Bit.Core.Services
requestMessage.Headers.Add("x-ms-version", paramValues["sv"]); requestMessage.Headers.Add("x-ms-version", paramValues["sv"]);
requestMessage.Headers.Add("x-ms-blob-type", "BlockBlob"); requestMessage.Headers.Add("x-ms-blob-type", "BlockBlob");
requestMessage.Content = new ByteArrayContent(data); requestMessage.Content = new ByteArrayContent(data.Buffer);
requestMessage.Version = new Version(1, 0); requestMessage.Version = new Version(1, 0);
requestMessage.Method = HttpMethod.Put; requestMessage.Method = HttpMethod.Put;
requestMessage.RequestUri = uriBuilder.Uri; requestMessage.RequestUri = uriBuilder.Uri;
@ -65,13 +66,13 @@ namespace Bit.Core.Services
} }
} }
private async Task AzureUploadBlocks(string uri, byte[] data, Func<Task<string>> renewalFunc) private async Task AzureUploadBlocks(string uri, EncByteArray data, Func<Task<string>> renewalFunc)
{ {
_httpClient.Timeout = TimeSpan.FromHours(3); _httpClient.Timeout = TimeSpan.FromHours(3);
var baseParams = HttpUtility.ParseQueryString(CoreHelpers.GetUri(uri).Query); var baseParams = HttpUtility.ParseQueryString(CoreHelpers.GetUri(uri).Query);
var blockSize = MaxBlockSize(baseParams["sv"]); var blockSize = MaxBlockSize(baseParams["sv"]);
var blockIndex = 0; var blockIndex = 0;
var numBlocks = Math.Ceiling((decimal)data.Length / blockSize); var numBlocks = Math.Ceiling((decimal)data.Buffer.Length / blockSize);
var blocksStaged = new List<string>(); var blocksStaged = new List<string>();
if (numBlocks > MAX_BLOCKS_PER_BLOB) if (numBlocks > MAX_BLOCKS_PER_BLOB)
@ -95,7 +96,7 @@ namespace Bit.Core.Services
requestMessage.Headers.Add("x-ms-version", baseParams["sv"]); requestMessage.Headers.Add("x-ms-version", baseParams["sv"]);
requestMessage.Headers.Add("x-ms-blob-type", "BlockBlob"); requestMessage.Headers.Add("x-ms-blob-type", "BlockBlob");
requestMessage.Content = new ByteArrayContent(data.Skip(blockIndex * blockSize).Take(blockSize).ToArray()); requestMessage.Content = new ByteArrayContent(data.Buffer.Skip(blockIndex * blockSize).Take(blockSize).ToArray());
requestMessage.Version = new Version(1, 0); requestMessage.Version = new Version(1, 0);
requestMessage.Method = HttpMethod.Put; requestMessage.Method = HttpMethod.Put;
requestMessage.RequestUri = blockUriBuilder.Uri; requestMessage.RequestUri = blockUriBuilder.Uri;

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Models.Domain;
namespace Bit.Core.Services namespace Bit.Core.Services
{ {
@ -13,11 +14,11 @@ namespace Bit.Core.Services
private readonly ApiService _apiService; private readonly ApiService _apiService;
public async Task Upload(string encryptedFileName, byte[] encryptedFileData, Func<MultipartFormDataContent, Task> apiCall) public async Task Upload(string encryptedFileName, EncByteArray encryptedFileData, Func<MultipartFormDataContent, Task> apiCall)
{ {
var fd = new MultipartFormDataContent($"--BWMobileFormBoundary{DateTime.UtcNow.Ticks}") var fd = new MultipartFormDataContent($"--BWMobileFormBoundary{DateTime.UtcNow.Ticks}")
{ {
{ new ByteArrayContent(encryptedFileData), "data", encryptedFileName } { new ByteArrayContent(encryptedFileData.Buffer), "data", encryptedFileName }
}; };
await apiCall(fd); await apiCall(fd);

View File

@ -568,7 +568,7 @@ namespace Bit.Core.Services
{ {
Key = orgEncAttachmentKey.EncryptedString, Key = orgEncAttachmentKey.EncryptedString,
FileName = encFileName.EncryptedString, FileName = encFileName.EncryptedString,
FileSize = encFileData.Length, FileSize = encFileData.Buffer.Length,
}; };
var uploadDataResponse = await _apiService.PostCipherAttachmentAsync(cipher.Id, request); var uploadDataResponse = await _apiService.PostCipherAttachmentAsync(cipher.Id, request);
@ -588,12 +588,12 @@ namespace Bit.Core.Services
[Obsolete("Mar 25 2021: This method has been deprecated in favor of direct uploads. This method still exists for backward compatibility with old server versions.")] [Obsolete("Mar 25 2021: This method has been deprecated in favor of direct uploads. This method still exists for backward compatibility with old server versions.")]
private async Task<CipherResponse> LegacyServerAttachmentFileUploadAsync(string cipherId, private async Task<CipherResponse> LegacyServerAttachmentFileUploadAsync(string cipherId,
CipherString encFileName, byte[] encFileData, CipherString key) EncString encFileName, EncByteArray encFileData, EncString key)
{ {
var boundary = string.Concat("--BWMobileFormBoundary", DateTime.UtcNow.Ticks); var boundary = string.Concat("--BWMobileFormBoundary", DateTime.UtcNow.Ticks);
var fd = new MultipartFormDataContent(boundary); var fd = new MultipartFormDataContent(boundary);
fd.Add(new StringContent(key.EncryptedString), "key"); fd.Add(new StringContent(key.EncryptedString), "key");
fd.Add(new StreamContent(new MemoryStream(encFileData)), "data", encFileName.EncryptedString); fd.Add(new StreamContent(new MemoryStream(encFileData.Buffer)), "data", encFileName.EncryptedString);
return await _apiService.PostCipherAttachmentLegacyAsync(cipherId, fd); return await _apiService.PostCipherAttachmentLegacyAsync(cipherId, fd);
} }
@ -828,7 +828,7 @@ namespace Bit.Core.Services
var boundary = string.Concat("--BWMobileFormBoundary", DateTime.UtcNow.Ticks); var boundary = string.Concat("--BWMobileFormBoundary", DateTime.UtcNow.Ticks);
var fd = new MultipartFormDataContent(boundary); var fd = new MultipartFormDataContent(boundary);
fd.Add(new StringContent(dataEncKey.Item2.EncryptedString), "key"); fd.Add(new StringContent(dataEncKey.Item2.EncryptedString), "key");
fd.Add(new StreamContent(new MemoryStream(encData)), "data", encFileName.EncryptedString); fd.Add(new StreamContent(new MemoryStream(encData.Buffer)), "data", encFileName.EncryptedString);
await _apiService.PostShareCipherAttachmentAsync(cipherId, attachmentView.Id, fd, organizationId); await _apiService.PostShareCipherAttachmentAsync(cipherId, attachmentView.Id, fd, organizationId);
} }
@ -1037,7 +1037,7 @@ namespace Bit.Core.Services
{ {
var modelPropInfo = modelType.GetProperty(propName); var modelPropInfo = modelType.GetProperty(propName);
var modelProp = modelPropInfo.GetValue(model) as string; var modelProp = modelPropInfo.GetValue(model) as string;
CipherString val = null; EncString val = null;
if (!string.IsNullOrWhiteSpace(modelProp)) if (!string.IsNullOrWhiteSpace(modelProp))
{ {
val = await _cryptoService.EncryptAsync(modelProp, key); val = await _cryptoService.EncryptAsync(modelProp, key);

View File

@ -148,7 +148,7 @@ namespace Bit.Core.Services
} }
byte[] decEncKey = null; byte[] decEncKey = null;
var encKeyCipher = new CipherString(encKey); var encKeyCipher = new EncString(encKey);
if (encKeyCipher.EncryptionType == EncryptionType.AesCbc256_B64) if (encKeyCipher.EncryptionType == EncryptionType.AesCbc256_B64)
{ {
decEncKey = await DecryptToBytesAsync(encKeyCipher, key); decEncKey = await DecryptToBytesAsync(encKeyCipher, key);
@ -205,7 +205,7 @@ namespace Bit.Core.Services
{ {
return null; return null;
} }
_privateKey = await DecryptToBytesAsync(new CipherString(encPrivateKey), null); _privateKey = await DecryptToBytesAsync(new EncString(encPrivateKey), null);
return _privateKey; return _privateKey;
} }
@ -389,7 +389,7 @@ namespace Bit.Core.Services
} }
public async Task<SymmetricCryptoKey> MakeKeyFromPinAsync(string pin, string salt, public async Task<SymmetricCryptoKey> MakeKeyFromPinAsync(string pin, string salt,
KdfType kdf, int kdfIterations, CipherString protectedKeyCs = null) KdfType kdf, int kdfIterations, EncString protectedKeyCs = null)
{ {
if (protectedKeyCs == null) if (protectedKeyCs == null)
{ {
@ -398,27 +398,27 @@ namespace Bit.Core.Services
{ {
throw new Exception("No PIN protected key found."); throw new Exception("No PIN protected key found.");
} }
protectedKeyCs = new CipherString(pinProtectedKey); protectedKeyCs = new EncString(pinProtectedKey);
} }
var pinKey = await MakePinKeyAysnc(pin, salt, kdf, kdfIterations); var pinKey = await MakePinKeyAysnc(pin, salt, kdf, kdfIterations);
var decKey = await DecryptToBytesAsync(protectedKeyCs, pinKey); var decKey = await DecryptToBytesAsync(protectedKeyCs, pinKey);
return new SymmetricCryptoKey(decKey); return new SymmetricCryptoKey(decKey);
} }
public async Task<Tuple<CipherString, SymmetricCryptoKey>> MakeShareKeyAsync() public async Task<Tuple<EncString, SymmetricCryptoKey>> MakeShareKeyAsync()
{ {
var shareKey = await _cryptoFunctionService.RandomBytesAsync(64); var shareKey = await _cryptoFunctionService.RandomBytesAsync(64);
var publicKey = await GetPublicKeyAsync(); var publicKey = await GetPublicKeyAsync();
var encShareKey = await RsaEncryptAsync(shareKey, publicKey); var encShareKey = await RsaEncryptAsync(shareKey, publicKey);
return new Tuple<CipherString, SymmetricCryptoKey>(encShareKey, new SymmetricCryptoKey(shareKey)); return new Tuple<EncString, SymmetricCryptoKey>(encShareKey, new SymmetricCryptoKey(shareKey));
} }
public async Task<Tuple<string, CipherString>> MakeKeyPairAsync(SymmetricCryptoKey key = null) public async Task<Tuple<string, EncString>> MakeKeyPairAsync(SymmetricCryptoKey key = null)
{ {
var keyPair = await _cryptoFunctionService.RsaGenerateKeyPairAsync(2048); var keyPair = await _cryptoFunctionService.RsaGenerateKeyPairAsync(2048);
var publicB64 = Convert.ToBase64String(keyPair.Item1); var publicB64 = Convert.ToBase64String(keyPair.Item1);
var privateEnc = await EncryptAsync(keyPair.Item2, key); var privateEnc = await EncryptAsync(keyPair.Item2, key);
return new Tuple<string, CipherString>(publicB64, privateEnc); return new Tuple<string, EncString>(publicB64, privateEnc);
} }
public async Task<SymmetricCryptoKey> MakePinKeyAysnc(string pin, string salt, KdfType kdf, int kdfIterations) public async Task<SymmetricCryptoKey> MakePinKeyAysnc(string pin, string salt, KdfType kdf, int kdfIterations)
@ -447,20 +447,20 @@ namespace Bit.Core.Services
return Convert.ToBase64String(hash); return Convert.ToBase64String(hash);
} }
public async Task<Tuple<SymmetricCryptoKey, CipherString>> MakeEncKeyAsync(SymmetricCryptoKey key) public async Task<Tuple<SymmetricCryptoKey, EncString>> MakeEncKeyAsync(SymmetricCryptoKey key)
{ {
var theKey = await GetKeyForEncryptionAsync(key); var theKey = await GetKeyForEncryptionAsync(key);
var encKey = await _cryptoFunctionService.RandomBytesAsync(64); var encKey = await _cryptoFunctionService.RandomBytesAsync(64);
return await BuildEncKeyAsync(theKey, encKey); return await BuildEncKeyAsync(theKey, encKey);
} }
public async Task<Tuple<SymmetricCryptoKey, CipherString>> RemakeEncKeyAsync(SymmetricCryptoKey key) public async Task<Tuple<SymmetricCryptoKey, EncString>> RemakeEncKeyAsync(SymmetricCryptoKey key)
{ {
var encKey = await GetEncKeyAsync(); var encKey = await GetEncKeyAsync();
return await BuildEncKeyAsync(key, encKey.Key); return await BuildEncKeyAsync(key, encKey.Key);
} }
public async Task<CipherString> EncryptAsync(string plainValue, SymmetricCryptoKey key = null) public async Task<EncString> EncryptAsync(string plainValue, SymmetricCryptoKey key = null)
{ {
if (plainValue == null) if (plainValue == null)
{ {
@ -469,7 +469,7 @@ namespace Bit.Core.Services
return await EncryptAsync(Encoding.UTF8.GetBytes(plainValue), key); return await EncryptAsync(Encoding.UTF8.GetBytes(plainValue), key);
} }
public async Task<CipherString> EncryptAsync(byte[] plainValue, SymmetricCryptoKey key = null) public async Task<EncString> EncryptAsync(byte[] plainValue, SymmetricCryptoKey key = null)
{ {
if (plainValue == null) if (plainValue == null)
{ {
@ -479,10 +479,10 @@ namespace Bit.Core.Services
var iv = Convert.ToBase64String(encObj.Iv); var iv = Convert.ToBase64String(encObj.Iv);
var data = Convert.ToBase64String(encObj.Data); var data = Convert.ToBase64String(encObj.Data);
var mac = encObj.Mac != null ? Convert.ToBase64String(encObj.Mac) : null; var mac = encObj.Mac != null ? Convert.ToBase64String(encObj.Mac) : null;
return new CipherString(encObj.Key.EncType, data, iv, mac); return new EncString(encObj.Key.EncType, data, iv, mac);
} }
public async Task<byte[]> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null) public async Task<EncByteArray> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null)
{ {
var encValue = await AesEncryptAsync(plainValue, key); var encValue = await AesEncryptAsync(plainValue, key);
var macLen = 0; var macLen = 0;
@ -498,10 +498,10 @@ namespace Bit.Core.Services
Buffer.BlockCopy(encValue.Mac, 0, encBytes, 1 + encValue.Iv.Length, encValue.Mac.Length); Buffer.BlockCopy(encValue.Mac, 0, encBytes, 1 + encValue.Iv.Length, encValue.Mac.Length);
} }
Buffer.BlockCopy(encValue.Data, 0, encBytes, 1 + encValue.Iv.Length + macLen, encValue.Data.Length); Buffer.BlockCopy(encValue.Data, 0, encBytes, 1 + encValue.Iv.Length + macLen, encValue.Data.Length);
return encBytes; return new EncByteArray(encBytes);
} }
public async Task<CipherString> RsaEncryptAsync(byte[] data, byte[] publicKey = null) public async Task<EncString> RsaEncryptAsync(byte[] data, byte[] publicKey = null)
{ {
if (publicKey == null) if (publicKey == null)
{ {
@ -512,21 +512,21 @@ namespace Bit.Core.Services
throw new Exception("Public key unavailable."); throw new Exception("Public key unavailable.");
} }
var encBytes = await _cryptoFunctionService.RsaEncryptAsync(data, publicKey, CryptoHashAlgorithm.Sha1); var encBytes = await _cryptoFunctionService.RsaEncryptAsync(data, publicKey, CryptoHashAlgorithm.Sha1);
return new CipherString(EncryptionType.Rsa2048_OaepSha1_B64, Convert.ToBase64String(encBytes)); return new EncString(EncryptionType.Rsa2048_OaepSha1_B64, Convert.ToBase64String(encBytes));
} }
public async Task<byte[]> DecryptToBytesAsync(CipherString cipherString, SymmetricCryptoKey key = null) public async Task<byte[]> DecryptToBytesAsync(EncString encString, SymmetricCryptoKey key = null)
{ {
var iv = Convert.FromBase64String(cipherString.Iv); var iv = Convert.FromBase64String(encString.Iv);
var data = Convert.FromBase64String(cipherString.Data); var data = Convert.FromBase64String(encString.Data);
var mac = !string.IsNullOrWhiteSpace(cipherString.Mac) ? Convert.FromBase64String(cipherString.Mac) : null; var mac = !string.IsNullOrWhiteSpace(encString.Mac) ? Convert.FromBase64String(encString.Mac) : null;
return await AesDecryptToBytesAsync(cipherString.EncryptionType, data, iv, mac, key); return await AesDecryptToBytesAsync(encString.EncryptionType, data, iv, mac, key);
} }
public async Task<string> DecryptToUtf8Async(CipherString cipherString, SymmetricCryptoKey key = null) public async Task<string> DecryptToUtf8Async(EncString encString, SymmetricCryptoKey key = null)
{ {
return await AesDecryptToUtf8Async(cipherString.EncryptionType, cipherString.Data, return await AesDecryptToUtf8Async(encString.EncryptionType, encString.Data,
cipherString.Iv, cipherString.Mac, key); encString.Iv, encString.Mac, key);
} }
public async Task<byte[]> DecryptFromBytesAsync(byte[] encBytes, SymmetricCryptoKey key) public async Task<byte[]> DecryptFromBytesAsync(byte[] encBytes, SymmetricCryptoKey key)
@ -809,10 +809,10 @@ namespace Bit.Core.Services
return phrase; return phrase;
} }
private async Task<Tuple<SymmetricCryptoKey, CipherString>> BuildEncKeyAsync(SymmetricCryptoKey key, private async Task<Tuple<SymmetricCryptoKey, EncString>> BuildEncKeyAsync(SymmetricCryptoKey key,
byte[] encKey) byte[] encKey)
{ {
CipherString encKeyEnc = null; EncString encKeyEnc = null;
if (key.Key.Length == 32) if (key.Key.Length == 32)
{ {
var newKey = await StretchKeyAsync(key); var newKey = await StretchKeyAsync(key);
@ -826,7 +826,7 @@ namespace Bit.Core.Services
{ {
throw new Exception("Invalid key size."); throw new Exception("Invalid key size.");
} }
return new Tuple<SymmetricCryptoKey, CipherString>(new SymmetricCryptoKey(encKey), encKeyEnc); return new Tuple<SymmetricCryptoKey, EncString>(new SymmetricCryptoKey(encKey), encKeyEnc);
} }
private class EncryptedObject private class EncryptedObject

View File

@ -20,7 +20,7 @@ namespace Bit.Core.Services {
private readonly ApiService _apiService; private readonly ApiService _apiService;
public async Task UploadCipherAttachmentFileAsync(AttachmentUploadDataResponse uploadData, public async Task UploadCipherAttachmentFileAsync(AttachmentUploadDataResponse uploadData,
string encryptedFileName, byte[] encryptedFileData) string encryptedFileName, EncByteArray encryptedFileData)
{ {
try try
{ {
@ -48,7 +48,7 @@ namespace Bit.Core.Services {
} }
} }
public async Task UploadSendFileAsync(SendFileUploadDataResponse uploadData, CipherString fileName, byte[] encryptedFileData) public async Task UploadSendFileAsync(SendFileUploadDataResponse uploadData, EncString fileName, EncByteArray encryptedFileData)
{ {
try try
{ {

View File

@ -633,7 +633,7 @@ namespace Bit.Core.Services
} }
var tasks = history.Select(async item => var tasks = history.Select(async item =>
{ {
var decrypted = await _cryptoService.DecryptToUtf8Async(new CipherString(item.Password)); var decrypted = await _cryptoService.DecryptToUtf8Async(new EncString(item.Password));
return new GeneratedPasswordHistory return new GeneratedPasswordHistory
{ {
Password = decrypted, Password = decrypted,

View File

@ -81,7 +81,7 @@ namespace Bit.Core.Services
await DeleteAsync(id); await DeleteAsync(id);
} }
public async Task<(Send send, byte[] encryptedFileData)> EncryptAsync(SendView model, byte[] fileData, public async Task<(Send send, EncByteArray encryptedFileData)> EncryptAsync(SendView model, byte[] fileData,
string password, SymmetricCryptoKey key = null) string password, SymmetricCryptoKey key = null)
{ {
if (model.Key == null) if (model.Key == null)
@ -103,7 +103,7 @@ namespace Bit.Core.Services
Notes = await _cryptoService.EncryptAsync(model.Notes, model.CryptoKey), Notes = await _cryptoService.EncryptAsync(model.Notes, model.CryptoKey),
HideEmail = model.HideEmail HideEmail = model.HideEmail
}; };
byte[] encryptedFileData = null; EncByteArray encryptedFileData = null;
if (password != null) if (password != null)
{ {
@ -197,9 +197,9 @@ namespace Bit.Core.Services
_decryptedSendsCache = null; _decryptedSendsCache = null;
} }
public async Task<string> SaveWithServerAsync(Send send, byte[] encryptedFileData) public async Task<string> SaveWithServerAsync(Send send, EncByteArray encryptedFileData)
{ {
var request = new SendRequest(send, encryptedFileData?.LongLength); var request = new SendRequest(send, encryptedFileData?.Buffer?.LongLength);
SendResponse response = default; SendResponse response = default;
if (send.Id == null) if (send.Id == null)
{ {
@ -243,11 +243,11 @@ namespace Bit.Core.Services
} }
[Obsolete("Mar 25 2021: This method has been deprecated in favor of direct uploads. This method still exists for backward compatibility with old server versions.")] [Obsolete("Mar 25 2021: This method has been deprecated in favor of direct uploads. This method still exists for backward compatibility with old server versions.")]
private async Task<SendResponse> LegacyServerSendFileUpload(SendRequest request, Send send, byte[] encryptedFileData) { private async Task<SendResponse> LegacyServerSendFileUpload(SendRequest request, Send send, EncByteArray encryptedFileData) {
var fd = new MultipartFormDataContent($"--BWMobileFormBoundary{DateTime.UtcNow.Ticks}") var fd = new MultipartFormDataContent($"--BWMobileFormBoundary{DateTime.UtcNow.Ticks}")
{ {
{ new StringContent(JsonConvert.SerializeObject(request)), "model" }, { new StringContent(JsonConvert.SerializeObject(request)), "model" },
{ new ByteArrayContent(encryptedFileData), "data", send.File.FileName.EncryptedString } { new ByteArrayContent(encryptedFileData.Buffer), "data", send.File.FileName.EncryptedString }
}; };
return await _apiService.PostSendFileAsync(fd); return await _apiService.PostSendFileAsync(fd);

View File

@ -48,7 +48,7 @@ namespace Bit.Core.Services
_loggedOutCallback = loggedOutCallback; _loggedOutCallback = loggedOutCallback;
} }
public CipherString PinProtectedKey { get; set; } = null; public EncString PinProtectedKey { get; set; } = null;
public bool BiometricLocked { get; set; } = true; public bool BiometricLocked { get; set; } = true;
public async Task<bool> IsLockedAsync() public async Task<bool> IsLockedAsync()

View File

@ -140,7 +140,7 @@ namespace Bit.iOS.Core.Controllers
_vaultTimeoutService.PinProtectedKey); _vaultTimeoutService.PinProtectedKey);
var encKey = await _cryptoService.GetEncKeyAsync(key); var encKey = await _cryptoService.GetEncKeyAsync(key);
var protectedPin = await _storageService.GetAsync<string>(Bit.Core.Constants.ProtectedPin); var protectedPin = await _storageService.GetAsync<string>(Bit.Core.Constants.ProtectedPin);
var decPin = await _cryptoService.DecryptToUtf8Async(new CipherString(protectedPin), encKey); var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
failed = decPin != inputtedValue; failed = decPin != inputtedValue;
if (!failed) if (!failed)
{ {
@ -191,7 +191,7 @@ namespace Bit.iOS.Core.Controllers
{ {
var protectedPin = await _storageService.GetAsync<string>(Bit.Core.Constants.ProtectedPin); var protectedPin = await _storageService.GetAsync<string>(Bit.Core.Constants.ProtectedPin);
var encKey = await _cryptoService.GetEncKeyAsync(key2); var encKey = await _cryptoService.GetEncKeyAsync(key2);
var decPin = await _cryptoService.DecryptToUtf8Async(new CipherString(protectedPin), encKey); var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, email, var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, email,
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000)); kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000));
_vaultTimeoutService.PinProtectedKey = await _cryptoService.EncryptAsync(key2.Key, pinKey); _vaultTimeoutService.PinProtectedKey = await _cryptoService.EncryptAsync(key2.Key, pinKey);

View File

@ -40,17 +40,17 @@ namespace Bit.Core.Test.Models.Domain
var prefix = "decrypted_"; var prefix = "decrypted_";
var prefixBytes = Encoding.UTF8.GetBytes(prefix); var prefixBytes = Encoding.UTF8.GetBytes(prefix);
cryptoService.DecryptToBytesAsync(Arg.Any<CipherString>(), Arg.Any<SymmetricCryptoKey>()) cryptoService.DecryptToBytesAsync(Arg.Any<EncString>(), Arg.Any<SymmetricCryptoKey>())
.Returns(info => prefixBytes.Concat(Encoding.UTF8.GetBytes(((CipherString)info[0]).EncryptedString)).ToArray()); .Returns(info => prefixBytes.Concat(Encoding.UTF8.GetBytes(((EncString)info[0]).EncryptedString)).ToArray());
cryptoService.DecryptFromBytesAsync(Arg.Any<byte[]>(), Arg.Any<SymmetricCryptoKey>()) cryptoService.DecryptFromBytesAsync(Arg.Any<byte[]>(), Arg.Any<SymmetricCryptoKey>())
.Returns(info => prefixBytes.Concat((byte[])info[0]).ToArray()); .Returns(info => prefixBytes.Concat((byte[])info[0]).ToArray());
cryptoService.DecryptToUtf8Async(Arg.Any<CipherString>(), Arg.Any<SymmetricCryptoKey>()) cryptoService.DecryptToUtf8Async(Arg.Any<EncString>(), Arg.Any<SymmetricCryptoKey>())
.Returns(info => $"{prefix}{((CipherString)info[0]).EncryptedString}"); .Returns(info => $"{prefix}{((EncString)info[0]).EncryptedString}");
ServiceContainer.Register("cryptoService", cryptoService); ServiceContainer.Register("cryptoService", cryptoService);
var view = await send.DecryptAsync(); var view = await send.DecryptAsync();
string expectedDecryptionString(CipherString encryptedString) => string expectedDecryptionString(EncString encryptedString) =>
encryptedString?.EncryptedString == null ? null : $"{prefix}{encryptedString.EncryptedString}"; encryptedString?.EncryptedString == null ? null : $"{prefix}{encryptedString.EncryptedString}";
TestHelper.AssertPropertyEqual(send, view, "Name", "Notes", "File", "Text", "Key", "UserId"); TestHelper.AssertPropertyEqual(send, view, "Name", "Notes", "File", "Text", "Key", "UserId");

View File

@ -22,17 +22,17 @@ namespace Bit.Core.Test.Services
{ {
[Theory, UserCipherAutoData] [Theory, UserCipherAutoData]
public async Task SaveWithServerAsync_PrefersFileUploadService(SutProvider<CipherService> sutProvider, public async Task SaveWithServerAsync_PrefersFileUploadService(SutProvider<CipherService> sutProvider,
Cipher cipher, string fileName, byte[] data, AttachmentUploadDataResponse uploadDataResponse, CipherString encKey) Cipher cipher, string fileName, EncByteArray data, AttachmentUploadDataResponse uploadDataResponse, EncString encKey)
{ {
sutProvider.GetDependency<ICryptoService>().EncryptAsync(fileName, Arg.Any<SymmetricCryptoKey>()) sutProvider.GetDependency<ICryptoService>().EncryptAsync(fileName, Arg.Any<SymmetricCryptoKey>())
.Returns(new CipherString(fileName)); .Returns(new EncString(fileName));
sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data, Arg.Any<SymmetricCryptoKey>()) sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data.Buffer, Arg.Any<SymmetricCryptoKey>())
.Returns(data); .Returns(data);
sutProvider.GetDependency<ICryptoService>().MakeEncKeyAsync(Arg.Any<SymmetricCryptoKey>()).Returns(new Tuple<SymmetricCryptoKey, CipherString>(null, encKey)); sutProvider.GetDependency<ICryptoService>().MakeEncKeyAsync(Arg.Any<SymmetricCryptoKey>()).Returns(new Tuple<SymmetricCryptoKey, EncString>(null, encKey));
sutProvider.GetDependency<IApiService>().PostCipherAttachmentAsync(cipher.Id, Arg.Any<AttachmentRequest>()) sutProvider.GetDependency<IApiService>().PostCipherAttachmentAsync(cipher.Id, Arg.Any<AttachmentRequest>())
.Returns(uploadDataResponse); .Returns(uploadDataResponse);
await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data); await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data.Buffer);
await sutProvider.GetDependency<IFileUploadService>().Received(1) await sutProvider.GetDependency<IFileUploadService>().Received(1)
.UploadCipherAttachmentFileAsync(uploadDataResponse, fileName, data); .UploadCipherAttachmentFileAsync(uploadDataResponse, fileName, data);
@ -42,20 +42,20 @@ namespace Bit.Core.Test.Services
[InlineUserCipherAutoData(HttpStatusCode.NotFound)] [InlineUserCipherAutoData(HttpStatusCode.NotFound)]
[InlineUserCipherAutoData(HttpStatusCode.MethodNotAllowed)] [InlineUserCipherAutoData(HttpStatusCode.MethodNotAllowed)]
public async Task SaveWithServerAsync_FallsBackToLegacyFormData(HttpStatusCode statusCode, public async Task SaveWithServerAsync_FallsBackToLegacyFormData(HttpStatusCode statusCode,
SutProvider<CipherService> sutProvider, Cipher cipher, string fileName, byte[] data, SutProvider<CipherService> sutProvider, Cipher cipher, string fileName, EncByteArray data,
CipherResponse response, CipherString encKey) CipherResponse response, EncString encKey)
{ {
sutProvider.GetDependency<ICryptoService>().EncryptAsync(fileName, Arg.Any<SymmetricCryptoKey>()) sutProvider.GetDependency<ICryptoService>().EncryptAsync(fileName, Arg.Any<SymmetricCryptoKey>())
.Returns(new CipherString(fileName)); .Returns(new EncString(fileName));
sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data, Arg.Any<SymmetricCryptoKey>()) sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data.Buffer, Arg.Any<SymmetricCryptoKey>())
.Returns(data); .Returns(data);
sutProvider.GetDependency<ICryptoService>().MakeEncKeyAsync(Arg.Any<SymmetricCryptoKey>()).Returns(new Tuple<SymmetricCryptoKey, CipherString>(null, encKey)); sutProvider.GetDependency<ICryptoService>().MakeEncKeyAsync(Arg.Any<SymmetricCryptoKey>()).Returns(new Tuple<SymmetricCryptoKey, EncString>(null, encKey));
sutProvider.GetDependency<IApiService>().PostCipherAttachmentAsync(cipher.Id, Arg.Any<AttachmentRequest>()) sutProvider.GetDependency<IApiService>().PostCipherAttachmentAsync(cipher.Id, Arg.Any<AttachmentRequest>())
.Throws(new ApiException(new ErrorResponse {StatusCode = statusCode})); .Throws(new ApiException(new ErrorResponse {StatusCode = statusCode}));
sutProvider.GetDependency<IApiService>().PostCipherAttachmentLegacyAsync(cipher.Id, Arg.Any<MultipartFormDataContent>()) sutProvider.GetDependency<IApiService>().PostCipherAttachmentLegacyAsync(cipher.Id, Arg.Any<MultipartFormDataContent>())
.Returns(response); .Returns(response);
await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data); await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data.Buffer);
await sutProvider.GetDependency<IApiService>().Received(1) await sutProvider.GetDependency<IApiService>().Received(1)
.PostCipherAttachmentLegacyAsync(cipher.Id, Arg.Any<MultipartFormDataContent>()); .PostCipherAttachmentLegacyAsync(cipher.Id, Arg.Any<MultipartFormDataContent>());
@ -63,20 +63,20 @@ namespace Bit.Core.Test.Services
[Theory, UserCipherAutoData] [Theory, UserCipherAutoData]
public async Task SaveWithServerAsync_ThrowsOnBadRequestApiException(SutProvider<CipherService> sutProvider, public async Task SaveWithServerAsync_ThrowsOnBadRequestApiException(SutProvider<CipherService> sutProvider,
Cipher cipher, string fileName, byte[] data, CipherString encKey) Cipher cipher, string fileName, EncByteArray data, EncString encKey)
{ {
sutProvider.GetDependency<ICryptoService>().EncryptAsync(fileName, Arg.Any<SymmetricCryptoKey>()) sutProvider.GetDependency<ICryptoService>().EncryptAsync(fileName, Arg.Any<SymmetricCryptoKey>())
.Returns(new CipherString(fileName)); .Returns(new EncString(fileName));
sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data, Arg.Any<SymmetricCryptoKey>()) sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data.Buffer, Arg.Any<SymmetricCryptoKey>())
.Returns(data); .Returns(data);
sutProvider.GetDependency<ICryptoService>().MakeEncKeyAsync(Arg.Any<SymmetricCryptoKey>()) sutProvider.GetDependency<ICryptoService>().MakeEncKeyAsync(Arg.Any<SymmetricCryptoKey>())
.Returns(new Tuple<SymmetricCryptoKey, CipherString>(null, encKey)); .Returns(new Tuple<SymmetricCryptoKey, EncString>(null, encKey));
var expectedException = new ApiException(new ErrorResponse { StatusCode = HttpStatusCode.BadRequest }); var expectedException = new ApiException(new ErrorResponse { StatusCode = HttpStatusCode.BadRequest });
sutProvider.GetDependency<IApiService>().PostCipherAttachmentAsync(cipher.Id, Arg.Any<AttachmentRequest>()) sutProvider.GetDependency<IApiService>().PostCipherAttachmentAsync(cipher.Id, Arg.Any<AttachmentRequest>())
.Throws(expectedException); .Throws(expectedException);
var actualException = await Assert.ThrowsAsync<ApiException>(async () => var actualException = await Assert.ThrowsAsync<ApiException>(async () =>
await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data)); await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data.Buffer));
Assert.Equal(expectedException.Error.StatusCode, actualException.Error.StatusCode); Assert.Equal(expectedException.Error.StatusCode, actualException.Error.StatusCode);
} }
@ -90,7 +90,7 @@ namespace Bit.Core.Test.Services
await sutProvider.Sut.DownloadAndDecryptAttachmentAsync(cipherId, attachment, null); await sutProvider.Sut.DownloadAndDecryptAttachmentAsync(cipherId, attachment, null);
sutProvider.GetDependency<IApiService>().Received(1).GetAttachmentData(cipherId, attachment.Id); await sutProvider.GetDependency<IApiService>().Received(1).GetAttachmentData(cipherId, attachment.Id);
} }
} }
} }

View File

@ -175,14 +175,14 @@ namespace Bit.Core.Test.Services
sutProvider.GetDependency<IUserService>().GetUserIdAsync().Returns(userId); sutProvider.GetDependency<IUserService>().GetUserIdAsync().Returns(userId);
sutProvider.GetDependency<IApiService>().PostSendAsync(Arg.Any<SendRequest>()).Returns(response); sutProvider.GetDependency<IApiService>().PostSendAsync(Arg.Any<SendRequest>()).Returns(response);
var fileContentBytes = Encoding.UTF8.GetBytes("This is the file content"); var fileContentBytes = new EncByteArray(Encoding.UTF8.GetBytes("This is the file content"));
await sutProvider.Sut.SaveWithServerAsync(send, fileContentBytes); await sutProvider.Sut.SaveWithServerAsync(send, fileContentBytes);
Predicate<SendRequest> sendRequestPredicate = r => Predicate<SendRequest> sendRequestPredicate = r =>
{ {
// Note Send -> SendRequest tested in SendRequestTests // Note Send -> SendRequest tested in SendRequestTests
TestHelper.AssertPropertyEqual(new SendRequest(send, fileContentBytes?.LongLength), r); TestHelper.AssertPropertyEqual(new SendRequest(send, fileContentBytes.Buffer?.LongLength), r);
return true; return true;
}; };
@ -208,7 +208,7 @@ namespace Bit.Core.Test.Services
sutProvider.GetDependency<IUserService>().GetUserIdAsync().Returns(userId); sutProvider.GetDependency<IUserService>().GetUserIdAsync().Returns(userId);
sutProvider.GetDependency<IApiService>().PostFileTypeSendAsync(Arg.Any<SendRequest>()).Returns(response); sutProvider.GetDependency<IApiService>().PostFileTypeSendAsync(Arg.Any<SendRequest>()).Returns(response);
var fileContentBytes = Encoding.UTF8.GetBytes("This is the file content"); var fileContentBytes = new EncByteArray(Encoding.UTF8.GetBytes("This is the file content"));
await sutProvider.Sut.SaveWithServerAsync(send, fileContentBytes); await sutProvider.Sut.SaveWithServerAsync(send, fileContentBytes);
@ -233,7 +233,7 @@ namespace Bit.Core.Test.Services
sutProvider.GetDependency<IApiService>().PostFileTypeSendAsync(Arg.Any<SendRequest>()).Throws(new ApiException(error)); sutProvider.GetDependency<IApiService>().PostFileTypeSendAsync(Arg.Any<SendRequest>()).Throws(new ApiException(error));
sutProvider.GetDependency<IApiService>().PostSendFileAsync(Arg.Any<MultipartFormDataContent>()).Returns(response); sutProvider.GetDependency<IApiService>().PostSendFileAsync(Arg.Any<MultipartFormDataContent>()).Returns(response);
var fileContentBytes = Encoding.UTF8.GetBytes("This is the file content"); var fileContentBytes = new EncByteArray(Encoding.UTF8.GetBytes("This is the file content"));
await sutProvider.Sut.SaveWithServerAsync(send, fileContentBytes); await sutProvider.Sut.SaveWithServerAsync(send, fileContentBytes);
@ -339,12 +339,12 @@ namespace Bit.Core.Test.Services
byte[] getPbkdf(string password, byte[] key) => byte[] getPbkdf(string password, byte[] key) =>
prefixBytes.Concat(Encoding.UTF8.GetBytes(password)).Concat(key).ToArray(); prefixBytes.Concat(Encoding.UTF8.GetBytes(password)).Concat(key).ToArray();
CipherString encryptBytes(byte[] secret, SymmetricCryptoKey key) => EncString encryptBytes(byte[] secret, SymmetricCryptoKey key) =>
new CipherString($"{prefix}{Convert.ToBase64String(secret)}{Convert.ToBase64String(key.Key)}"); new EncString($"{prefix}{Convert.ToBase64String(secret)}{Convert.ToBase64String(key.Key)}");
CipherString encrypt(string secret, SymmetricCryptoKey key) => EncString encrypt(string secret, SymmetricCryptoKey key) =>
new CipherString($"{prefix}{secret}{Convert.ToBase64String(key.Key)}"); new EncString($"{prefix}{secret}{Convert.ToBase64String(key.Key)}");
byte[] encryptFileBytes(byte[] secret, SymmetricCryptoKey key) => EncByteArray encryptFileBytes(byte[] secret, SymmetricCryptoKey key) =>
secret.Concat(key.Key).ToArray(); new EncByteArray(secret.Concat(key.Key).ToArray());
sutProvider.GetDependency<ICryptoFunctionService>().Pbkdf2Async(Arg.Any<string>(), Arg.Any<byte[]>(), Arg.Any<CryptoHashAlgorithm>(), Arg.Any<int>()) sutProvider.GetDependency<ICryptoFunctionService>().Pbkdf2Async(Arg.Any<string>(), Arg.Any<byte[]>(), Arg.Any<CryptoHashAlgorithm>(), Arg.Any<int>())
.Returns(info => getPbkdf((string)info[0], (byte[])info[1])); .Returns(info => getPbkdf((string)info[0], (byte[])info[1]));
@ -374,7 +374,7 @@ namespace Bit.Core.Test.Services
case SendType.File: case SendType.File:
// Only set filename // Only set filename
TestHelper.AssertPropertyEqual(encrypt(view.File.FileName, view.CryptoKey), send.File.FileName); TestHelper.AssertPropertyEqual(encrypt(view.File.FileName, view.CryptoKey), send.File.FileName);
Assert.Equal(encryptFileBytes(fileData, view.CryptoKey), encryptedFileData); Assert.Equal(encryptFileBytes(fileData, view.CryptoKey).Buffer, encryptedFileData.Buffer);
break; break;
default: default:
throw new Exception("Untested send type"); throw new Exception("Untested send type");