mirror of
https://github.com/AlexMacocian/SystemExtensions.git
synced 2026-07-24 03:56:27 +00:00
Improve IHttpClient factories (#20)
Codestyle fixes Setup CODEOWNERS Setup dependabot
This commit is contained in:
@@ -4,224 +4,223 @@ using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Utilities;
|
||||
|
||||
namespace System.Security.Encryption
|
||||
namespace System.Security.Encryption;
|
||||
|
||||
public sealed class AesEncrypter : ISymmetricEncrypter, IDisposable
|
||||
{
|
||||
public sealed class AesEncrypter : ISymmetricEncrypter, IDisposable
|
||||
private readonly Aes aes;
|
||||
|
||||
public AesEncrypter()
|
||||
{
|
||||
private readonly Aes aes;
|
||||
this.aes = Aes.Create();
|
||||
}
|
||||
|
||||
public AesEncrypter()
|
||||
public AesEncrypter(Aes aes)
|
||||
{
|
||||
this.aes = aes;
|
||||
}
|
||||
|
||||
public async Task<string> Decrypt(string key, string iv, string value)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var decryptedStream = await this.DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToString(decryptedStream);
|
||||
}
|
||||
|
||||
public async Task<string> Decrypt(byte[] key, byte[] iv, string value)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var decryptedStream = await this.DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToString(decryptedStream);
|
||||
}
|
||||
|
||||
public async Task<byte[]> Decrypt(string key, string iv, byte[] value)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var decryptedStream = await this.DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(decryptedStream);
|
||||
}
|
||||
|
||||
public async Task<byte[]> Decrypt(byte[] key, byte[] iv, byte[] value)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var decryptedStream = await this.DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(decryptedStream);
|
||||
}
|
||||
|
||||
public async Task<Stream> Decrypt(string key, string iv, Stream value)
|
||||
{
|
||||
return await this.DecryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<Stream> Decrypt(byte[] key, byte[] iv, Stream value)
|
||||
{
|
||||
return await this.DecryptInternal(key, iv, value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<string> Encrypt(string key, string iv, string value)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var encryptedStream = await this.EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToString(encryptedStream);
|
||||
}
|
||||
|
||||
public async Task<string> Encrypt(byte[] key, byte[] iv, string value)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var encryptedStream = await this.EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToString(encryptedStream);
|
||||
}
|
||||
|
||||
public async Task<byte[]> Encrypt(string key, string iv, byte[] value)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var encryptedStream = await this.EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(encryptedStream);
|
||||
}
|
||||
|
||||
public async Task<byte[]> Encrypt(byte[] key, byte[] iv, byte[] value)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var encryptedStream = await this.EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(encryptedStream);
|
||||
}
|
||||
|
||||
public async Task<Stream> Encrypt(string key, string iv, Stream value)
|
||||
{
|
||||
return value is null
|
||||
? throw new ArgumentNullException(nameof(value))
|
||||
: await this.EncryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<Stream> Encrypt(byte[] key, byte[] iv, Stream value)
|
||||
{
|
||||
return value is null
|
||||
? throw new ArgumentNullException(nameof(value))
|
||||
: await this.EncryptInternal(key, iv, value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Stream GetEncryptionStream(string key, string iv, Stream outStream)
|
||||
{
|
||||
return this.GetEncryptionStreamInternal(StringToBytes(key), StringToBytes(iv), outStream);
|
||||
}
|
||||
|
||||
public Stream GetEncryptionStream(byte[] key, byte[] iv, Stream outStream)
|
||||
{
|
||||
return this.GetEncryptionStreamInternal(key, iv, outStream);
|
||||
}
|
||||
|
||||
public Stream GetDecryptionStream(string key, string iv, Stream inStream)
|
||||
{
|
||||
return this.GetDecryptionStreamInternal(StringToBytes(key), StringToBytes(iv), inStream);
|
||||
}
|
||||
|
||||
public Stream GetDecryptionStream(byte[] key, byte[] iv, Stream inStream)
|
||||
{
|
||||
return this.GetDecryptionStreamInternal(key, iv, inStream);
|
||||
}
|
||||
|
||||
private async Task<Stream> EncryptInternal(byte[] key, byte[] iv, Stream toEncryptStream)
|
||||
{
|
||||
if (key.Length < 32)
|
||||
{
|
||||
this.aes = Aes.Create();
|
||||
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
|
||||
}
|
||||
|
||||
public AesEncrypter(Aes aes)
|
||||
if (iv.Length < 16)
|
||||
{
|
||||
this.aes = aes;
|
||||
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
|
||||
}
|
||||
|
||||
public async Task<string> Decrypt(string key, string iv, string value)
|
||||
key = key.Take(32).ToArray();
|
||||
iv = iv.Take(16).ToArray();
|
||||
|
||||
|
||||
var encryptedMemoryStream = new MemoryStream();
|
||||
using var cryptoStream = this.GetEncryptionStreamInternal(key, iv, encryptedMemoryStream);
|
||||
await toEncryptStream.CopyToAsync(cryptoStream).ConfigureAwait(false);
|
||||
if (!cryptoStream.HasFlushedFinalBlock)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var decryptedStream = await DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToString(decryptedStream);
|
||||
cryptoStream.FlushFinalBlock();
|
||||
}
|
||||
|
||||
public async Task<string> Decrypt(byte[] key, byte[] iv, string value)
|
||||
encryptedMemoryStream.Position = 0;
|
||||
return encryptedMemoryStream;
|
||||
}
|
||||
|
||||
private async Task<Stream> DecryptInternal(byte[] key, byte[] iv, Stream toDecryptStream)
|
||||
{
|
||||
if (key.Length < 32)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var decryptedStream = await DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToString(decryptedStream);
|
||||
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
|
||||
}
|
||||
|
||||
public async Task<byte[]> Decrypt(string key, string iv, byte[] value)
|
||||
if (iv.Length < 16)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var decryptedStream = await DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(decryptedStream);
|
||||
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
|
||||
}
|
||||
|
||||
public async Task<byte[]> Decrypt(byte[] key, byte[] iv, byte[] value)
|
||||
key = key.Take(32).ToArray();
|
||||
iv = iv.Take(16).ToArray();
|
||||
|
||||
|
||||
var decryptedMemoryStream = new MemoryStream();
|
||||
using var cryptoStream = this.GetDecryptionStreamInternal(key, iv, toDecryptStream);
|
||||
await cryptoStream.CopyToAsync(decryptedMemoryStream).ConfigureAwait(false);
|
||||
if (!cryptoStream.HasFlushedFinalBlock)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var decryptedStream = await DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(decryptedStream);
|
||||
cryptoStream.FlushFinalBlock();
|
||||
}
|
||||
|
||||
public async Task<Stream> Decrypt(string key, string iv, Stream value)
|
||||
decryptedMemoryStream.Position = 0;
|
||||
return decryptedMemoryStream;
|
||||
}
|
||||
|
||||
private CryptoStream GetEncryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
|
||||
{
|
||||
var crypto = this.aes.CreateEncryptor(key, iv);
|
||||
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Write);
|
||||
return cryptoStream;
|
||||
}
|
||||
|
||||
private CryptoStream GetDecryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
|
||||
{
|
||||
var crypto = this.aes.CreateDecryptor(key, iv);
|
||||
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Read);
|
||||
return cryptoStream;
|
||||
}
|
||||
|
||||
private static byte[] StreamToBytes(Stream value)
|
||||
{
|
||||
value.Position = 0;
|
||||
var buffer = new byte[1024];
|
||||
using var ms = new MemoryStream();
|
||||
var read = -1;
|
||||
do
|
||||
{
|
||||
return await DecryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
|
||||
}
|
||||
read = value.Read(buffer, 0, buffer.Length);
|
||||
ms.Write(buffer, 0, read);
|
||||
} while (read > 0);
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
public async Task<Stream> Decrypt(byte[] key, byte[] iv, Stream value)
|
||||
{
|
||||
return await DecryptInternal(key, iv, value).ConfigureAwait(false);
|
||||
}
|
||||
private static string StreamToString(Stream value)
|
||||
{
|
||||
return Convert.ToBase64String(StreamToBytes(value));
|
||||
}
|
||||
|
||||
public async Task<string> Encrypt(string key, string iv, string value)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var encryptedStream = await EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToString(encryptedStream);
|
||||
}
|
||||
private static byte[] StringToBytes(string value)
|
||||
{
|
||||
return Convert.FromBase64String(value);
|
||||
}
|
||||
|
||||
public async Task<string> Encrypt(byte[] key, byte[] iv, string value)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var encryptedStream = await EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToString(encryptedStream);
|
||||
}
|
||||
private static Stream BytesToStream(byte[] value)
|
||||
{
|
||||
return new MemoryStream(value);
|
||||
}
|
||||
|
||||
public async Task<byte[]> Encrypt(string key, string iv, byte[] value)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var encryptedStream = await EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(encryptedStream);
|
||||
}
|
||||
|
||||
public async Task<byte[]> Encrypt(byte[] key, byte[] iv, byte[] value)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var encryptedStream = await EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(encryptedStream);
|
||||
}
|
||||
|
||||
public async Task<Stream> Encrypt(string key, string iv, Stream value)
|
||||
{
|
||||
return value is null
|
||||
? throw new ArgumentNullException(nameof(value))
|
||||
: await EncryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<Stream> Encrypt(byte[] key, byte[] iv, Stream value)
|
||||
{
|
||||
return value is null
|
||||
? throw new ArgumentNullException(nameof(value))
|
||||
: await EncryptInternal(key, iv, value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Stream GetEncryptionStream(string key, string iv, Stream outStream)
|
||||
{
|
||||
return GetEncryptionStreamInternal(StringToBytes(key), StringToBytes(iv), outStream);
|
||||
}
|
||||
|
||||
public Stream GetEncryptionStream(byte[] key, byte[] iv, Stream outStream)
|
||||
{
|
||||
return GetEncryptionStreamInternal(key, iv, outStream);
|
||||
}
|
||||
|
||||
public Stream GetDecryptionStream(string key, string iv, Stream inStream)
|
||||
{
|
||||
return GetDecryptionStreamInternal(StringToBytes(key), StringToBytes(iv), inStream);
|
||||
}
|
||||
|
||||
public Stream GetDecryptionStream(byte[] key, byte[] iv, Stream inStream)
|
||||
{
|
||||
return GetDecryptionStreamInternal(key, iv, inStream);
|
||||
}
|
||||
|
||||
private async Task<Stream> EncryptInternal(byte[] key, byte[] iv, Stream toEncryptStream)
|
||||
{
|
||||
if (key.Length < 32)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
|
||||
}
|
||||
|
||||
if (iv.Length < 16)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
|
||||
}
|
||||
|
||||
key = key.Take(32).ToArray();
|
||||
iv = iv.Take(16).ToArray();
|
||||
|
||||
|
||||
var encryptedMemoryStream = new MemoryStream();
|
||||
using var cryptoStream = this.GetEncryptionStreamInternal(key, iv, encryptedMemoryStream);
|
||||
await toEncryptStream.CopyToAsync(cryptoStream).ConfigureAwait(false);
|
||||
if (!cryptoStream.HasFlushedFinalBlock)
|
||||
{
|
||||
cryptoStream.FlushFinalBlock();
|
||||
}
|
||||
|
||||
encryptedMemoryStream.Position = 0;
|
||||
return encryptedMemoryStream;
|
||||
}
|
||||
|
||||
private async Task<Stream> DecryptInternal(byte[] key, byte[] iv, Stream toDecryptStream)
|
||||
{
|
||||
if (key.Length < 32)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
|
||||
}
|
||||
|
||||
if (iv.Length < 16)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
|
||||
}
|
||||
|
||||
key = key.Take(32).ToArray();
|
||||
iv = iv.Take(16).ToArray();
|
||||
|
||||
|
||||
var decryptedMemoryStream = new MemoryStream();
|
||||
using var cryptoStream = this.GetDecryptionStreamInternal(key, iv, toDecryptStream);
|
||||
await cryptoStream.CopyToAsync(decryptedMemoryStream).ConfigureAwait(false);
|
||||
if (!cryptoStream.HasFlushedFinalBlock)
|
||||
{
|
||||
cryptoStream.FlushFinalBlock();
|
||||
}
|
||||
|
||||
decryptedMemoryStream.Position = 0;
|
||||
return decryptedMemoryStream;
|
||||
}
|
||||
|
||||
private CryptoStream GetEncryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
|
||||
{
|
||||
var crypto = this.aes.CreateEncryptor(key, iv);
|
||||
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Write);
|
||||
return cryptoStream;
|
||||
}
|
||||
|
||||
private CryptoStream GetDecryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
|
||||
{
|
||||
var crypto = this.aes.CreateDecryptor(key, iv);
|
||||
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Read);
|
||||
return cryptoStream;
|
||||
}
|
||||
|
||||
private static byte[] StreamToBytes(Stream value)
|
||||
{
|
||||
value.Position = 0;
|
||||
var buffer = new byte[1024];
|
||||
using var ms = new MemoryStream();
|
||||
var read = -1;
|
||||
do
|
||||
{
|
||||
read = value.Read(buffer, 0, buffer.Length);
|
||||
ms.Write(buffer, 0, read);
|
||||
} while (read > 0);
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private static string StreamToString(Stream value)
|
||||
{
|
||||
return Convert.ToBase64String(StreamToBytes(value));
|
||||
}
|
||||
|
||||
private static byte[] StringToBytes(string value)
|
||||
{
|
||||
return Convert.FromBase64String(value);
|
||||
}
|
||||
|
||||
private static Stream BytesToStream(byte[] value)
|
||||
{
|
||||
return new MemoryStream(value);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.aes.Dispose();
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
this.aes.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Encryption
|
||||
namespace System.Security.Encryption;
|
||||
|
||||
public interface ISymmetricEncrypter
|
||||
{
|
||||
public interface ISymmetricEncrypter
|
||||
{
|
||||
Stream GetEncryptionStream(string key, string iv, Stream outStream);
|
||||
Stream GetEncryptionStream(byte[] key, byte[] iv, Stream outStream);
|
||||
Stream GetDecryptionStream(string key, string iv, Stream inStream);
|
||||
Stream GetDecryptionStream(byte[] key, byte[] iv, Stream inStream);
|
||||
Task<string> Encrypt(string key, string iv, string value);
|
||||
Task<string> Encrypt(byte[] key, byte[] iv, string value);
|
||||
Task<byte[]> Encrypt(string key, string iv, byte[] value);
|
||||
Task<byte[]> Encrypt(byte[] key, byte[] iv, byte[] value);
|
||||
Task<Stream> Encrypt(string key, string iv, Stream value);
|
||||
Task<Stream> Encrypt(byte[] key, byte[] iv, Stream value);
|
||||
Task<string> Decrypt(string key, string iv, string value);
|
||||
Task<string> Decrypt(byte[] key, byte[] iv, string value);
|
||||
Task<byte[]> Decrypt(string key, string iv, byte[] value);
|
||||
Task<byte[]> Decrypt(byte[] key, byte[] iv, byte[] value);
|
||||
Task<Stream> Decrypt(string key, string iv, Stream value);
|
||||
Task<Stream> Decrypt(byte[] key, byte[] iv, Stream value);
|
||||
}
|
||||
Stream GetEncryptionStream(string key, string iv, Stream outStream);
|
||||
Stream GetEncryptionStream(byte[] key, byte[] iv, Stream outStream);
|
||||
Stream GetDecryptionStream(string key, string iv, Stream inStream);
|
||||
Stream GetDecryptionStream(byte[] key, byte[] iv, Stream inStream);
|
||||
Task<string> Encrypt(string key, string iv, string value);
|
||||
Task<string> Encrypt(byte[] key, byte[] iv, string value);
|
||||
Task<byte[]> Encrypt(string key, string iv, byte[] value);
|
||||
Task<byte[]> Encrypt(byte[] key, byte[] iv, byte[] value);
|
||||
Task<Stream> Encrypt(string key, string iv, Stream value);
|
||||
Task<Stream> Encrypt(byte[] key, byte[] iv, Stream value);
|
||||
Task<string> Decrypt(string key, string iv, string value);
|
||||
Task<string> Decrypt(byte[] key, byte[] iv, string value);
|
||||
Task<byte[]> Decrypt(string key, string iv, byte[] value);
|
||||
Task<byte[]> Decrypt(byte[] key, byte[] iv, byte[] value);
|
||||
Task<Stream> Decrypt(string key, string iv, Stream value);
|
||||
Task<Stream> Decrypt(byte[] key, byte[] iv, Stream value);
|
||||
}
|
||||
|
||||
@@ -1,102 +1,101 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Security.Encryption
|
||||
namespace System.Security.Encryption;
|
||||
|
||||
public sealed class SecureString
|
||||
{
|
||||
public sealed class SecureString
|
||||
private static byte[] optionalEntropy;
|
||||
private byte[] encryptedValue;
|
||||
|
||||
public string Value {
|
||||
get => this.encryptedValue is not null ? Encoding.UTF8.GetString(ProtectedData.Unprotect(this.encryptedValue, optionalEntropy, DataProtectionScope.CurrentUser)) : null;
|
||||
private set => this.encryptedValue = ProtectedData.Protect(Encoding.UTF8.GetBytes(value), optionalEntropy, DataProtectionScope.CurrentUser);
|
||||
}
|
||||
|
||||
public SecureString(string value)
|
||||
{
|
||||
private static byte[] optionalEntropy;
|
||||
private byte[] encryptedValue;
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
public string Value {
|
||||
get => this.encryptedValue is not null ? Encoding.UTF8.GetString(ProtectedData.Unprotect(this.encryptedValue, optionalEntropy, DataProtectionScope.CurrentUser)) : null;
|
||||
private set => this.encryptedValue = ProtectedData.Protect(Encoding.UTF8.GetBytes(value), optionalEntropy, DataProtectionScope.CurrentUser);
|
||||
}
|
||||
|
||||
public SecureString(string value)
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is string)
|
||||
{
|
||||
this.Value = value;
|
||||
return this == (obj as string);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
else if (obj is SecureString)
|
||||
{
|
||||
if (obj is string)
|
||||
{
|
||||
return this == (obj as string);
|
||||
}
|
||||
else if (obj is SecureString)
|
||||
{
|
||||
return this == (obj as SecureString);
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.Equals(obj);
|
||||
}
|
||||
return this == (obj as SecureString);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
else
|
||||
{
|
||||
return this.Value.GetHashCode();
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Value;
|
||||
}
|
||||
|
||||
public static readonly SecureString Empty = new(string.Empty);
|
||||
public static implicit operator string(SecureString ss) => ss is null ? string.Empty : ss.Value;
|
||||
public static implicit operator SecureString(string s) => new(s);
|
||||
public static SecureString operator +(SecureString ss1, SecureString ss2)
|
||||
{
|
||||
if (ss1 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss1));
|
||||
}
|
||||
|
||||
if (ss2 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss2));
|
||||
}
|
||||
|
||||
return new SecureString(ss1.Value + ss2.Value);
|
||||
}
|
||||
public static SecureString operator +(SecureString ss1, string s2)
|
||||
{
|
||||
if (ss1 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss1));
|
||||
}
|
||||
|
||||
return new SecureString(ss1.Value + s2);
|
||||
}
|
||||
public static SecureString operator +(SecureString ss1, char c)
|
||||
{
|
||||
if (ss1 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss1));
|
||||
}
|
||||
|
||||
return new SecureString(ss1.Value + c);
|
||||
}
|
||||
public static bool operator ==(SecureString ss1, SecureString ss2)
|
||||
{
|
||||
return ss1?.Value == ss2?.Value;
|
||||
}
|
||||
public static bool operator !=(SecureString ss1, SecureString ss2)
|
||||
{
|
||||
return !(ss1 == ss2);
|
||||
}
|
||||
public static bool operator ==(SecureString ss1, string s2)
|
||||
{
|
||||
return ss1?.Value == s2;
|
||||
}
|
||||
public static bool operator !=(SecureString ss1, string s2)
|
||||
{
|
||||
return !(ss1?.Value == s2);
|
||||
}
|
||||
|
||||
public static void AddOptionalEntropy(byte[] entropy)
|
||||
{
|
||||
optionalEntropy = entropy;
|
||||
return base.Equals(obj);
|
||||
}
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Value.GetHashCode();
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Value;
|
||||
}
|
||||
|
||||
public static readonly SecureString Empty = new(string.Empty);
|
||||
public static implicit operator string(SecureString ss) => ss is null ? string.Empty : ss.Value;
|
||||
public static implicit operator SecureString(string s) => new(s);
|
||||
public static SecureString operator +(SecureString ss1, SecureString ss2)
|
||||
{
|
||||
if (ss1 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss1));
|
||||
}
|
||||
|
||||
if (ss2 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss2));
|
||||
}
|
||||
|
||||
return new SecureString(ss1.Value + ss2.Value);
|
||||
}
|
||||
public static SecureString operator +(SecureString ss1, string s2)
|
||||
{
|
||||
if (ss1 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss1));
|
||||
}
|
||||
|
||||
return new SecureString(ss1.Value + s2);
|
||||
}
|
||||
public static SecureString operator +(SecureString ss1, char c)
|
||||
{
|
||||
if (ss1 is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(ss1));
|
||||
}
|
||||
|
||||
return new SecureString(ss1.Value + c);
|
||||
}
|
||||
public static bool operator ==(SecureString ss1, SecureString ss2)
|
||||
{
|
||||
return ss1?.Value == ss2?.Value;
|
||||
}
|
||||
public static bool operator !=(SecureString ss1, SecureString ss2)
|
||||
{
|
||||
return !(ss1 == ss2);
|
||||
}
|
||||
public static bool operator ==(SecureString ss1, string s2)
|
||||
{
|
||||
return ss1?.Value == s2;
|
||||
}
|
||||
public static bool operator !=(SecureString ss1, string s2)
|
||||
{
|
||||
return !(ss1?.Value == s2);
|
||||
}
|
||||
|
||||
public static void AddOptionalEntropy(byte[] entropy)
|
||||
{
|
||||
optionalEntropy = entropy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Hashing
|
||||
namespace System.Security.Hashing;
|
||||
|
||||
public interface IHashingService
|
||||
{
|
||||
public interface IHashingService
|
||||
{
|
||||
Task<string> Hash(string raw);
|
||||
Task<byte[]> Hash(byte[] raw);
|
||||
Task<Stream> Hash(Stream raw);
|
||||
}
|
||||
Task<string> Hash(string raw);
|
||||
Task<byte[]> Hash(byte[] raw);
|
||||
Task<Stream> Hash(Stream raw);
|
||||
}
|
||||
|
||||
@@ -1,47 +1,46 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Hashing
|
||||
namespace System.Security.Hashing;
|
||||
|
||||
public interface IPasswordHashingService
|
||||
{
|
||||
public interface IPasswordHashingService
|
||||
{
|
||||
/// <summary>
|
||||
/// Hash provided raw password and return the hashed value.
|
||||
/// </summary>
|
||||
/// <param name="raw">Base64 encoded password.</param>
|
||||
/// <param name="salt">Base64 encoded salt to be used for hashing.</param>
|
||||
/// <param name="length">Length of the resulting hash.</param>
|
||||
/// <param name="iterations">Number of hashing iterations to be performed.</param>
|
||||
/// <remarks>
|
||||
/// The length of the hash will vary due to the base64 encoding of the resulting hash.
|
||||
/// </remarks>
|
||||
/// <returns>Base64 encoded hashed password.</returns>
|
||||
Task<string> Hash(string raw, string salt, int length, int iterations);
|
||||
/// <summary>
|
||||
/// Hash provided raw password and return the hashed value.
|
||||
/// </summary>
|
||||
/// <param name="raw">Password to be hashed.</param>
|
||||
/// <param name="salt">Salt to be used for hashing.</param>
|
||||
/// <param name="length">Length of the resulting hash.</param>
|
||||
/// <param name="iterations">Number of hashing iterations to be performed.</param>
|
||||
/// <returns>Hashed password.</returns>
|
||||
Task<byte[]> Hash(byte[] raw, byte[] salt, int length, int iterations);
|
||||
/// <summary>
|
||||
/// Verify provided password against a hashed password.
|
||||
/// </summary>
|
||||
/// <param name="hash">Base64 encoding of the previously hashed password.</param>
|
||||
/// <param name="password">Base64 encoding of the password to be verified.</param>
|
||||
/// <param name="salt">Salt used to hash the previous password.</param>
|
||||
/// <param name="iterations">Number of iterations used to hash the previous password.</param>
|
||||
/// <returns>Returns true if password matches the previously hashed password. Otherwise returns false.</returns>
|
||||
Task<bool> VerifyPassword(string hash, string password, string salt, int iterations);
|
||||
/// <summary>
|
||||
/// Verify provided password against a hashed password.
|
||||
/// </summary>
|
||||
/// <param name="hash">Previously hashed password.</param>
|
||||
/// <param name="password">Password to be verified.</param>
|
||||
/// <param name="salt">Salt used to hash the previous password.</param>
|
||||
/// <param name="iterations">Number of iterations used to hash the previous password.</param>
|
||||
/// <returns>Returns true if password matches the previously hashed password. Otherwise returns false.</returns>
|
||||
Task<bool> VerifyPassword(byte[] hash, byte[] password, byte[] salt, int iterations);
|
||||
}
|
||||
/// <summary>
|
||||
/// Hash provided raw password and return the hashed value.
|
||||
/// </summary>
|
||||
/// <param name="raw">Base64 encoded password.</param>
|
||||
/// <param name="salt">Base64 encoded salt to be used for hashing.</param>
|
||||
/// <param name="length">Length of the resulting hash.</param>
|
||||
/// <param name="iterations">Number of hashing iterations to be performed.</param>
|
||||
/// <remarks>
|
||||
/// The length of the hash will vary due to the base64 encoding of the resulting hash.
|
||||
/// </remarks>
|
||||
/// <returns>Base64 encoded hashed password.</returns>
|
||||
Task<string> Hash(string raw, string salt, int length, int iterations);
|
||||
/// <summary>
|
||||
/// Hash provided raw password and return the hashed value.
|
||||
/// </summary>
|
||||
/// <param name="raw">Password to be hashed.</param>
|
||||
/// <param name="salt">Salt to be used for hashing.</param>
|
||||
/// <param name="length">Length of the resulting hash.</param>
|
||||
/// <param name="iterations">Number of hashing iterations to be performed.</param>
|
||||
/// <returns>Hashed password.</returns>
|
||||
Task<byte[]> Hash(byte[] raw, byte[] salt, int length, int iterations);
|
||||
/// <summary>
|
||||
/// Verify provided password against a hashed password.
|
||||
/// </summary>
|
||||
/// <param name="hash">Base64 encoding of the previously hashed password.</param>
|
||||
/// <param name="password">Base64 encoding of the password to be verified.</param>
|
||||
/// <param name="salt">Salt used to hash the previous password.</param>
|
||||
/// <param name="iterations">Number of iterations used to hash the previous password.</param>
|
||||
/// <returns>Returns true if password matches the previously hashed password. Otherwise returns false.</returns>
|
||||
Task<bool> VerifyPassword(string hash, string password, string salt, int iterations);
|
||||
/// <summary>
|
||||
/// Verify provided password against a hashed password.
|
||||
/// </summary>
|
||||
/// <param name="hash">Previously hashed password.</param>
|
||||
/// <param name="password">Password to be verified.</param>
|
||||
/// <param name="salt">Salt used to hash the previous password.</param>
|
||||
/// <param name="iterations">Number of iterations used to hash the previous password.</param>
|
||||
/// <returns>Returns true if password matches the previously hashed password. Otherwise returns false.</returns>
|
||||
Task<bool> VerifyPassword(byte[] hash, byte[] password, byte[] salt, int iterations);
|
||||
}
|
||||
|
||||
+87
-88
@@ -1,101 +1,100 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Hashing
|
||||
namespace System.Security.Hashing;
|
||||
|
||||
public sealed class Rfc2898DeriveBytesPasswordHashingService : IPasswordHashingService
|
||||
{
|
||||
public sealed class Rfc2898DeriveBytesPasswordHashingService : IPasswordHashingService
|
||||
private const int MinimumIterations = 10000;
|
||||
private const int MinimumHashLength = 32;
|
||||
|
||||
public Rfc2898DeriveBytesPasswordHashingService()
|
||||
{
|
||||
private const int MinimumIterations = 10000;
|
||||
private const int MinimumHashLength = 32;
|
||||
}
|
||||
|
||||
public Rfc2898DeriveBytesPasswordHashingService()
|
||||
public async Task<string> Hash(string raw, string salt, int length, int iterations)
|
||||
{
|
||||
this.ValidateHashArguments(raw, salt, length, iterations);
|
||||
|
||||
var rawBytes = Convert.FromBase64String(raw);
|
||||
var saltBytes = Convert.FromBase64String(salt);
|
||||
var hashBytes = await this.HashInternal(rawBytes, saltBytes, length, iterations);
|
||||
return Convert.ToBase64String(hashBytes);
|
||||
}
|
||||
public Task<byte[]> Hash(byte[] raw, byte[] salt, int length, int iterations)
|
||||
{
|
||||
this.ValidateHashArguments(raw, salt, length, iterations);
|
||||
|
||||
return this.HashInternal(raw, salt, length, iterations);
|
||||
}
|
||||
public Task<bool> VerifyPassword(string hash, string password, string salt, int iterations)
|
||||
{
|
||||
this.ValidateVerifyArguments(hash, password, salt, iterations);
|
||||
var hashBytes = Convert.FromBase64String(hash);
|
||||
var saltBytes = Convert.FromBase64String(salt);
|
||||
var passwordBytes = Convert.FromBase64String(password);
|
||||
return this.VerifyPasswordInternal(hashBytes, passwordBytes, saltBytes, iterations);
|
||||
}
|
||||
public Task<bool> VerifyPassword(byte[] hash, byte[] password, byte[] salt, int iterations)
|
||||
{
|
||||
this.ValidateVerifyArguments(hash, password, salt, iterations);
|
||||
return this.VerifyPasswordInternal(hash, password, salt, iterations);
|
||||
}
|
||||
|
||||
private void ValidateHashArguments(object raw, object salt, int length, int iterations)
|
||||
{
|
||||
_ = raw ?? throw new ArgumentNullException(nameof(raw));
|
||||
_ = salt ?? throw new ArgumentNullException(nameof(salt));
|
||||
|
||||
if (iterations < MinimumIterations)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to perform secure hash. Iteration count must be over {MinimumIterations}");
|
||||
}
|
||||
|
||||
public async Task<string> Hash(string raw, string salt, int length, int iterations)
|
||||
if (length < MinimumHashLength)
|
||||
{
|
||||
this.ValidateHashArguments(raw, salt, length, iterations);
|
||||
|
||||
var rawBytes = Convert.FromBase64String(raw);
|
||||
var saltBytes = Convert.FromBase64String(salt);
|
||||
var hashBytes = await this.HashInternal(rawBytes, saltBytes, length, iterations);
|
||||
return Convert.ToBase64String(hashBytes);
|
||||
}
|
||||
public Task<byte[]> Hash(byte[] raw, byte[] salt, int length, int iterations)
|
||||
{
|
||||
this.ValidateHashArguments(raw, salt, length, iterations);
|
||||
|
||||
return this.HashInternal(raw, salt, length, iterations);
|
||||
}
|
||||
public Task<bool> VerifyPassword(string hash, string password, string salt, int iterations)
|
||||
{
|
||||
this.ValidateVerifyArguments(hash, password, salt, iterations);
|
||||
var hashBytes = Convert.FromBase64String(hash);
|
||||
var saltBytes = Convert.FromBase64String(salt);
|
||||
var passwordBytes = Convert.FromBase64String(password);
|
||||
return this.VerifyPasswordInternal(hashBytes, passwordBytes, saltBytes, iterations);
|
||||
}
|
||||
public Task<bool> VerifyPassword(byte[] hash, byte[] password, byte[] salt, int iterations)
|
||||
{
|
||||
this.ValidateVerifyArguments(hash, password, salt, iterations);
|
||||
return this.VerifyPasswordInternal(hash, password, salt, iterations);
|
||||
}
|
||||
|
||||
private void ValidateHashArguments(object raw, object salt, int length, int iterations)
|
||||
{
|
||||
_ = raw ?? throw new ArgumentNullException(nameof(raw));
|
||||
_ = salt ?? throw new ArgumentNullException(nameof(salt));
|
||||
|
||||
if (iterations < MinimumIterations)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to perform secure hash. Iteration count must be over {MinimumIterations}");
|
||||
}
|
||||
|
||||
if (length < MinimumHashLength)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to perform secure hash. Hash length must be over {MinimumHashLength}");
|
||||
}
|
||||
}
|
||||
private void ValidateVerifyArguments(object hash, object password, object salt, int iterations)
|
||||
{
|
||||
_ = hash ?? throw new ArgumentNullException(nameof(hash));
|
||||
_ = salt ?? throw new ArgumentNullException(nameof(salt));
|
||||
_ = password ?? throw new ArgumentNullException(nameof(password));
|
||||
|
||||
if (iterations < MinimumIterations)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to verify hash. Iteration count must be over {MinimumIterations}");
|
||||
}
|
||||
}
|
||||
private Task<byte[]> HashInternal(byte[] raw, byte[] salt, int length, int iterations)
|
||||
{
|
||||
using var pbkdf2 = new Rfc2898DeriveBytes(raw, salt, iterations);
|
||||
var hash = pbkdf2.GetBytes(length);
|
||||
return Task.FromResult(hash);
|
||||
}
|
||||
private Task<bool> VerifyPasswordInternal(byte[] hash, byte[] password, byte[] salt, int iterations)
|
||||
{
|
||||
using var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations);
|
||||
var hashToVerify = pbkdf2.GetBytes(hash.Length);
|
||||
var lengthToVerify = Math.Max(hash.Length, hashToVerify.Length);
|
||||
var match = true;
|
||||
if (lengthToVerify <= 0)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
for(var i = 0; i < lengthToVerify; i++)
|
||||
{
|
||||
if (i < hash.Length && i < hashToVerify.Length)
|
||||
{
|
||||
if (hashToVerify[i].Equals(hash[i]) is false)
|
||||
{
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(match && hash.Length.Equals(hashToVerify.Length));
|
||||
throw new InvalidOperationException($"Unable to perform secure hash. Hash length must be over {MinimumHashLength}");
|
||||
}
|
||||
}
|
||||
private void ValidateVerifyArguments(object hash, object password, object salt, int iterations)
|
||||
{
|
||||
_ = hash ?? throw new ArgumentNullException(nameof(hash));
|
||||
_ = salt ?? throw new ArgumentNullException(nameof(salt));
|
||||
_ = password ?? throw new ArgumentNullException(nameof(password));
|
||||
|
||||
if (iterations < MinimumIterations)
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to verify hash. Iteration count must be over {MinimumIterations}");
|
||||
}
|
||||
}
|
||||
private Task<byte[]> HashInternal(byte[] raw, byte[] salt, int length, int iterations)
|
||||
{
|
||||
using var pbkdf2 = new Rfc2898DeriveBytes(raw, salt, iterations);
|
||||
var hash = pbkdf2.GetBytes(length);
|
||||
return Task.FromResult(hash);
|
||||
}
|
||||
private Task<bool> VerifyPasswordInternal(byte[] hash, byte[] password, byte[] salt, int iterations)
|
||||
{
|
||||
using var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations);
|
||||
var hashToVerify = pbkdf2.GetBytes(hash.Length);
|
||||
var lengthToVerify = Math.Max(hash.Length, hashToVerify.Length);
|
||||
var match = true;
|
||||
if (lengthToVerify <= 0)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
for(var i = 0; i < lengthToVerify; i++)
|
||||
{
|
||||
if (i < hash.Length && i < hashToVerify.Length)
|
||||
{
|
||||
if (hashToVerify[i].Equals(hash[i]) is false)
|
||||
{
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(match && hash.Length.Equals(hashToVerify.Length));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,61 +2,60 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Hashing
|
||||
namespace System.Security.Hashing;
|
||||
|
||||
public sealed class Sha256HashingService : IHashingService
|
||||
{
|
||||
public sealed class Sha256HashingService : IHashingService
|
||||
public async Task<string> Hash(string raw)
|
||||
{
|
||||
public async Task<string> Hash(string raw)
|
||||
using var rawStream = BytesToStream(StringToBytes(raw));
|
||||
using var hashedStream = await HashInternal(rawStream).ConfigureAwait(false);
|
||||
return StreamToString(hashedStream);
|
||||
}
|
||||
public async Task<byte[]> Hash(byte[] raw)
|
||||
{
|
||||
using var rawStream = BytesToStream(raw);
|
||||
using var hashedStream = await HashInternal(rawStream).ConfigureAwait(false);
|
||||
return StreamToBytes(hashedStream);
|
||||
}
|
||||
public async Task<Stream> Hash(Stream raw)
|
||||
{
|
||||
return await HashInternal(raw);
|
||||
}
|
||||
|
||||
private static byte[] StreamToBytes(Stream value)
|
||||
{
|
||||
value.Position = 0;
|
||||
var buffer = new byte[1024];
|
||||
using var ms = new MemoryStream();
|
||||
var read = -1;
|
||||
do
|
||||
{
|
||||
using var rawStream = BytesToStream(StringToBytes(raw));
|
||||
using var hashedStream = await HashInternal(rawStream).ConfigureAwait(false);
|
||||
return StreamToString(hashedStream);
|
||||
}
|
||||
public async Task<byte[]> Hash(byte[] raw)
|
||||
read = value.Read(buffer, 0, buffer.Length);
|
||||
ms.Write(buffer, 0, read);
|
||||
} while (read > 0);
|
||||
return ms.ToArray();
|
||||
}
|
||||
private static string StreamToString(Stream value)
|
||||
{
|
||||
return Convert.ToBase64String(StreamToBytes(value));
|
||||
}
|
||||
private static byte[] StringToBytes(string value)
|
||||
{
|
||||
return Convert.FromBase64String(value);
|
||||
}
|
||||
private static Stream BytesToStream(byte[] value)
|
||||
{
|
||||
return new MemoryStream(value);
|
||||
}
|
||||
private static async Task<Stream> HashInternal(Stream raw)
|
||||
{
|
||||
if (raw is null)
|
||||
{
|
||||
using var rawStream = BytesToStream(raw);
|
||||
using var hashedStream = await HashInternal(rawStream).ConfigureAwait(false);
|
||||
return StreamToBytes(hashedStream);
|
||||
}
|
||||
public async Task<Stream> Hash(Stream raw)
|
||||
{
|
||||
return await HashInternal(raw);
|
||||
throw new ArgumentNullException(nameof(raw));
|
||||
}
|
||||
|
||||
private static byte[] StreamToBytes(Stream value)
|
||||
{
|
||||
value.Position = 0;
|
||||
var buffer = new byte[1024];
|
||||
using var ms = new MemoryStream();
|
||||
var read = -1;
|
||||
do
|
||||
{
|
||||
read = value.Read(buffer, 0, buffer.Length);
|
||||
ms.Write(buffer, 0, read);
|
||||
} while (read > 0);
|
||||
return ms.ToArray();
|
||||
}
|
||||
private static string StreamToString(Stream value)
|
||||
{
|
||||
return Convert.ToBase64String(StreamToBytes(value));
|
||||
}
|
||||
private static byte[] StringToBytes(string value)
|
||||
{
|
||||
return Convert.FromBase64String(value);
|
||||
}
|
||||
private static Stream BytesToStream(byte[] value)
|
||||
{
|
||||
return new MemoryStream(value);
|
||||
}
|
||||
private static async Task<Stream> HashInternal(Stream raw)
|
||||
{
|
||||
if (raw is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(raw));
|
||||
}
|
||||
|
||||
using var sha256 = SHA256.Create();
|
||||
return await Task.Run(() => new MemoryStream(sha256.ComputeHash(raw)));
|
||||
}
|
||||
using var sha256 = SHA256.Create();
|
||||
return await Task.Run(() => new MemoryStream(sha256.ComputeHash(raw)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,58 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace System.Security.Rng
|
||||
namespace System.Security.Rng;
|
||||
|
||||
public sealed class CryptoRngProvider : ICryptoRngProvider, IDisposable
|
||||
{
|
||||
public sealed class CryptoRngProvider : ICryptoRngProvider, IDisposable
|
||||
private readonly RNGCryptoServiceProvider rngProvider;
|
||||
private bool disposedValue;
|
||||
|
||||
public CryptoRngProvider()
|
||||
{
|
||||
private readonly RNGCryptoServiceProvider rngProvider;
|
||||
private bool disposedValue;
|
||||
|
||||
public CryptoRngProvider()
|
||||
{
|
||||
this.rngProvider = new RNGCryptoServiceProvider();
|
||||
}
|
||||
public CryptoRngProvider(CspParameters cspParams)
|
||||
{
|
||||
this.rngProvider = new RNGCryptoServiceProvider(cspParams);
|
||||
}
|
||||
this.rngProvider = new RNGCryptoServiceProvider();
|
||||
}
|
||||
public CryptoRngProvider(CspParameters cspParams)
|
||||
{
|
||||
this.rngProvider = new RNGCryptoServiceProvider(cspParams);
|
||||
}
|
||||
|
||||
|
||||
public void GetBytes(byte[] data)
|
||||
{
|
||||
this.rngProvider.GetBytes(data);
|
||||
}
|
||||
public void GetNonZeroBytes(byte[] data)
|
||||
{
|
||||
this.rngProvider.GetNonZeroBytes(data);
|
||||
}
|
||||
public byte[] GetBytes(int byteCount)
|
||||
{
|
||||
var bytes = new byte[byteCount];
|
||||
this.GetBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
public byte[] GetNonZeroBytes(int byteCount)
|
||||
{
|
||||
var bytes = new byte[byteCount];
|
||||
this.GetNonZeroBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
public void GetBytes(byte[] data)
|
||||
{
|
||||
this.rngProvider.GetBytes(data);
|
||||
}
|
||||
public void GetNonZeroBytes(byte[] data)
|
||||
{
|
||||
this.rngProvider.GetNonZeroBytes(data);
|
||||
}
|
||||
public byte[] GetBytes(int byteCount)
|
||||
{
|
||||
var bytes = new byte[byteCount];
|
||||
this.GetBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
public byte[] GetNonZeroBytes(int byteCount)
|
||||
{
|
||||
var bytes = new byte[byteCount];
|
||||
this.GetNonZeroBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.disposedValue)
|
||||
{
|
||||
if (!this.disposedValue)
|
||||
if (disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
this.rngProvider.Dispose();
|
||||
}
|
||||
|
||||
this.disposedValue = true;
|
||||
this.rngProvider.Dispose();
|
||||
}
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
this.disposedValue = true;
|
||||
}
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
namespace System.Security.Rng
|
||||
namespace System.Security.Rng;
|
||||
|
||||
public interface ICryptoRngProvider
|
||||
{
|
||||
public interface ICryptoRngProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Populate provided array of bytes with cryptographically secure random bytes.
|
||||
/// </summary>
|
||||
/// <param name="data">Array of bytes to be populated.</param>
|
||||
public void GetBytes(byte[] data);
|
||||
/// <summary>
|
||||
/// Return an array of cryptographically secure random bytes.
|
||||
/// </summary>
|
||||
/// <param name="byteCount">Length of the returned array.</param>
|
||||
/// <returns>Array containing cryptographically secure random values.</returns>
|
||||
public byte[] GetBytes(int byteCount);
|
||||
/// <summary>
|
||||
/// Populate provided array of bytes with cryptographically secure random non-zero bytes.
|
||||
/// </summary>
|
||||
/// <param name="data">Array of bytes to be populated.</param>
|
||||
public void GetNonZeroBytes(byte[] data);
|
||||
/// <summary>
|
||||
/// Return an array of cryptographically secure random non-zero bytes.
|
||||
/// </summary>
|
||||
/// <param name="byteCount">Length of the returned array.</param>
|
||||
/// <returns>Array containing cryptographically secure random non-zero values.</returns>
|
||||
public byte[] GetNonZeroBytes(int byteCount);
|
||||
}
|
||||
/// <summary>
|
||||
/// Populate provided array of bytes with cryptographically secure random bytes.
|
||||
/// </summary>
|
||||
/// <param name="data">Array of bytes to be populated.</param>
|
||||
public void GetBytes(byte[] data);
|
||||
/// <summary>
|
||||
/// Return an array of cryptographically secure random bytes.
|
||||
/// </summary>
|
||||
/// <param name="byteCount">Length of the returned array.</param>
|
||||
/// <returns>Array containing cryptographically secure random values.</returns>
|
||||
public byte[] GetBytes(int byteCount);
|
||||
/// <summary>
|
||||
/// Populate provided array of bytes with cryptographically secure random non-zero bytes.
|
||||
/// </summary>
|
||||
/// <param name="data">Array of bytes to be populated.</param>
|
||||
public void GetNonZeroBytes(byte[] data);
|
||||
/// <summary>
|
||||
/// Return an array of cryptographically secure random non-zero bytes.
|
||||
/// </summary>
|
||||
/// <param name="byteCount">Length of the returned array.</param>
|
||||
/// <returns>Array containing cryptographically secure random non-zero values.</returns>
|
||||
public byte[] GetNonZeroBytes(int byteCount);
|
||||
}
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace System.Security.Utilities
|
||||
namespace System.Security.Utilities;
|
||||
|
||||
internal sealed class NotClosingCryptoStream : CryptoStream
|
||||
{
|
||||
internal sealed class NotClosingCryptoStream : CryptoStream
|
||||
public NotClosingCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
|
||||
: base(stream, transform, mode)
|
||||
{
|
||||
public NotClosingCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
|
||||
: base(stream, transform, mode)
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.HasFlushedFinalBlock)
|
||||
{
|
||||
this.FlushFinalBlock();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.HasFlushedFinalBlock)
|
||||
{
|
||||
this.FlushFinalBlock();
|
||||
}
|
||||
|
||||
base.Dispose(false);
|
||||
}
|
||||
base.Dispose(false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user