Skip to content

Commit a148ea0

Browse files
rbenzingclaude
andcommitted
fix: replace SequenceEqual with SecureMemory.SecureCompare on secret key comparisons
Eliminates timing side-channels in SessionManager key lookup and Sodium.ValidateX25519PublicKey small-order point checks by using the constant-time sodium_memcmp wrapper instead of short-circuiting SequenceEqual. Adds SecureCompare_EqualKeys_ReturnsTrue test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent a8dd34e commit a148ea0

3 files changed

Lines changed: 22 additions & 2 deletions

File tree

LibEmiddle.Tests.Unit/SecurityTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,5 +779,25 @@ public void SecureMemoryClear_ShouldEffectivelyClearMemory()
779779
}
780780

781781
#endregion
782+
783+
#region SecureCompare Tests
784+
785+
/// <summary>
786+
/// Tests that SecureCompare correctly identifies equal and differing keys.
787+
/// </summary>
788+
[TestMethod]
789+
public void SecureCompare_EqualKeys_ReturnsTrue()
790+
{
791+
var key = new byte[32];
792+
System.Security.Cryptography.RandomNumberGenerator.Fill(key);
793+
var key2 = (byte[])key.Clone();
794+
Assert.IsTrue(LibEmiddle.Core.SecureMemory.SecureCompare(key, key2),
795+
"SecureCompare must return true for byte-identical keys");
796+
key2[0] ^= 0xFF;
797+
Assert.IsFalse(LibEmiddle.Core.SecureMemory.SecureCompare(key, key2),
798+
"SecureCompare must return false for differing keys");
799+
}
800+
801+
#endregion
782802
}
783803
}

LibEmiddle/Core/Sodium.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1391,7 +1391,7 @@ public static bool ValidateX25519PublicKey(ReadOnlySpan<byte> x25519PublicKey)
13911391
// Check against known small-order points
13921392
foreach (var smallOrder in SMALL_ORDER_POINTS)
13931393
{
1394-
if (x25519PublicKey.SequenceEqual(smallOrder))
1394+
if (SecureMemory.SecureCompare(x25519PublicKey, smallOrder))
13951395
return false;
13961396
}
13971397

LibEmiddle/Sessions/SessionManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ public async Task<IChatSession> GetOrCreateChatSessionAsync(
591591
foreach (var kv in _activeSessions)
592592
{
593593
if (kv.Value is Messaging.Chat.ChatSession cs &&
594-
cs.RemotePublicKey.AsSpan().SequenceEqual(recipientPublicKey))
594+
SecureMemory.SecureCompare(cs.RemotePublicKey, recipientPublicKey))
595595
{
596596
return cs;
597597
}

0 commit comments

Comments
 (0)