1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-11-21 11:25:56 +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);
var encKey = await _cryptoService.GetEncKeyAsync(key);
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;
if (!failed)
{
@ -272,7 +272,7 @@ namespace Bit.App.Pages
{
var protectedPin = await _storageService.GetAsync<string>(Constants.ProtectedPin);
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,
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000));
_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 masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key);
Tuple<SymmetricCryptoKey, CipherString> encKey;
Tuple<SymmetricCryptoKey, EncString> encKey;
var existingEncKey = await _cryptoService.GetEncKeyAsync();
if (existingEncKey == null)
{

View File

@ -1,10 +1,11 @@
using System;
using System.Threading.Tasks;
using Bit.Core.Models.Domain;
namespace Bit.Core.Abstractions
{
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 ClearPinProtectedKeyAsync();
Task<byte[]> DecryptFromBytesAsync(byte[] encBytes, SymmetricCryptoKey key);
Task<byte[]> DecryptToBytesAsync(CipherString cipherString, SymmetricCryptoKey key = null);
Task<string> DecryptToUtf8Async(CipherString cipherString, SymmetricCryptoKey key = null);
Task<CipherString> EncryptAsync(byte[] plainValue, SymmetricCryptoKey key = null);
Task<CipherString> EncryptAsync(string plainValue, SymmetricCryptoKey key = null);
Task<byte[]> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null);
Task<byte[]> DecryptToBytesAsync(EncString encString, SymmetricCryptoKey key = null);
Task<string> DecryptToUtf8Async(EncString encString, SymmetricCryptoKey key = null);
Task<EncString> EncryptAsync(byte[] plainValue, SymmetricCryptoKey key = null);
Task<EncString> EncryptAsync(string plainValue, SymmetricCryptoKey key = null);
Task<EncByteArray> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null);
Task<SymmetricCryptoKey> GetEncKeyAsync(SymmetricCryptoKey key = null);
Task<List<string>> GetFingerprintAsync(string userId, byte[] publicKey = null);
Task<SymmetricCryptoKey> GetKeyAsync();
@ -33,17 +33,17 @@ namespace Bit.Core.Abstractions
Task<bool> HasEncKeyAsync();
Task<string> HashPasswordAsync(string password, SymmetricCryptoKey key);
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> MakeKeyFromPinAsync(string pin, string salt, KdfType kdf, int kdfIterations,
CipherString protectedKeyCs = null);
Task<Tuple<string, CipherString>> MakeKeyPairAsync(SymmetricCryptoKey key = null);
EncString protectedKeyEs = null);
Task<Tuple<string, EncString>> MakeKeyPairAsync(SymmetricCryptoKey key = null);
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<int> RandomNumberAsync(int min, int max);
Task<Tuple<SymmetricCryptoKey, CipherString>> RemakeEncKeyAsync(SymmetricCryptoKey key);
Task<CipherString> RsaEncryptAsync(byte[] data, byte[] publicKey = null);
Task<Tuple<SymmetricCryptoKey, EncString>> RemakeEncKeyAsync(SymmetricCryptoKey key);
Task<EncString> RsaEncryptAsync(byte[] data, byte[] publicKey = null);
Task SetEncKeyAsync(string encKey);
Task SetEncPrivateKeyAsync(string encPrivateKey);
Task SetKeyAsync(SymmetricCryptoKey key);

View File

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

View File

@ -9,12 +9,12 @@ namespace Bit.Core.Abstractions
public interface ISendService
{
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);
Task<Send> GetAsync(string id);
Task<List<Send>> GetAllAsync();
Task<List<SendView>> GetAllDecryptedAsync();
Task<string> SaveWithServerAsync(Send sendData, byte[] encryptedFileData);
Task<string> SaveWithServerAsync(Send sendData, EncByteArray encryptedFileData);
Task UpsertAsync(params SendData[] send);
Task ReplaceAsync(Dictionary<string, SendData> sends);
Task ClearAsync(string userId);

View File

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

View File

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

View File

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

View File

@ -58,8 +58,8 @@ namespace Bit.Core.Models.Domain
public string Id { get; set; }
public string OrganizationId { get; set; }
public string FolderId { get; set; }
public CipherString Name { get; set; }
public CipherString Notes { get; set; }
public EncString Name { get; set; }
public EncString Notes { get; set; }
public Enums.CipherType Type { get; set; }
public bool Favorite { 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 OrganizationId { get; set; }
public CipherString Name { get; set; }
public EncString Name { get; set; }
public string ExternalId { get; set; }
public bool ReadOnly { get; set; }

View File

@ -24,13 +24,13 @@ namespace Bit.Core.Models.Domain
else
{
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,
HashSet<string> notCipherStringList = null)
HashSet<string> notEncryptedStringList = null)
where D : Domain
where O : Data.Data
{
@ -41,13 +41,13 @@ namespace Bit.Core.Models.Domain
var domainPropInfo = domainType.GetProperty(prop);
var domainProp = domainPropInfo.GetValue(domain);
var dataObjPropInfo = dataObjType.GetProperty(prop);
if (notCipherStringList?.Contains(prop) ?? false)
if (notEncryptedStringList?.Contains(prop) ?? false)
{
dataObjPropInfo.SetValue(dataObj, domainProp, null);
}
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);
string val = null;
if (domainPropInfo.GetValue(domain) is CipherString domainProp)
if (domainPropInfo.GetValue(domain) is EncString domainProp)
{
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
{
public class CipherString
public class EncString
{
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))
{
@ -37,7 +37,7 @@ namespace Bit.Core.Models.Domain
Mac = mac;
}
public CipherString(string encryptedString)
public EncString(string encryptedString)
{
if (string.IsNullOrWhiteSpace(encryptedString))
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,11 +15,11 @@ namespace Bit.Core.Models.Domain
public string AccessId { get; set; }
public string UserId { get; set; }
public SendType Type { get; set; }
public CipherString Name { get; set; }
public CipherString Notes { get; set; }
public EncString Name { get; set; }
public EncString Notes { get; set; }
public SendFile File { get; set; }
public SendText Text { get; set; }
public CipherString Key { get; set; }
public EncString Key { get; set; }
public int? MaxAccessCount { get; set; }
public int AccessCount { 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 Size { get; set; }
public string SizeName { get; set; }
public CipherString FileName { get; set; }
public EncString FileName { get; set; }
public SendFile() : base() { }

View File

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

View File

@ -8,6 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Web;
using Bit.Core.Abstractions;
using Bit.Core.Models.Domain;
using Bit.Core.Utilities;
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);
}
@ -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())
{
@ -51,7 +52,7 @@ namespace Bit.Core.Services
requestMessage.Headers.Add("x-ms-version", paramValues["sv"]);
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.Method = HttpMethod.Put;
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);
var baseParams = HttpUtility.ParseQueryString(CoreHelpers.GetUri(uri).Query);
var blockSize = MaxBlockSize(baseParams["sv"]);
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>();
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-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.Method = HttpMethod.Put;
requestMessage.RequestUri = blockUriBuilder.Uri;

View File

@ -1,6 +1,7 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Bit.Core.Models.Domain;
namespace Bit.Core.Services
{
@ -13,11 +14,11 @@ namespace Bit.Core.Services
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}")
{
{ new ByteArrayContent(encryptedFileData), "data", encryptedFileName }
{ new ByteArrayContent(encryptedFileData.Buffer), "data", encryptedFileName }
};
await apiCall(fd);

View File

@ -568,7 +568,7 @@ namespace Bit.Core.Services
{
Key = orgEncAttachmentKey.EncryptedString,
FileName = encFileName.EncryptedString,
FileSize = encFileData.Length,
FileSize = encFileData.Buffer.Length,
};
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.")]
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 fd = new MultipartFormDataContent(boundary);
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);
}
@ -828,7 +828,7 @@ namespace Bit.Core.Services
var boundary = string.Concat("--BWMobileFormBoundary", DateTime.UtcNow.Ticks);
var fd = new MultipartFormDataContent(boundary);
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);
}
@ -1037,7 +1037,7 @@ namespace Bit.Core.Services
{
var modelPropInfo = modelType.GetProperty(propName);
var modelProp = modelPropInfo.GetValue(model) as string;
CipherString val = null;
EncString val = null;
if (!string.IsNullOrWhiteSpace(modelProp))
{
val = await _cryptoService.EncryptAsync(modelProp, key);

View File

@ -148,7 +148,7 @@ namespace Bit.Core.Services
}
byte[] decEncKey = null;
var encKeyCipher = new CipherString(encKey);
var encKeyCipher = new EncString(encKey);
if (encKeyCipher.EncryptionType == EncryptionType.AesCbc256_B64)
{
decEncKey = await DecryptToBytesAsync(encKeyCipher, key);
@ -205,7 +205,7 @@ namespace Bit.Core.Services
{
return null;
}
_privateKey = await DecryptToBytesAsync(new CipherString(encPrivateKey), null);
_privateKey = await DecryptToBytesAsync(new EncString(encPrivateKey), null);
return _privateKey;
}
@ -389,7 +389,7 @@ namespace Bit.Core.Services
}
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)
{
@ -398,27 +398,27 @@ namespace Bit.Core.Services
{
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 decKey = await DecryptToBytesAsync(protectedKeyCs, pinKey);
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 publicKey = await GetPublicKeyAsync();
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 publicB64 = Convert.ToBase64String(keyPair.Item1);
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)
@ -447,20 +447,20 @@ namespace Bit.Core.Services
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 encKey = await _cryptoFunctionService.RandomBytesAsync(64);
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();
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)
{
@ -469,7 +469,7 @@ namespace Bit.Core.Services
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)
{
@ -479,10 +479,10 @@ namespace Bit.Core.Services
var iv = Convert.ToBase64String(encObj.Iv);
var data = Convert.ToBase64String(encObj.Data);
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 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.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)
{
@ -512,21 +512,21 @@ namespace Bit.Core.Services
throw new Exception("Public key unavailable.");
}
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 data = Convert.FromBase64String(cipherString.Data);
var mac = !string.IsNullOrWhiteSpace(cipherString.Mac) ? Convert.FromBase64String(cipherString.Mac) : null;
return await AesDecryptToBytesAsync(cipherString.EncryptionType, data, iv, mac, key);
var iv = Convert.FromBase64String(encString.Iv);
var data = Convert.FromBase64String(encString.Data);
var mac = !string.IsNullOrWhiteSpace(encString.Mac) ? Convert.FromBase64String(encString.Mac) : null;
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,
cipherString.Iv, cipherString.Mac, key);
return await AesDecryptToUtf8Async(encString.EncryptionType, encString.Data,
encString.Iv, encString.Mac, key);
}
public async Task<byte[]> DecryptFromBytesAsync(byte[] encBytes, SymmetricCryptoKey key)
@ -809,10 +809,10 @@ namespace Bit.Core.Services
return phrase;
}
private async Task<Tuple<SymmetricCryptoKey, CipherString>> BuildEncKeyAsync(SymmetricCryptoKey key,
private async Task<Tuple<SymmetricCryptoKey, EncString>> BuildEncKeyAsync(SymmetricCryptoKey key,
byte[] encKey)
{
CipherString encKeyEnc = null;
EncString encKeyEnc = null;
if (key.Key.Length == 32)
{
var newKey = await StretchKeyAsync(key);
@ -826,7 +826,7 @@ namespace Bit.Core.Services
{
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

View File

@ -20,7 +20,7 @@ namespace Bit.Core.Services {
private readonly ApiService _apiService;
public async Task UploadCipherAttachmentFileAsync(AttachmentUploadDataResponse uploadData,
string encryptedFileName, byte[] encryptedFileData)
string encryptedFileName, EncByteArray encryptedFileData)
{
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
{

View File

@ -633,7 +633,7 @@ namespace Bit.Core.Services
}
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
{
Password = decrypted,

View File

@ -81,7 +81,7 @@ namespace Bit.Core.Services
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)
{
if (model.Key == null)
@ -103,7 +103,7 @@ namespace Bit.Core.Services
Notes = await _cryptoService.EncryptAsync(model.Notes, model.CryptoKey),
HideEmail = model.HideEmail
};
byte[] encryptedFileData = null;
EncByteArray encryptedFileData = null;
if (password != null)
{
@ -197,9 +197,9 @@ namespace Bit.Core.Services
_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;
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.")]
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}")
{
{ 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);

View File

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

View File

@ -140,7 +140,7 @@ namespace Bit.iOS.Core.Controllers
_vaultTimeoutService.PinProtectedKey);
var encKey = await _cryptoService.GetEncKeyAsync(key);
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;
if (!failed)
{
@ -191,7 +191,7 @@ namespace Bit.iOS.Core.Controllers
{
var protectedPin = await _storageService.GetAsync<string>(Bit.Core.Constants.ProtectedPin);
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,
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000));
_vaultTimeoutService.PinProtectedKey = await _cryptoService.EncryptAsync(key2.Key, pinKey);

View File

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

View File

@ -22,17 +22,17 @@ namespace Bit.Core.Test.Services
{
[Theory, UserCipherAutoData]
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>())
.Returns(new CipherString(fileName));
sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data, Arg.Any<SymmetricCryptoKey>())
.Returns(new EncString(fileName));
sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data.Buffer, Arg.Any<SymmetricCryptoKey>())
.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>())
.Returns(uploadDataResponse);
await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data);
await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data.Buffer);
await sutProvider.GetDependency<IFileUploadService>().Received(1)
.UploadCipherAttachmentFileAsync(uploadDataResponse, fileName, data);
@ -42,20 +42,20 @@ namespace Bit.Core.Test.Services
[InlineUserCipherAutoData(HttpStatusCode.NotFound)]
[InlineUserCipherAutoData(HttpStatusCode.MethodNotAllowed)]
public async Task SaveWithServerAsync_FallsBackToLegacyFormData(HttpStatusCode statusCode,
SutProvider<CipherService> sutProvider, Cipher cipher, string fileName, byte[] data,
CipherResponse response, CipherString encKey)
SutProvider<CipherService> sutProvider, Cipher cipher, string fileName, EncByteArray data,
CipherResponse response, EncString encKey)
{
sutProvider.GetDependency<ICryptoService>().EncryptAsync(fileName, Arg.Any<SymmetricCryptoKey>())
.Returns(new CipherString(fileName));
sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data, Arg.Any<SymmetricCryptoKey>())
.Returns(new EncString(fileName));
sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data.Buffer, Arg.Any<SymmetricCryptoKey>())
.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>())
.Throws(new ApiException(new ErrorResponse {StatusCode = statusCode}));
sutProvider.GetDependency<IApiService>().PostCipherAttachmentLegacyAsync(cipher.Id, Arg.Any<MultipartFormDataContent>())
.Returns(response);
await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data);
await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data.Buffer);
await sutProvider.GetDependency<IApiService>().Received(1)
.PostCipherAttachmentLegacyAsync(cipher.Id, Arg.Any<MultipartFormDataContent>());
@ -63,20 +63,20 @@ namespace Bit.Core.Test.Services
[Theory, UserCipherAutoData]
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>())
.Returns(new CipherString(fileName));
sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data, Arg.Any<SymmetricCryptoKey>())
.Returns(new EncString(fileName));
sutProvider.GetDependency<ICryptoService>().EncryptToBytesAsync(data.Buffer, Arg.Any<SymmetricCryptoKey>())
.Returns(data);
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 });
sutProvider.GetDependency<IApiService>().PostCipherAttachmentAsync(cipher.Id, Arg.Any<AttachmentRequest>())
.Throws(expectedException);
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);
}
@ -90,7 +90,7 @@ namespace Bit.Core.Test.Services
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<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);
Predicate<SendRequest> sendRequestPredicate = r =>
{
// 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;
};
@ -208,7 +208,7 @@ namespace Bit.Core.Test.Services
sutProvider.GetDependency<IUserService>().GetUserIdAsync().Returns(userId);
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);
@ -233,7 +233,7 @@ namespace Bit.Core.Test.Services
sutProvider.GetDependency<IApiService>().PostFileTypeSendAsync(Arg.Any<SendRequest>()).Throws(new ApiException(error));
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);
@ -339,12 +339,12 @@ namespace Bit.Core.Test.Services
byte[] getPbkdf(string password, byte[] key) =>
prefixBytes.Concat(Encoding.UTF8.GetBytes(password)).Concat(key).ToArray();
CipherString encryptBytes(byte[] secret, SymmetricCryptoKey key) =>
new CipherString($"{prefix}{Convert.ToBase64String(secret)}{Convert.ToBase64String(key.Key)}");
CipherString encrypt(string secret, SymmetricCryptoKey key) =>
new CipherString($"{prefix}{secret}{Convert.ToBase64String(key.Key)}");
byte[] encryptFileBytes(byte[] secret, SymmetricCryptoKey key) =>
secret.Concat(key.Key).ToArray();
EncString encryptBytes(byte[] secret, SymmetricCryptoKey key) =>
new EncString($"{prefix}{Convert.ToBase64String(secret)}{Convert.ToBase64String(key.Key)}");
EncString encrypt(string secret, SymmetricCryptoKey key) =>
new EncString($"{prefix}{secret}{Convert.ToBase64String(key.Key)}");
EncByteArray encryptFileBytes(byte[] secret, SymmetricCryptoKey key) =>
new EncByteArray(secret.Concat(key.Key).ToArray());
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]));
@ -374,7 +374,7 @@ namespace Bit.Core.Test.Services
case SendType.File:
// Only set 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;
default:
throw new Exception("Untested send type");