Skip to content

Commit

Permalink
Improve and dedup GetNonZeroBytes (dotnet#81340)
Browse files Browse the repository at this point in the history
- RsaPaddingProcessor has its own complete copy; that now appears to be an unnecessary duplication.
- If a zero byte is found, the implementation currently looks at the rest of the bytes byte by byte.  We expect 0s to be rare, so copy in bulk instead.
  • Loading branch information
stephentoub authored Jan 31, 2023
1 parent 7c4b59c commit 4cbbaea
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ internal static void PadPkcs1Encryption(
destination[ps.Length + 2] = 0;

// 2(a). Fill PS with random data from a CSPRNG, but no zero-values.
FillNonZeroBytes(ps);
RandomNumberGeneratorImplementation.FillNonZeroBytes(ps);

source.CopyTo(mInEM);
}
Expand Down Expand Up @@ -500,37 +500,6 @@ private static void Mgf1(IncrementalHash hasher, ReadOnlySpan<byte> mgfSeed, Spa
}
}

// This is a copy of RandomNumberGeneratorImplementation.GetNonZeroBytes, but adapted
// to the object-less RandomNumberGenerator.Fill.
private static void FillNonZeroBytes(Span<byte> data)
{
while (data.Length > 0)
{
// Fill the remaining portion of the span with random bytes.
RandomNumberGenerator.Fill(data);

// Find the first zero in the remaining portion.
int indexOfFirst0Byte = data.IndexOf((byte)0);
if (indexOfFirst0Byte < 0)
{
break;
}

// If there were any zeros, shift down all non-zeros.
for (int i = indexOfFirst0Byte + 1; i < data.Length; i++)
{
if (data[i] != 0)
{
data[indexOfFirst0Byte++] = data[i];
}
}

// Request new random bytes if necessary; dont re-use
// existing bytes since they were shifted down.
data = data.Slice(indexOfFirst0Byte);
}
}

/// <summary>
/// Bitwise XOR of <paramref name="b"/> into <paramref name="a"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

namespace System.Security.Cryptography
{
internal sealed partial class RandomNumberGeneratorImplementation : RandomNumberGenerator
Expand Down Expand Up @@ -51,35 +49,52 @@ public override void GetNonZeroBytes(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);

GetNonZeroBytes(new Span<byte>(data));
FillNonZeroBytes(data);
}

public override void GetNonZeroBytes(Span<byte> data)
{
FillNonZeroBytes(data);
}

internal static void FillNonZeroBytes(Span<byte> data)
{
while (data.Length > 0)
{
// Fill the remaining portion of the span with random bytes.
GetBytes(data);
FillSpan(data);

// Find the first zero in the remaining portion.
int indexOfFirst0Byte = data.IndexOf((byte)0);
if (indexOfFirst0Byte < 0)
// Find the first zero in the remaining portion. If there isn't any, we're all done.
int first0Byte = data.IndexOf((byte)0);
if (first0Byte < 0)
{
return;
}

// If there were any zeros, shift down all non-zeros.
for (int i = indexOfFirst0Byte + 1; i < data.Length; i++)
// There's at least one zero. Shift down all non-zeros.
int zerosFound = 1;
Span<byte> remainder = data.Slice(first0Byte + 1);
while (true)
{
if (data[i] != 0)
// Find the next zero.
int next0Byte = remainder.IndexOf((byte)0);
if (next0Byte < 0)
{
data[indexOfFirst0Byte++] = data[i];
// There weren't any more zeros. Copy the remaining valid data down.
remainder.CopyTo(data.Slice(first0Byte));
break;
}

// Copy down until the next zero, then reset to continue copying from there.
remainder.Slice(0, next0Byte).CopyTo(data.Slice(first0Byte));
zerosFound++;
first0Byte += next0Byte;
remainder = remainder.Slice(next0Byte + 1);
}

// Request new random bytes if necessary; dont re-use
// existing bytes since they were shifted down.
data = data.Slice(indexOfFirst0Byte);
// Slice to any remaining space that needs to be filled. This is equal to the
// number of zeros found.
data = data.Slice(data.Length - zerosFound);
}
}
}
Expand Down

0 comments on commit 4cbbaea

Please sign in to comment.