Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use cryptographically random values where required #88

Merged
merged 7 commits into from
Mar 22, 2024
5 changes: 2 additions & 3 deletions libs/cluster/Server/GarnetClusterConnectionStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT license.

using System;
using System.Security.Cryptography;
using Garnet.common;
using Microsoft.Extensions.Logging;

Expand All @@ -14,8 +15,6 @@ internal class GarnetClusterConnectionStore
int numConnection;
bool _disposed;

Random rand = new Random(Guid.NewGuid().GetHashCode());

SingleWriterMultiReaderLock _lock;

public int Count => numConnection;
Expand Down Expand Up @@ -220,7 +219,7 @@ public bool GetRandomConnection(out GarnetServerNode conn)
if (_disposed) return false;
if (numConnection == 0) return false;

var offset = rand.Next(0, numConnection);
var offset = RandomNumberGenerator.GetInt32(0, numConnection);
conn = connections[offset];
return true;
}
Expand Down
19 changes: 8 additions & 11 deletions libs/common/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,25 @@
// Licensed under the MIT license.

using System;
using System.Text;
using System.Security.Cryptography;

namespace Garnet.common
{
/// <summary>
/// Collection of methods generating hex ids
/// </summary>
public class Generator
public static class Generator
{
static ReadOnlySpan<byte> hexchars => "0123456789abcdef"u8;

/// <summary>
/// Random hex id
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
public static string CreateHexId(int size = 40)
{
var NodeId = new byte[size];
new Random(Guid.NewGuid().GetHashCode()).NextBytes(NodeId);
for (int i = 0; i < NodeId.Length; i++) NodeId[i] = hexchars[NodeId[i] & 0xf];
return Encoding.ASCII.GetString(NodeId);
Span<byte> nodeIdBuffer = stackalloc byte[size];
RandomNumberGenerator.Fill(nodeIdBuffer);
vazois marked this conversation as resolved.
Show resolved Hide resolved
return Convert.ToHexString(nodeIdBuffer).ToLowerInvariant();
}

/// <summary>
Expand All @@ -33,9 +30,9 @@ public static string CreateHexId(int size = 40)
/// <returns></returns>
public static string DefaultHexId(int size = 40)
{
var NodeId = new byte[size];
for (int i = 0; i < NodeId.Length; i++) NodeId[i] = hexchars[0];
return Encoding.ASCII.GetString(NodeId);
Span<byte> nodeIdBuffer = stackalloc byte[size];
nodeIdBuffer.Clear();
return Convert.ToHexString(nodeIdBuffer).ToLowerInvariant();
}
}
}
8 changes: 3 additions & 5 deletions libs/server/Objects/Hash/HashObjectImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Buffers;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Garnet.common;
using Tsavorite.core;
Expand Down Expand Up @@ -215,7 +216,6 @@ private void HashRandomField(byte* input, int length, ref SpanByteAndMemory outp
ObjectOutputHeader _output = default;
try
{
Random random = new();
var withValues = false;
int[] indexes = default;

Expand Down Expand Up @@ -270,9 +270,7 @@ private void HashRandomField(byte* input, int length, ref SpanByteAndMemory outp
countParameter = Math.Abs(countParameter);
indexes = new int[countParameter];
for (int i = 0; i < countParameter; i++)
indexes[i] = random.Next(0, hash.Count);
// Shuffle
indexes = indexes.OrderBy(x => random.Next()).ToArray();
indexes[i] = RandomNumberGenerator.GetInt32(0, hash.Count);
}

// Write the size of the array reply
Expand All @@ -296,7 +294,7 @@ private void HashRandomField(byte* input, int length, ref SpanByteAndMemory outp
else if (count == 2) // No count parameter or withvalues is present, we just return a random field
{
// Write a bulk string value of a random field from the hash value stored at key.
int index = random.Next(hash.Count);
int index = RandomNumberGenerator.GetInt32(0, hash.Count);
var pair = hash.ElementAt(index);
while (!RespWriteUtils.WriteBulkString(pair.Key, ref curr, end))
ObjectUtils.ReallocateOutput(ref output, ref isMemory, ref ptr, ref ptrHandle, ref curr, ref end);
Expand Down
8 changes: 3 additions & 5 deletions libs/server/Objects/Set/SetObjectImpl.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

using System;
using System.Buffers;
using System.Linq;
using System.Security.Cryptography;
using Garnet.common;
using Tsavorite.core;

Expand Down Expand Up @@ -142,8 +142,6 @@ private void SetLength(byte* input, int length, byte* output)
_output->bytesDone = 0;
}

static readonly Random random = new();

private void SetPop(byte* input, int length, ref SpanByteAndMemory output)
{
// SPOP key[count]
Expand Down Expand Up @@ -178,7 +176,7 @@ private void SetPop(byte* input, int length, ref SpanByteAndMemory output)
for (int i = 0; i < countParameter; i++)
{
// Generate a new index based on the elements left in the set
var index = random.Next(0, set.Count - 1);
var index = RandomNumberGenerator.GetInt32(0, set.Count - 1);
var item = set.ElementAt(index);
set.Remove(item);
this.UpdateSize(item, false);
Expand All @@ -190,7 +188,7 @@ private void SetPop(byte* input, int length, ref SpanByteAndMemory output)
else if (count == int.MinValue) // no count parameter is present, we just pop and return a random item of the set
{
// Write a bulk string value of a random field from the hash value stored at key.
int index = random.Next(set.Count);
int index = RandomNumberGenerator.GetInt32(0, set.Count);
var item = set.ElementAt(index);
set.Remove(item);
this.UpdateSize(item, false);
Expand Down
7 changes: 2 additions & 5 deletions libs/server/Objects/SortedSet/SortedSetObjectImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Garnet.common;
using Tsavorite.core;
Expand Down Expand Up @@ -651,7 +652,6 @@ private void SortedSetRandomMember(byte* input, int length, ref SpanByteAndMemor
MemoryHandle ptrHandle = default;
byte* ptr = output.SpanByte.ToPointer();

Random random = new();
var curr = ptr;
var end = curr + output.Length;

Expand Down Expand Up @@ -680,10 +680,7 @@ private void SortedSetRandomMember(byte* input, int length, ref SpanByteAndMemor
// The order of fields in the reply is truly random.
indexes = new int[Math.Abs(count)];
for (int i = 0; i < indexes.Length; i++)
indexes[i] = random.Next(0, sortedSetDict.Count);

// Guarantee random order
indexes = indexes.OrderBy(x => random.Next()).ToArray();
indexes[i] = RandomNumberGenerator.GetInt32(0, sortedSetDict.Count);
}

foreach (var item in indexes)
Expand Down
Loading