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

Memory optimization #39 #40

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Standard.Licensing.sln
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Standard.Licensing", "Standard.Licensing\Standard.Licensing.csproj", "{C658755A-2F60-430B-A41E-9C11C817B909}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Standard.Licensing.Tests", "Standard.Licensing.Tests\Standard.Licensing.Tests.csproj", "{3BF56CDC-AA67-4BBC-A7F6-422920E0E2F9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Standard.Licensing.Tests", "Standard.Licensing.Tests\Standard.Licensing.Tests.csproj", "{3BF56CDC-AA67-4BBC-A7F6-422920E0E2F9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
28 changes: 24 additions & 4 deletions src/Standard.Licensing/License.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ public class License
{
private readonly XElement xmlData;
private readonly string signatureAlgorithm = X9ObjectIdentifiers.ECDsaWithSha512.Id;
private static XmlReaderSettings defaultXmlReaderSettings = new XmlReaderSettings
{
IgnoreWhitespace = true, // Ignore unnecessary whitespace nodes
IgnoreComments = true, // Skip comment nodes to reduce processing
IgnoreProcessingInstructions = true // Skip processing instructions
};

/// <summary>
/// Initializes a new instance of the <see cref="License"/> class.
Expand Down Expand Up @@ -279,7 +285,12 @@ public static License Load(string xmlString)
/// <returns>A <see cref="License"/> populated from the <see cref="Stream"/> that contains XML.</returns>
public static License Load(Stream stream)
{
return new License(XElement.Load(stream, LoadOptions.None));
// Use XmlReader for efficient XML parsing
using (var reader = XmlReader.Create(stream, defaultXmlReaderSettings))
{
var xmlData = XElement.Load(reader);
return new License(xmlData);
}
}

/// <summary>
Expand All @@ -301,7 +312,9 @@ public static License Load(TextReader reader)
/// <returns>A <see cref="License"/> populated from the <see cref="TextReader"/> that contains XML.</returns>
public static License Load(XmlReader reader)
{
return new License(XElement.Load(reader, LoadOptions.None));
// Directly load the XML from the XmlReader
var xmlData = XElement.Load(reader);
return new License(xmlData);
}

/// <summary>
Expand All @@ -311,7 +324,11 @@ public static License Load(XmlReader reader)
/// <see cref="License"/> will be written to.</param>
public void Save(Stream stream)
{
xmlData.Save(stream);
// Use XmlWriter for efficient XML writing
using (var writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true }))
{
xmlData.WriteTo(writer);
}
}

/// <summary>
Expand All @@ -321,7 +338,10 @@ public void Save(Stream stream)
/// <see cref="License"/> will be written to.</param>
public void Save(TextWriter textWriter)
{
xmlData.Save(textWriter);
using (var writer = XmlWriter.Create(textWriter, new XmlWriterSettings { Indent = true }))
{
xmlData.WriteTo(writer);
}
}

/// <summary>
Expand Down
39 changes: 30 additions & 9 deletions src/Standard.Licensing/Security/Cryptography/KeyFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,15 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System;
using System.Buffers;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;

#if NET6_0_OR_GREATER
using System.Security.Cryptography; // Use native cryptography in .NET 6.0+
#endif

namespace Standard.Licensing.Security.Cryptography
{
Expand All @@ -43,14 +48,30 @@ internal static class KeyFactory
/// <returns>The encrypted private key.</returns>
public static string ToEncryptedPrivateKeyString(AsymmetricKeyParameter key, string passPhrase)
{
var salt = new byte[16];
var secureRandom = SecureRandom.GetInstance("SHA256PRNG");
secureRandom.SetSeed(secureRandom.GenerateSeed(16)); //See Bug #135
secureRandom.NextBytes(salt);
// Rent a buffer for the salt (16 bytes for the salt)
var salt = ArrayPool<byte>.Shared.Rent(16);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential issue here as the salt array is no longer guaranteed to be 16 bytes long.


return
Convert.ToBase64String(PrivateKeyFactory.EncryptKey(keyEncryptionAlgorithm, passPhrase.ToCharArray(),
salt, 10, key));
try
{
#if NET6_0_OR_GREATER
// Use built-in cryptography (e.g., RNGCryptoServiceProvider) in .NET 6.0+
RandomNumberGenerator.Fill(salt.AsSpan(0, 16));
#else
// Use BouncyCastle for .NET Standard 2.0 or other versions
var secureRandom = SecureRandom.GetInstance("SHA256PRNG");
secureRandom.SetSeed(secureRandom.GenerateSeed(16)); // Seed generation
secureRandom.NextBytes(salt, 0, 16);
#endif
// Encrypt the key (BouncyCastle library used for all versions)
var encryptedKey = PrivateKeyFactory.EncryptKey(keyEncryptionAlgorithm, passPhrase.ToCharArray(), salt, 10, key);

return Convert.ToBase64String(encryptedKey);
}
finally
{
// Return the rented buffer to the pool
ArrayPool<byte>.Shared.Return(salt);
}
}

/// <summary>
Expand Down
3 changes: 2 additions & 1 deletion src/Standard.Licensing/Standard.Licensing.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0;net6.0;netstandard2.0;net461</TargetFrameworks>
Expand Down Expand Up @@ -47,6 +47,7 @@ v1.1.9

<ItemGroup>
<PackageReference Include="BouncyCastle.Cryptography" Version="2.4.0" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
</ItemGroup>

</Project>