Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
dee1ada
Begin work on animated intro background
d2dyno1 Dec 19, 2025
6caa4a2
Light mode adjustments
d2dyno1 Dec 19, 2025
0346a3d
Upgraded to Uno 6.4
d2dyno1 Dec 19, 2025
8fcdb8c
Added link to Terms of Service
d2dyno1 Dec 20, 2025
aef68a8
Refactor onboarding slide to FeatureSlide control
d2dyno1 Dec 20, 2025
65d9824
Added OnPlatform to Uno
d2dyno1 Dec 20, 2025
16c5d83
Added Upload status operation
d2dyno1 Dec 25, 2025
5517d9f
Improved PerformOperationAsync
d2dyno1 Dec 25, 2025
637b51a
Use a segmented control in view options sheet
d2dyno1 Dec 25, 2025
fa26c7d
Improved popups
d2dyno1 Dec 25, 2025
f455c70
Minor improvements to popups
d2dyno1 Dec 25, 2025
509da41
Added popup shadow
d2dyno1 Dec 26, 2025
383d51c
Added cancellation when connecting to account
d2dyno1 Dec 26, 2025
d9958ca
ActivityIndicator for initializing LoginViewModel
d2dyno1 Dec 26, 2025
1a5efe7
Small UX fix
d2dyno1 Dec 26, 2025
566a41e
Added AccountBarControl to vault OverviewPage
d2dyno1 Dec 27, 2025
863e28e
Update FtpAccountViewModel.cs
d2dyno1 Dec 27, 2025
640ab95
Small stability fixes
d2dyno1 Dec 27, 2025
83f72e5
Update VaultLoginViewModel.cs
d2dyno1 Dec 27, 2025
70ceb10
Fixed build
d2dyno1 Dec 27, 2025
c95ed58
Minor changes
d2dyno1 Dec 30, 2025
f586cdd
Improved date formatting
d2dyno1 Jan 1, 2026
c4d2c48
Added the option to import and export settings
d2dyno1 Jan 1, 2026
496325f
Use FixedTimeEquals instead of SequenceEqual
d2dyno1 Jan 1, 2026
93ab9df
Begin work on memory hardening
d2dyno1 Jan 2, 2026
34fe6c9
Use new IKey interfaces
d2dyno1 Jan 2, 2026
511203f
Use andomNumberGenerator.Fill instead
d2dyno1 Jan 2, 2026
628a080
More work on UseKey security
d2dyno1 Jan 2, 2026
20bce38
Fixed build on Windows
d2dyno1 Jan 2, 2026
099b3cc
Prefer more IKeyUsage instead of IKeyBytes
d2dyno1 Jan 3, 2026
84d42db
Fixed vault name editing box visibility
d2dyno1 Jan 3, 2026
08447eb
Update SettingsPage.xaml
d2dyno1 Jan 3, 2026
558ee41
Update some deps
d2dyno1 Jan 3, 2026
3e29fad
Test fix for WebDav on MacOS
d2dyno1 Jan 7, 2026
8a0c779
Update EncryptingDiskStoreFile.cs
d2dyno1 Jan 7, 2026
f76146d
Update nwebdav
d2dyno1 Jan 7, 2026
41173b9
Added MulticastProgress
d2dyno1 Jan 7, 2026
46bfdfd
Added a limit to MulticastProgress
d2dyno1 Jan 7, 2026
f098146
Removed empty chars
d2dyno1 Jan 7, 2026
cdc14db
Update EncryptingDiskStoreFile.cs
d2dyno1 Jan 8, 2026
c2c1e26
Update nwebdav
d2dyno1 Jan 8, 2026
a1460e1
Inherit from IDavStorable
d2dyno1 Jan 8, 2026
2190cfb
Use actual GetItemsAsync
d2dyno1 Jan 8, 2026
7cc9af1
More reimplementing
d2dyno1 Jan 8, 2026
96be570
Reimplement DeleteAsync_Dav
d2dyno1 Jan 8, 2026
ea7c4eb
Reimplemented Create..Async methods
d2dyno1 Jan 8, 2026
5814be8
Removed IStoreItem, IStoreCollection, IStoreFile
d2dyno1 Jan 8, 2026
aae9f3b
Update EncryptingDiskStoreFile.cs
d2dyno1 Jan 8, 2026
5f19149
Update nwebdav
d2dyno1 Jan 8, 2026
7218dc9
Added BackedDav storage
d2dyno1 Jan 9, 2026
bd87a51
Minor cleanup
d2dyno1 Jan 9, 2026
9f3185c
Update nwebdav
d2dyno1 Jan 9, 2026
1b022e5
Test shortcut files on Windows
d2dyno1 Jan 9, 2026
026a52f
Cleaned up code
d2dyno1 Jan 9, 2026
156eb53
Update csproj
d2dyno1 Jan 9, 2026
7957d97
Test code
d2dyno1 Jan 9, 2026
fab8fe0
Begin work on separate window
d2dyno1 Jan 9, 2026
899d3a7
More work on vault preview
d2dyno1 Jan 10, 2026
558518e
Fixed some small activation issues
d2dyno1 Jan 10, 2026
d8d424c
Update VaultViewModel.cs
d2dyno1 Jan 10, 2026
842304b
Update App.xaml.cs
d2dyno1 Jan 10, 2026
cd3bea7
Update SkiaApplicationService.cs
d2dyno1 Jan 10, 2026
61ac8ee
Extend titlebar on MacOS
d2dyno1 Jan 10, 2026
cb2905b
Added widget reorder button
d2dyno1 Jan 10, 2026
9d70587
Some improvements
d2dyno1 Jan 10, 2026
bc03449
Update VaultDashboardPage.xaml
d2dyno1 Jan 11, 2026
d31bb10
Added a banner to privacy settings page
d2dyno1 Jan 11, 2026
652615d
Removed unused settings
d2dyno1 Jan 12, 2026
762a6ea
Added more scan options to health page
d2dyno1 Jan 12, 2026
e6c776c
Update VaultHealthViewModel.Scanning.cs
d2dyno1 Jan 12, 2026
a5687a0
Begin work on file content validator
d2dyno1 Jan 12, 2026
04d45fc
Implemented YubiKey PIV authentication
d2dyno1 Jan 12, 2026
88a5aa6
Update WindowsVaultCredentialsService.cs
d2dyno1 Jan 12, 2026
182e6fd
Fixed YubiKey blinking animation
d2dyno1 Jan 13, 2026
b7d5431
Fixed shield assets on Uno desktop
d2dyno1 Jan 13, 2026
d595201
Update SeverityHealthIconConverter.cs
d2dyno1 Jan 13, 2026
53ec64b
Added DebugPhoneLinkPage
d2dyno1 Jan 13, 2026
4c7e7dc
Draft DeviceLinkService
d2dyno1 Jan 16, 2026
739aeea
Fixed MainPage toolbar options
d2dyno1 Jan 16, 2026
12e5ff0
Device Link checkpoint
d2dyno1 Jan 24, 2026
6ac454e
Added MacOsIconHelper
d2dyno1 Jan 24, 2026
605dddf
Update MacOsIconHelper.cs
d2dyno1 Jan 24, 2026
ffcedcd
Quality control
d2dyno1 Jan 24, 2026
c699e95
Set AssemblyName to SecureFolderFS
d2dyno1 Jan 24, 2026
0c4b51e
Update UnoThemeHelper.cs
d2dyno1 Jan 29, 2026
42f765d
Persist widget order
d2dyno1 Jan 30, 2026
4a39981
Improvements to data corruption health checks
d2dyno1 Feb 1, 2026
77849d3
Fixed build
d2dyno1 Feb 1, 2026
50bd4c1
Begin work on Device Link Enrollment
d2dyno1 Feb 6, 2026
5ebb07a
Update SkiaVaultCredentialsService.cs
d2dyno1 Feb 6, 2026
1012039
Update WindowsVaultCredentialsService.cs
d2dyno1 Feb 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
19 changes: 19 additions & 0 deletions SecureFolderFS.sln
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecureFolderFS.Core.WinFsp"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecureFolderFS.Cli", "src\Platforms\SecureFolderFS.Cli\SecureFolderFS.Cli.csproj", "{A9219707-C494-4D3B-8123-43652707B516}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecureFolderFS.Sdk.PhoneLink", "src\Sdk\SecureFolderFS.Sdk.PhoneLink\SecureFolderFS.Sdk.PhoneLink.csproj", "{85FE77EA-9F89-4F42-BD79-26C82F847DDC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -504,6 +506,22 @@ Global
{A9219707-C494-4D3B-8123-43652707B516}.Release|x64.Build.0 = Release|Any CPU
{A9219707-C494-4D3B-8123-43652707B516}.Release|x86.ActiveCfg = Release|Any CPU
{A9219707-C494-4D3B-8123-43652707B516}.Release|x86.Build.0 = Release|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Debug|arm64.ActiveCfg = Debug|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Debug|arm64.Build.0 = Debug|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Debug|x64.ActiveCfg = Debug|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Debug|x64.Build.0 = Debug|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Debug|x86.ActiveCfg = Debug|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Debug|x86.Build.0 = Debug|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Release|Any CPU.Build.0 = Release|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Release|arm64.ActiveCfg = Release|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Release|arm64.Build.0 = Release|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Release|x64.ActiveCfg = Release|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Release|x64.Build.0 = Release|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Release|x86.ActiveCfg = Release|Any CPU
{85FE77EA-9F89-4F42-BD79-26C82F847DDC}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -539,6 +557,7 @@ Global
{79C128B4-DD9D-4BAC-AA81-9BFAD02ECDD3} = {086CDAC6-2730-4F09-BA28-B41F737E6C4D}
{F56308B3-01B8-489B-ABE2-69F35FC5A7DE} = {F2ACE2B7-1599-4769-8FF4-41FA03B25D26}
{A9219707-C494-4D3B-8123-43652707B516} = {66BC1E2B-D99A-49E2-8B8F-EF7851493CB0}
{85FE77EA-9F89-4F42-BD79-26C82F847DDC} = {086CDAC6-2730-4F09-BA28-B41F737E6C4D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A1906FD8-BB54-4688-BC0F-9ED7532D2CB0}
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"msbuild-sdks": {
"Uno.Sdk": "6.0.96"
"Uno.Sdk": "6.4.24"
}
}
2 changes: 1 addition & 1 deletion lib/nwebdav
Submodule nwebdav updated 41 files
+0 −28 NWebDav.Server/Extensions/DavStorageExtensions.Folder.cs
+0 −24 NWebDav.Server/Extensions/StoreExtensions.cs
+5 −4 NWebDav.Server/Handlers/CopyHandler.cs
+26 −12 NWebDav.Server/Handlers/DeleteHandler.cs
+8 −7 NWebDav.Server/Handlers/GetAndHeadHandler.cs
+11 −2 NWebDav.Server/Handlers/MkcolHandler.cs
+31 −16 NWebDav.Server/Handlers/MoveHandler.cs
+11 −9 NWebDav.Server/Handlers/PropFindHandler.cs
+69 −23 NWebDav.Server/Handlers/PutHandler.cs
+14 −14 NWebDav.Server/Locking/BaseLockingManager.cs
+8 −8 NWebDav.Server/Locking/ILockingManager.cs
+10 −10 NWebDav.Server/Locking/InMemoryLockingManager.cs
+12 −12 NWebDav.Server/Props/DavExtCollectionProperties.cs
+2 −2 NWebDav.Server/Props/DavProperty.cs
+11 −11 NWebDav.Server/Props/DavTypedProperties.cs
+5 −5 NWebDav.Server/Props/DefaultLockingProperties.cs
+3 −3 NWebDav.Server/Props/IPropertyManager.cs
+6 −6 NWebDav.Server/Props/OverridePropertyManager.cs
+5 −5 NWebDav.Server/Props/PropertyManager.cs
+3 −3 NWebDav.Server/Props/QuotaProperties.cs
+12 −12 NWebDav.Server/Props/StandardProperties.cs
+5 −5 NWebDav.Server/Props/Win32Properties.cs
+245 −0 NWebDav.Server/Storage/BackedDavFile.cs
+426 −0 NWebDav.Server/Storage/BackedDavFolder.cs
+145 −0 NWebDav.Server/Storage/BackedDavStore.cs
+0 −21 NWebDav.Server/Storage/DavFile.cs
+0 −111 NWebDav.Server/Storage/DavFolder.cs
+0 −52 NWebDav.Server/Storage/DavStorable.cs
+2 −1 NWebDav.Server/Storage/IDavFile.cs
+11 −3 NWebDav.Server/Storage/IDavFolder.cs
+14 −1 NWebDav.Server/Storage/IDavStorable.cs
+98 −0 NWebDav.Server/Storage/LengthLimitedStream.cs
+8 −7 NWebDav.Server/Stores/DiskStore.cs
+126 −102 NWebDav.Server/Stores/DiskStoreCollection.cs
+66 −48 NWebDav.Server/Stores/DiskStoreFile.cs
+3 −2 NWebDav.Server/Stores/IStore.cs
+0 −34 NWebDav.Server/Stores/IStoreCollection.cs
+0 −15 NWebDav.Server/Stores/IStoreFile.cs
+0 −20 NWebDav.Server/Stores/IStoreItem.cs
+5 −4 NWebDav.Server/Stores/RootDiskStore.cs
+3 −2 NWebDav.Server/Stores/StoreResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ public static AesSiv128 CreateInstance(ReadOnlySpan<byte> dekKey, ReadOnlySpan<b
macKey.CopyTo(longKeySpan.Slice(dekKey.Length));

var aesCmacSiv = Aead.CreateAesCmacSiv(longKey);

return new AesSiv128(aesCmacSiv);
}

Expand Down
4 changes: 3 additions & 1 deletion src/Core/SecureFolderFS.Core.Cryptography/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ public static class KeyTraits
public const int DEK_KEY_LENGTH = 32;
public const int MAC_KEY_LENGTH = 32;
public const int ARGON2_KEK_LENGTH = 32;
public const int CHALLENGE_KEY_PART_LENGTH = 128;
public const int CHALLENGE_KEY_PART_LENGTH_64 = 64;
public const int CHALLENGE_KEY_PART_LENGTH_128 = 128;
public const int ECIES_SHA256_AESGCM_STDX963_KEY_LENGTH = 32;
public const int HMAC_SHA1_HASH_LENGTH = 20;
}

public static class CipherId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using SecureFolderFS.Shared.ComponentModel;
using static SecureFolderFS.Core.Cryptography.Constants.Crypto.Chunks.AesCtrHmac;
using static SecureFolderFS.Core.Cryptography.Extensions.ContentCryptExtensions.AesCtrHmacContentExtensions;
using static SecureFolderFS.Core.Cryptography.Extensions.HeaderCryptExtensions.AesCtrHmacHeaderExtensions;
Expand All @@ -12,7 +13,7 @@ namespace SecureFolderFS.Core.Cryptography.ContentCrypt
/// <inheritdoc cref="IContentCrypt"/>
internal sealed class AesCtrHmacContentCrypt : BaseContentCrypt
{
private readonly SecretKey _macKey;
private readonly IKeyUsage _macKey;

/// <inheritdoc/>
public override int ChunkPlaintextSize { get; } = CHUNK_PLAINTEXT_SIZE;
Expand All @@ -23,16 +24,17 @@ internal sealed class AesCtrHmacContentCrypt : BaseContentCrypt
/// <inheritdoc/>
public override int ChunkFirstReservedSize { get; } = CHUNK_NONCE_SIZE;

public AesCtrHmacContentCrypt(SecretKey macKey)
public AesCtrHmacContentCrypt(IKeyUsage macKey)
{
_macKey = macKey;
}

/// <inheritdoc/>
public override void EncryptChunk(ReadOnlySpan<byte> plaintextChunk, long chunkNumber, ReadOnlySpan<byte> header, Span<byte> ciphertextChunk)
[SkipLocalsInit]
public override unsafe void EncryptChunk(ReadOnlySpan<byte> plaintextChunk, long chunkNumber, ReadOnlySpan<byte> header, Span<byte> ciphertextChunk)
{
// Chunk nonce
secureRandom.GetBytes(ciphertextChunk.Slice(0, CHUNK_NONCE_SIZE));
RandomNumberGenerator.Fill(ciphertextChunk.Slice(0, CHUNK_NONCE_SIZE));

// Encrypt
AesCtr128.Encrypt(
Expand All @@ -41,34 +43,75 @@ public override void EncryptChunk(ReadOnlySpan<byte> plaintextChunk, long chunkN
ciphertextChunk.Slice(0, CHUNK_NONCE_SIZE),
ciphertextChunk.Slice(CHUNK_NONCE_SIZE, plaintextChunk.Length));

// Calculate MAC
CalculateChunkMac(
header.GetHeaderNonce(),
ciphertextChunk.Slice(0, CHUNK_NONCE_SIZE),
ciphertextChunk.Slice(CHUNK_NONCE_SIZE, plaintextChunk.Length),
chunkNumber,
ciphertextChunk.Slice(CHUNK_NONCE_SIZE + plaintextChunk.Length, CHUNK_MAC_SIZE));
// Calculate MAC using UseKey pattern
fixed (byte* headerPtr = header)
fixed (byte* ciphertextPtr = ciphertextChunk)
{
var state = (
headerPtr: (nint)headerPtr,
headerLen: header.Length,
ctPtr: (nint)ciphertextPtr,
ctLen: ciphertextChunk.Length,
ptLen: plaintextChunk.Length,
chunkNumber
);

_macKey.UseKey(state, static (macKey, s) =>
{
var hdr = new ReadOnlySpan<byte>((byte*)s.headerPtr, s.headerLen);
var ct = new Span<byte>((byte*)s.ctPtr, s.ctLen);

CalculateChunkMacStatic(
macKey,
hdr.GetHeaderNonce(),
ct.Slice(0, CHUNK_NONCE_SIZE),
ct.Slice(CHUNK_NONCE_SIZE, s.ptLen),
s.chunkNumber,
ct.Slice(CHUNK_NONCE_SIZE + s.ptLen, CHUNK_MAC_SIZE));
});
}
}

/// <inheritdoc/>
[SkipLocalsInit]
public override bool DecryptChunk(ReadOnlySpan<byte> ciphertextChunk, long chunkNumber,
ReadOnlySpan<byte> header, Span<byte> plaintextChunk)
public override unsafe bool DecryptChunk(ReadOnlySpan<byte> ciphertextChunk, long chunkNumber, ReadOnlySpan<byte> header, Span<byte> plaintextChunk)
{
// Allocate byte* for MAC
Span<byte> mac = stackalloc byte[CHUNK_MAC_SIZE];

// Calculate MAC
CalculateChunkMac(
header.GetHeaderNonce(),
ciphertextChunk.GetChunkNonce(),
ciphertextChunk.GetChunkPayload(),
chunkNumber,
mac);

// Check MAC
if (!mac.SequenceEqual(ciphertextChunk.GetChunkMac()))
return false;
// Verify MAC using UseKey pattern
fixed (byte* headerPtr = header)
fixed (byte* ciphertextPtr = ciphertextChunk)
{
var state = (
headerPtr: (nint)headerPtr,
headerLen: header.Length,
ctPtr: (nint)ciphertextPtr,
ctLen: ciphertextChunk.Length,
chunkNumber
);

var macValid = _macKey.UseKey(state, static (macKey, s) =>
{
var hdr = new ReadOnlySpan<byte>((byte*)s.headerPtr, s.headerLen);
var ct = new ReadOnlySpan<byte>((byte*)s.ctPtr, s.ctLen);

// Allocate byte* for MAC
Span<byte> mac = stackalloc byte[CHUNK_MAC_SIZE];

// Calculate MAC
CalculateChunkMacStatic(
macKey,
hdr.GetHeaderNonce(),
ct.GetChunkNonce(),
ct.GetChunkPayload(),
s.chunkNumber,
mac);

// Check MAC using constant-time comparison to prevent timing attacks
return CryptographicOperations.FixedTimeEquals(mac, ct.GetChunkMac());
});

if (!macValid)
return false;
}

// Decrypt
AesCtr128.Decrypt(
Expand All @@ -81,7 +124,7 @@ public override bool DecryptChunk(ReadOnlySpan<byte> ciphertextChunk, long chunk
}

[SkipLocalsInit]
private void CalculateChunkMac(ReadOnlySpan<byte> headerNonce, ReadOnlySpan<byte> chunkNonce, ReadOnlySpan<byte> ciphertextPayload, long chunkNumber, Span<byte> chunkMac)
private static void CalculateChunkMacStatic(ReadOnlySpan<byte> macKey, ReadOnlySpan<byte> headerNonce, ReadOnlySpan<byte> chunkNonce, ReadOnlySpan<byte> ciphertextPayload, long chunkNumber, Span<byte> chunkMac)
{
// Convert long to byte array
Span<byte> beChunkNumber = stackalloc byte[sizeof(long)];
Expand All @@ -92,12 +135,12 @@ private void CalculateChunkMac(ReadOnlySpan<byte> headerNonce, ReadOnlySpan<byte
beChunkNumber.Reverse();

// Initialize HMAC
using var hmacSha256 = IncrementalHash.CreateHMAC(HashAlgorithmName.SHA256, _macKey);
using var hmacSha256 = IncrementalHash.CreateHMAC(HashAlgorithmName.SHA256, macKey);

hmacSha256.AppendData(headerNonce); // headerNonce
hmacSha256.AppendData(beChunkNumber); // beChunkNumber
hmacSha256.AppendData(chunkNonce); // chunkNonce
hmacSha256.AppendData(ciphertextPayload); // ciphertextPayload
hmacSha256.AppendData(ciphertextPayload); // ciphertextPayload

hmacSha256.GetCurrentHash(chunkMac);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using SecureFolderFS.Core.Cryptography.Helpers;
using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using static SecureFolderFS.Core.Cryptography.Constants.Crypto.Chunks.AesGcm;
using static SecureFolderFS.Core.Cryptography.Constants.Crypto.Headers.AesGcm;
using static SecureFolderFS.Core.Cryptography.Extensions.ContentCryptExtensions.AesGcmContentExtensions;
Expand All @@ -26,11 +27,11 @@ internal sealed class AesGcmContentCrypt : BaseContentCrypt
public override void EncryptChunk(ReadOnlySpan<byte> plaintextChunk, long chunkNumber, ReadOnlySpan<byte> header, Span<byte> ciphertextChunk)
{
// Chunk nonce
secureRandom.GetBytes(ciphertextChunk.Slice(0, CHUNK_NONCE_SIZE));
RandomNumberGenerator.Fill(ciphertextChunk.Slice(0, CHUNK_NONCE_SIZE));

// Big Endian chunk number and file header nonce
Span<byte> associatedData = stackalloc byte[sizeof(long) + HEADER_NONCE_SIZE];
CryptHelpers.FillAssociatedDataBe(associatedData, header.GetHeaderNonce(), chunkNumber);
CryptHelpers.FillAssociatedDataBigEndian(associatedData, header.GetHeaderNonce(), chunkNumber);

// Encrypt
AesGcm128.Encrypt(
Expand All @@ -48,7 +49,7 @@ public override bool DecryptChunk(ReadOnlySpan<byte> ciphertextChunk, long chunk
{
// Big Endian chunk number and file header nonce
Span<byte> associatedData = stackalloc byte[sizeof(long) + HEADER_NONCE_SIZE];
CryptHelpers.FillAssociatedDataBe(associatedData, header.GetHeaderNonce(), chunkNumber);
CryptHelpers.FillAssociatedDataBigEndian(associatedData, header.GetHeaderNonce(), chunkNumber);

// Decrypt
return AesGcm128.TryDecrypt(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ namespace SecureFolderFS.Core.Cryptography.ContentCrypt
/// <inheritdoc cref="IContentCrypt"/>
internal abstract class BaseContentCrypt : IContentCrypt
{
protected readonly RandomNumberGenerator secureRandom;

/// <inheritdoc/>
public abstract int ChunkPlaintextSize { get; }

Expand All @@ -17,11 +15,6 @@ internal abstract class BaseContentCrypt : IContentCrypt
/// <inheritdoc/>
public abstract int ChunkFirstReservedSize { get; }

protected BaseContentCrypt()
{
secureRandom = RandomNumberGenerator.Create();
}

/// <inheritdoc/>
public abstract void EncryptChunk(ReadOnlySpan<byte> plaintextChunk, long chunkNumber, ReadOnlySpan<byte> header, Span<byte> ciphertextChunk);

Expand Down Expand Up @@ -61,7 +54,6 @@ public virtual long CalculatePlaintextSize(long ciphertextSize)
/// <inheritdoc/>
public virtual void Dispose()
{
secureRandom.Dispose();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using SecureFolderFS.Core.Cryptography.Helpers;
using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using static SecureFolderFS.Core.Cryptography.Constants.Crypto.Chunks.XChaCha20Poly1305;
using static SecureFolderFS.Core.Cryptography.Constants.Crypto.Headers.XChaCha20Poly1305;
using static SecureFolderFS.Core.Cryptography.Extensions.ContentCryptExtensions.XChaChaContentExtensions;
Expand All @@ -26,11 +27,11 @@ internal sealed class XChaChaContentCrypt : BaseContentCrypt
public override void EncryptChunk(ReadOnlySpan<byte> plaintextChunk, long chunkNumber, ReadOnlySpan<byte> header, Span<byte> ciphertextChunk)
{
// Chunk nonce
secureRandom.GetBytes(ciphertextChunk.Slice(0, CHUNK_NONCE_SIZE));
RandomNumberGenerator.Fill(ciphertextChunk.Slice(0, CHUNK_NONCE_SIZE));

// Big Endian chunk number and file header nonce
Span<byte> associatedData = stackalloc byte[sizeof(long) + HEADER_NONCE_SIZE];
CryptHelpers.FillAssociatedDataBe(associatedData, header.GetHeaderNonce(), chunkNumber);
CryptHelpers.FillAssociatedDataBigEndian(associatedData, header.GetHeaderNonce(), chunkNumber);

// Encrypt
XChaCha20Poly1305.Encrypt(
Expand All @@ -48,7 +49,7 @@ public override unsafe bool DecryptChunk(ReadOnlySpan<byte> ciphertextChunk, lon
{
// Big Endian chunk number and file header nonce
Span<byte> associatedData = stackalloc byte[sizeof(long) + HEADER_NONCE_SIZE];
CryptHelpers.FillAssociatedDataBe(associatedData, header.GetHeaderNonce(), chunkNumber);
CryptHelpers.FillAssociatedDataBigEndian(associatedData, header.GetHeaderNonce(), chunkNumber);

// Decrypt
return XChaCha20Poly1305.Decrypt(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using SecureFolderFS.Core.Cryptography.SecureStore;
using SecureFolderFS.Shared.ComponentModel;

namespace SecureFolderFS.Core.Cryptography.Extensions
{
/// <summary>
/// Provides extension methods for the <see cref="ManagedKey"/> class.
/// </summary>
public static class KeyExtensions
{
/// <summary>
/// Creates a copy of the specified <see cref="IKeyBytes"/> instance if it is cloneable.
/// </summary>
/// <param name="originalKey">The original <see cref="IKeyBytes"/> to copy.</param>
/// <returns>A new copy of the <see cref="IKeyBytes"/>.</returns>
public static TKey CreateCopy<TKey>(this TKey originalKey)
where TKey : IKeyUsage
{
if (originalKey is ICloneable cloneableKey)
return (TKey)cloneableKey.Clone();

throw new NotSupportedException("The provided key instance is not cloneable.");
}

/// <summary>
/// Creates a unique copy of the specified <typeparamref name="TKey"/> and disposes the original key.
/// </summary>
/// <param name="originalKey">The original <typeparamref name="TKey"/> to copy.</param>
/// <returns>A new copy of the key.</returns>
public static TKey CreateUniqueCopy<TKey>(this TKey originalKey)
where TKey : IKeyUsage
{
var copiedKey = originalKey.CreateCopy();
originalKey.Dispose();

return copiedKey;
}
}
}

This file was deleted.

Loading