mirror of
https://github.com/bitwarden/mobile.git
synced 2024-11-28 12:35:40 +01:00
PM-2572 Added cipherKey to Attachment and logic to use it
This commit is contained in:
parent
b65f18d8e2
commit
4332e7a498
@ -34,6 +34,7 @@ namespace Bit.Core.Models.Domain
|
|||||||
public string SizeName { get; set; }
|
public string SizeName { get; set; }
|
||||||
public EncString Key { get; set; }
|
public EncString Key { get; set; }
|
||||||
public EncString FileName { get; set; }
|
public EncString FileName { get; set; }
|
||||||
|
public EncString CipherKey { get; set; }
|
||||||
|
|
||||||
public async Task<AttachmentView> DecryptAsync(string orgId, SymmetricCryptoKey key = null)
|
public async Task<AttachmentView> DecryptAsync(string orgId, SymmetricCryptoKey key = null)
|
||||||
{
|
{
|
||||||
|
@ -134,14 +134,25 @@ namespace Bit.Core.Models.Domain
|
|||||||
{
|
{
|
||||||
model.Attachments = new List<AttachmentView>();
|
model.Attachments = new List<AttachmentView>();
|
||||||
var tasks = new List<Task>();
|
var tasks = new List<Task>();
|
||||||
async Task decryptAndAddAttachmentAsync(Attachment attachment)
|
async Task decryptAndAddAttachmentAsync(Attachment attachment, SymmetricCryptoKey decKey)
|
||||||
{
|
{
|
||||||
var decAttachment = await attachment.DecryptAsync(OrganizationId, model.Key);
|
var decAttachment = await attachment.DecryptAsync(OrganizationId, model.Key ?? decKey);
|
||||||
model.Attachments.Add(decAttachment);
|
model.Attachments.Add(decAttachment);
|
||||||
}
|
}
|
||||||
foreach (var attachment in Attachments)
|
foreach (var attachment in Attachments)
|
||||||
{
|
{
|
||||||
tasks.Add(decryptAndAddAttachmentAsync(attachment));
|
SymmetricCryptoKey decKey = null;
|
||||||
|
//If the cipher.key is null but the attachment.cipherKey has a value we will use it to decrypt the attachment
|
||||||
|
if (Key == null && attachment.CipherKey != null)
|
||||||
|
{
|
||||||
|
var cryptoService = ServiceContainer.Resolve<ICryptoService>();
|
||||||
|
|
||||||
|
var orgKey = await cryptoService.GetOrgKeyAsync(OrganizationId);
|
||||||
|
|
||||||
|
var key = await cryptoService.DecryptToBytesAsync(attachment.CipherKey, orgKey);
|
||||||
|
decKey = new CipherKey(key);
|
||||||
|
}
|
||||||
|
tasks.Add(decryptAndAddAttachmentAsync(attachment, decKey));
|
||||||
}
|
}
|
||||||
await Task.WhenAll(tasks);
|
await Task.WhenAll(tasks);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ namespace Bit.Core.Models.View
|
|||||||
public string SizeName { get; set; }
|
public string SizeName { get; set; }
|
||||||
public string FileName { get; set; }
|
public string FileName { get; set; }
|
||||||
public SymmetricCryptoKey Key { get; set; }
|
public SymmetricCryptoKey Key { get; set; }
|
||||||
|
public CipherKey CipherKey { get; set; }
|
||||||
|
|
||||||
public long FileSize
|
public long FileSize
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//#define ENABLE_NEW_CIPHER_KEY_ENCRYPTION_ON_CREATION
|
#define ENABLE_NEW_CIPHER_KEY_ENCRYPTION_ON_CREATION
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -571,25 +571,39 @@ namespace Bit.Core.Services
|
|||||||
await UpsertAsync(data);
|
await UpsertAsync(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ShareWithServerAsync(CipherView cipher, string organizationId, HashSet<string> collectionIds)
|
public async Task ShareWithServerAsync(CipherView cipherView, string organizationId, HashSet<string> collectionIds)
|
||||||
{
|
{
|
||||||
var attachmentTasks = new List<Task>();
|
var attachmentTasks = new List<Task>();
|
||||||
if (cipher.Attachments != null)
|
Cipher cipher = null;
|
||||||
|
//If the cipher doesn't have a key, we update it
|
||||||
|
if(cipherView.Key == null)
|
||||||
{
|
{
|
||||||
foreach (var attachment in cipher.Attachments)
|
cipher = await EncryptAsync(cipherView);
|
||||||
|
var putCipherRequest = new CipherRequest(cipher);
|
||||||
|
var putCipherResponse = await _apiService.PutCipherAsync(cipherView.Id, putCipherRequest);
|
||||||
|
var cipherData = new CipherData(putCipherResponse, await _stateService.GetActiveUserIdAsync());
|
||||||
|
await UpsertAsync(cipherData);
|
||||||
|
cipher = await GetAsync(cipherView.Id);
|
||||||
|
cipherView = await cipher.DecryptAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cipherView.Attachments != null)
|
||||||
|
{
|
||||||
|
foreach (var attachment in cipherView.Attachments)
|
||||||
{
|
{
|
||||||
if (attachment.Key == null)
|
if (attachment.Key == null)
|
||||||
{
|
{
|
||||||
attachmentTasks.Add(ShareAttachmentWithServerAsync(attachment, cipher.Id, organizationId));
|
attachmentTasks.Add(ShareAttachmentWithServerAsync(attachment, cipherView.Id, organizationId, cipherView.Key, cipher?.Key));
|
||||||
|
attachment.CipherKey = cipherView.Key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await Task.WhenAll(attachmentTasks);
|
await Task.WhenAll(attachmentTasks);
|
||||||
cipher.OrganizationId = organizationId;
|
cipherView.OrganizationId = organizationId;
|
||||||
cipher.CollectionIds = collectionIds;
|
cipherView.CollectionIds = collectionIds;
|
||||||
var encCipher = await EncryptAsync(cipher);
|
var encCipher = await EncryptAsync(cipherView);
|
||||||
var request = new CipherShareRequest(encCipher);
|
var request = new CipherShareRequest(encCipher);
|
||||||
var response = await _apiService.PutShareCipherAsync(cipher.Id, request);
|
var response = await _apiService.PutShareCipherAsync(cipherView.Id, request);
|
||||||
var userId = await _stateService.GetActiveUserIdAsync();
|
var userId = await _stateService.GetActiveUserIdAsync();
|
||||||
var data = new CipherData(response, userId, collectionIds);
|
var data = new CipherData(response, userId, collectionIds);
|
||||||
await UpsertAsync(data);
|
await UpsertAsync(data);
|
||||||
@ -855,12 +869,13 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
||||||
private async Task<Tuple<SymmetricCryptoKey, EncString, SymmetricCryptoKey>> MakeAttachmentKeyAsync(string organizationId, Cipher cipher = null, CipherView cipherView = null)
|
private async Task<Tuple<SymmetricCryptoKey, EncString, SymmetricCryptoKey>> MakeAttachmentKeyAsync(string organizationId, Cipher cipher = null, CipherView cipherView = null, SymmetricCryptoKey cipherKey = null)
|
||||||
{
|
{
|
||||||
var orgKey = await _cryptoService.GetOrgKeyAsync(organizationId);
|
var orgKey = await _cryptoService.GetOrgKeyAsync(organizationId);
|
||||||
|
|
||||||
SymmetricCryptoKey encryptionKey = orgKey;
|
//We give priority to the use of cipher.key if it exists
|
||||||
if (cipher != null && cipherView != null)
|
SymmetricCryptoKey encryptionKey = cipherKey ?? orgKey;
|
||||||
|
if (cipher != null && cipherView != null && cipher.Key == null)
|
||||||
{
|
{
|
||||||
encryptionKey = await UpdateCipherAndGetCipherKeyAsync(cipher, cipherView, orgKey, false);
|
encryptionKey = await UpdateCipherAndGetCipherKeyAsync(cipher, cipherView, orgKey, false);
|
||||||
}
|
}
|
||||||
@ -872,7 +887,7 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task ShareAttachmentWithServerAsync(AttachmentView attachmentView, string cipherId,
|
private async Task ShareAttachmentWithServerAsync(AttachmentView attachmentView, string cipherId,
|
||||||
string organizationId)
|
string organizationId, SymmetricCryptoKey cipherKey = null, EncString cipherKeyProtected = null)
|
||||||
{
|
{
|
||||||
var attachmentResponse = await _httpClient.GetAsync(attachmentView.Url);
|
var attachmentResponse = await _httpClient.GetAsync(attachmentView.Url);
|
||||||
if (!attachmentResponse.IsSuccessStatusCode)
|
if (!attachmentResponse.IsSuccessStatusCode)
|
||||||
@ -883,7 +898,7 @@ namespace Bit.Core.Services
|
|||||||
var bytes = await attachmentResponse.Content.ReadAsByteArrayAsync();
|
var bytes = await attachmentResponse.Content.ReadAsByteArrayAsync();
|
||||||
var decBytes = await _cryptoService.DecryptFromBytesAsync(bytes, null);
|
var decBytes = await _cryptoService.DecryptFromBytesAsync(bytes, null);
|
||||||
|
|
||||||
var (attachmentKey, protectedAttachmentKey, encKey) = await MakeAttachmentKeyAsync(organizationId);
|
var (attachmentKey, protectedAttachmentKey, encKey) = await MakeAttachmentKeyAsync(organizationId, cipherKey:cipherKey);
|
||||||
|
|
||||||
var encFileName = await _cryptoService.EncryptAsync(attachmentView.FileName, encKey);
|
var encFileName = await _cryptoService.EncryptAsync(attachmentView.FileName, encKey);
|
||||||
var encFileData = await _cryptoService.EncryptToBytesAsync(decBytes, attachmentKey);
|
var encFileData = await _cryptoService.EncryptToBytesAsync(decBytes, attachmentKey);
|
||||||
@ -892,6 +907,10 @@ namespace Bit.Core.Services
|
|||||||
var fd = new MultipartFormDataContent(boundary);
|
var fd = new MultipartFormDataContent(boundary);
|
||||||
fd.Add(new StringContent(protectedAttachmentKey.EncryptedString), "key");
|
fd.Add(new StringContent(protectedAttachmentKey.EncryptedString), "key");
|
||||||
fd.Add(new StreamContent(new MemoryStream(encFileData.Buffer)), "data", encFileName.EncryptedString);
|
fd.Add(new StreamContent(new MemoryStream(encFileData.Buffer)), "data", encFileName.EncryptedString);
|
||||||
|
if(cipherKey != null && cipherKeyProtected != null)
|
||||||
|
{
|
||||||
|
fd.Add(new StringContent(cipherKeyProtected.EncryptedString), "cipherKey");
|
||||||
|
}
|
||||||
await _apiService.PostShareCipherAttachmentAsync(cipherId, attachmentView.Id, fd, organizationId);
|
await _apiService.PostShareCipherAttachmentAsync(cipherId, attachmentView.Id, fd, organizationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user