SpectraUtils 3.0.0

dotnet add package SpectraUtils --version 3.0.0
                    
NuGet\Install-Package SpectraUtils -Version 3.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SpectraUtils" Version="3.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SpectraUtils" Version="3.0.0" />
                    
Directory.Packages.props
<PackageReference Include="SpectraUtils" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SpectraUtils --version 3.0.0
                    
#r "nuget: SpectraUtils, 3.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SpectraUtils@3.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SpectraUtils&version=3.0.0
                    
Install as a Cake Addin
#tool nuget:?package=SpectraUtils&version=3.0.0
                    
Install as a Cake Tool

SpectraUtils

CI NuGet License: MIT .NET 8 | 10

SpectraUtils is a small, dependency-light utility library for .NET with a focus on Turkish applications: identity / tax number / IBAN validation, Turkish-aware name formatting, PBKDF2 password hashing and secure random generators.

Package What's inside
SpectraUtils Validators, validation attributes, name formatting, password hashing, token / OTP / password generation, LINQ & string extensions. No ASP.NET Core dependency.
SpectraUtils.AspNetCore AllowedExtensionsAttribute for IFormFile / IFormFileCollection uploads.

Upgrading from 2.x? Version 3.0 contains important bug fixes and breaking changes. See the migration guide.


Installation

dotnet add package SpectraUtils
dotnet add package SpectraUtils.AspNetCore   # only if you validate file uploads

Supported frameworks: .NET 8 and .NET 10 (and later).

Quick start

using SpectraUtils.Extensions;

builder.Services.AddSpectraUtils();

// or with options
builder.Services.AddSpectraUtils(options =>
{
    options.Pbkdf2.Iterations = 700_000;
    options.NameCulture = CultureInfo.InvariantCulture; // default: Turkish casing
});

All services are stateless and registered as singletons with TryAdd, so your own registrations win.

Service Default implementation
IPasswordHasher Pbkdf2PasswordHasher
IPasswordHelper PasswordHelper
ISecureTokenGenerator SecureTokenGenerator
IOneTimeCodeGenerator OneTimeCodeGenerator
INameEdit NameEdit
ISpectraUtil SpectraUtil (facade over all of the above)

Not using DI? Every service has a public parameterless constructor, e.g. new Pbkdf2PasswordHasher(), or use the facade: var utils = new SpectraUtil();.

Namespaces: SpectraUtils.Abstractions (interfaces), SpectraUtils.Services (implementations), SpectraUtils.Validation (static validators), SpectraUtils.Attributes.ValidationAttributes, SpectraUtils.Configuration (options), SpectraUtils.Extensions.


Security

Password hashing (PBKDF2)

IPasswordHasher hasher = ...; // injected

string hash = hasher.Hash("UserPassword123!");
// PBKDF2$SHA256$600000$<salt>$<key>

if (hasher.Verify(input, user.PasswordHash))
{
    // Upgrade old hashes (e.g. created with fewer iterations) transparently.
    if (hasher.NeedsRehash(user.PasswordHash))
        user.PasswordHash = hasher.Hash(input);
}
  • Defaults follow OWASP: PBKDF2-HMAC-SHA256, 600,000 iterations, 16-byte salt, 32-byte key. SHA-384 and SHA-512 are available through Pbkdf2Options.Algorithm.
  • Every hash stores its own parameters, so changing the options never breaks existing hashes. Hashes created by SpectraUtils 2.x are still verified.
  • Comparison is constant-time. A malformed hash returns false instead of throwing, and tampered hashes with absurd iteration counts are rejected (Pbkdf2Options.MaxIterations).

Tokens, one-time codes and passwords

string token = tokenGenerator.GenerateToken();            // 32 random bytes, Base64Url (43 chars)
string resetToken = tokenGenerator.GenerateToken(64);

string otp = otpGenerator.GenerateNumericCode();          // "048213" (6 digits, uniformly random)
string longOtp = otpGenerator.GenerateNumericCode(10);    // up to 32 digits

string password = passwordHelper.CreateStandardPassword(); // 12 chars, all character categories
string pin = passwordHelper.CreatePassword(8,
    includeUppercaseLetter: false, includeLowercaseLetter: false,
    includeSpecialCharacter: false, includeNumber: true);

Everything uses System.Security.Cryptography.RandomNumberGenerator without modulo bias. CreatePassword guarantees at least one character from every selected category.

Treat OTPs as short-lived secrets: expire them after a few minutes, limit attempts, and compare them in constant time.


Validation

[TCIDValidation] makes the value mandatory: null, empty or whitespace is invalid. The other attributes treat null as valid, so add [Required] when those values are mandatory. Error messages support {0} for the display name and work with ErrorMessageResourceType for localization.

using SpectraUtils.Attributes.ValidationAttributes;

public class RegisterRequest
{
    [TCIDValidation]                                   // null/empty is invalid too
    public string? IdentityNumber { get; set; }        // "10000000146"

    [TurkishTaxNumberValidation]
    public string? TaxNumber { get; set; }             // 10-digit VKN

    [IbanValidation("TR")]
    public string? Iban { get; set; }                  // "TR33 0006 1005 1978 6457 8413 26"

    [MinimumAge(18, ErrorMessage = "{0}: en az {1} yaşında olmalısınız.")]
    public DateOnly? BirthDate { get; set; }           // DateOnly, DateTime or DateTimeOffset
}
Attribute Notes
TCIDValidationAttribute Turkish identity number (TCKN), both check digits. Mandatory: null / empty is invalid. Whitespace is ignored.
TurkishTaxNumberValidationAttribute Turkish tax number (VKN) check digit. Whitespace is ignored.
IbanValidationAttribute ISO 13616 / MOD-97, country-specific length (e.g. TR = 26). Optional country code.
MinimumAgeAttribute Placeholders {0} (name) and {1} (age). "Today" comes from the registered TimeProvider, so it is testable.
AllowedExtensionsAttribute In SpectraUtils.AspNetCore. See below.

Programmatic validators

using SpectraUtils.Validation;

bool tckn = TurkishIdentityNumberValidator.IsValid("10000000146");
bool vkn  = TurkishTaxNumberValidator.IsValid("1739750504");
bool iban = IbanValidator.IsValid("TR33 0006 1005 1978 6457 8413 26", expectedCountryCode: "TR");

Validators never throw: null, empty, malformed or oversized input simply returns false.

File uploads (SpectraUtils.AspNetCore)

public class UploadRequest
{
    [Required]
    [AllowedExtensions(2 * 1024 * 1024, ".jpg", ".png")]       // max 2 MB
    public IFormFile? Avatar { get; set; }

    [AllowedExtensions(10 * 1024 * 1024, ".pdf", ".docx",
        FileSizeErrorMessage = "{0} must be smaller than {2}.")]
    public IFormFileCollection? Documents { get; set; }        // every file is checked
}

Only the file name is checked. If you store or serve uploads, also verify the content (magic bytes).


Name formatting

INameEdit names = ...; // injected

names.NameCorrection("  aYşe   nur ");               // "Ayşe Nur"
names.NameCorrection("ismail");                      // "İsmail"  (Turkish casing by default)
names.NameCorrection("mehmet", "ali");               // "Mehmet Ali"
names.SurnameCorrection("yılmaz");                   // "YILMAZ"
names.FullNameCorrection("oğuzhan", "karagüzel");    // "Oğuzhan KARAGÜZEL"
names.StandardizeCharacters("Çağdaş Işık Crème");    // "Cagdas Isik Creme"
names.CreateUserName("Ayşe Nur");                    // "aysenur0427"
  • Casing uses Turkish rules (i ↔ İ, ı ↔ I) by default; pass another culture with new NameEdit(CultureInfo.InvariantCulture) or options.NameCulture.
  • Works in globalization-invariant mode (e.g. small Docker images) as well.
  • Passing null returns null; the return types are annotated for nullable reference types.

Extensions

using SpectraUtils.Extensions;

if (!name.IsNullOrWhiteSpace()) { /* name is not null here */ }

"a😀b".ReverseSafe();                                 // "b😀a" (emoji and accents stay intact)

query.WhereIf(filter.OnlyActive, x => x.IsActive);   // IEnumerable and IQueryable
items.IsNullOrEmpty();                                // count-aware, IQueryable-aware
items.Tap(x => logger.LogDebug("{Item}", x));         // deferred side effect in a pipeline
items.ForEach(Console.WriteLine);

Development

cd SpectraUtilsPackage/SpectraUtils
dotnet test                       # runs on net8.0 and net10.0
dotnet pack -c Release -o artifacts

Changes are listed in CHANGELOG.md. Contributions are welcome — please open an issue or a pull request.

Security disclosure

If you discover a security vulnerability, please report it privately through GitHub Security Advisories instead of the public issue tracker.

License

MIT © Oğuzhan KARAGÜZEL — oguzhankaraguzel.com

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on SpectraUtils:

Package Downloads
SpectraUtils.AspNetCore

ASP.NET Core add-ons for SpectraUtils: file upload validation (allowed extensions and maximum size) for IFormFile and IFormFileCollection.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0 107 10/10/2026
2.0.0 546 1/3/2026
1.1.0 429 10/14/2023
1.0.4 356 8/15/2023
1.0.3 345 8/15/2023 1.0.3 is deprecated because it has critical bugs.
1.0.0 327 8/11/2023