diff --git a/.gitignore b/.gitignore index b3a6883..daedc2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,487 +1,49 @@ -### VisualStudioCode template -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -!.vscode/*.code-snippets - -# Local History for Visual Studio Code -.history/ - -# Built Visual Studio Code Extensions -*.vsix - -### JetBrains template -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### VisualStudio template -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch +# Build artifacts +bin/ +obj/ +*.dll +*.exe *.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.tlog -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages +*.so +*.dylib *.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat +# Dependencies +packages/ node_modules/ +vendor/ -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio 6 auto-generated project file (contains which files were open etc.) -*.vbp - -# Visual Studio 6 workspace and project file (working project files containing files to include in project) -*.dsw -*.dsp - -# Visual Studio 6 technical files - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# Visual Studio History (VSHistory) files -.vshistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# Fody - auto-generated XML schema -FodyWeavers.xsd +# Logs +*.log -# VS Code files for those working on multiple tools -*.code-workspace +# Environment +.env +.env.local +.env.* -# Local History for Visual Studio Code +# Editors +.vscode/ +.idea/ +*.swp +*.swo -# Windows Installer files from build outputs -*.cab -*.msi -*.msix -*.msm -*.msp +# OS generated files +.DS_Store +Thumbs.db -# JetBrains Rider -*.sln.iml +# Test and coverage +coverage/ +htmlcov/ +*.coverage -# Custom -**/.idea/ +# Temporary files +*.tmp +*.temp +*.bak + +# Output directories typically used in .NET projects +Debug/ +Release/ +Build/ +Dist/ +Output/ \ No newline at end of file diff --git a/src/nHash.Application/Cryptos/Hashes/Algorithms/Argon2idHash.cs b/src/nHash.Application/Cryptos/Hashes/Algorithms/Argon2idHash.cs index 59ea6d8..107762b 100644 --- a/src/nHash.Application/Cryptos/Hashes/Algorithms/Argon2idHash.cs +++ b/src/nHash.Application/Cryptos/Hashes/Algorithms/Argon2idHash.cs @@ -1,93 +1,91 @@ -using System.Security.Cryptography; -using Blake2Fast; +using Isopoh.Cryptography.Argon2; namespace nHash.Application.Hashes.Algorithms; public class Argon2idHash : IHash { - private static readonly byte[] DefaultSalt = "nHashSalt1234567"u8.ToArray(); + private readonly int _memoryKb; + private readonly int _iterations; + private readonly int _parallelism; + private readonly int _hashLength; - public byte[] ComputeHash(byte[] buffer) + public Argon2idHash(int memoryKb = 65536, int iterations = 3, int parallelism = 4, int hashLength = 32) { - uint lanes = 1; - uint memoryKb = 64; - uint iterations = 2; - uint tagLength = 32; + _memoryKb = memoryKb; + _iterations = iterations; + _parallelism = parallelism; + _hashLength = hashLength; + } - uint blockCount = memoryKb; - var blocks = new ulong[blockCount][]; - for (int i = 0; i < blockCount; i++) + public byte[] ComputeHash(byte[] buffer) + { + var salt = new byte[16]; + using (var rng = System.Security.Cryptography.RandomNumberGenerator.Create()) { - blocks[i] = new ulong[128]; + rng.GetBytes(salt); } - - var hasher = Blake2b.CreateIncrementalHasher(64); - hasher.Update(BitConverter.GetBytes(lanes)); - hasher.Update(BitConverter.GetBytes(tagLength)); - hasher.Update(BitConverter.GetBytes(memoryKb)); - hasher.Update(BitConverter.GetBytes(iterations)); - hasher.Update(buffer); - hasher.Update(DefaultSalt); - var h0 = hasher.Finish(); - for (uint i = 0; i < 2; i++) + var config = new Argon2Config { - var temp = new byte[1024]; - var blockHasher = Blake2b.CreateIncrementalHasher(64); - blockHasher.Update(h0); - blockHasher.Update(BitConverter.GetBytes(i)); - blockHasher.Update(BitConverter.GetBytes((uint)0)); - var hash = blockHasher.Finish(); - - for (int offset = 0; offset < 1024; offset += 64) - { - Array.Copy(hash, 0, temp, offset, 64); - hash = Blake2b.ComputeHash(64, hash); - } - - for (int j = 0; j < 128; j++) - { - blocks[i][j] = BitConverter.ToUInt64(temp, j * 8); - } - } + Type = Argon2Type.DataIndependentAddressing, + Version = Argon2Version.Nineteen, + Password = buffer, + Salt = salt, + Threads = _parallelism, + Iterations = _iterations, + Memory = _memoryKb, + HashLength = _hashLength + }; + + var hash = Argon2.Hash(config); + + var result = new byte[salt.Length + hash.Length]; + Array.Copy(salt, 0, result, 0, salt.Length); + Array.Copy(hash, 0, result, salt.Length, hash.Length); + + return result; + } - for (uint i = 2; i < blockCount; i++) + public bool VerifyHash(byte[] buffer, byte[] storedHashWithSalt) + { + if (storedHashWithSalt.Length < 16) { - uint refBlock = (i - 1) % i; - MixBlocks(blocks[i - 1], blocks[refBlock], blocks[i]); + return false; } - var finalBlock = blocks[blockCount - 1]; - var finalBytes = new byte[1024]; - for (int j = 0; j < 128; j++) + var salt = new byte[16]; + Array.Copy(storedHashWithSalt, 0, salt, 0, 16); + + var expectedHash = new byte[storedHashWithSalt.Length - 16]; + Array.Copy(storedHashWithSalt, 16, expectedHash, 0, expectedHash.Length); + + var config = new Argon2Config { - Array.Copy(BitConverter.GetBytes(finalBlock[j]), 0, finalBytes, j * 8, 8); - } + Type = Argon2Type.DataIndependentAddressing, + Version = Argon2Version.Nineteen, + Password = buffer, + Salt = salt, + Threads = _parallelism, + Iterations = _iterations, + Memory = _memoryKb, + HashLength = expectedHash.Length + }; - var result = Blake2b.ComputeHash((int)tagLength, finalBytes); - return result; - } + var computedHash = Argon2.Hash(config); - private static void MixBlocks(ulong[] prev, ulong[] refBlock, ulong[] next) - { - for (int j = 0; j < 128; j++) + if (computedHash.Length != expectedHash.Length) { - next[j] = prev[j] ^ refBlock[j]; + return false; } - for (int i = 0; i < 8; i++) + + for (int i = 0; i < computedHash.Length; i++) { - MixRound(next, i * 16); + if (computedHash[i] != expectedHash[i]) + { + return false; + } } - } - private static void MixRound(ulong[] state, int offset) - { - state[offset + 0] += state[offset + 4]; - state[offset + 12] ^= state[offset + 0]; - state[offset + 12] = (state[offset + 12] << 32) | (state[offset + 12] >> 32); - - state[offset + 8] += state[offset + 12]; - state[offset + 4] ^= state[offset + 8]; - state[offset + 4] = (state[offset + 4] << 24) | (state[offset + 4] >> 40); + return true; } } diff --git a/src/nHash.Application/Texts/Counter/TextCounterService.cs b/src/nHash.Application/Texts/Counter/TextCounterService.cs index ffe1395..41c5a61 100644 --- a/src/nHash.Application/Texts/Counter/TextCounterService.cs +++ b/src/nHash.Application/Texts/Counter/TextCounterService.cs @@ -7,15 +7,12 @@ public static int WordCount(string text) int wordCount = 0; bool isWord = false; - // Iterate through each character in the string foreach (char c in text) { - // If the character is a letter, set isWord to true if (char.IsLetter(c)) { isWord = true; } - // If the character is not a letter and isWord is true, increment the word count else if (isWord) { wordCount++; @@ -23,7 +20,6 @@ public static int WordCount(string text) } } - // If the last character was a letter, increment the word count if (isWord) { wordCount++; @@ -31,13 +27,11 @@ public static int WordCount(string text) return wordCount; } - - public static void CountCharactersWordsSentences(string text) + + public static (int Characters, int Words, int Sentences) CountCharactersWordsSentences(string text) { - // Count number of characters var characterCount = text.Length; - - // Count number of words + var wordCount = 0; var isWord = false; foreach (var c in text) @@ -59,8 +53,7 @@ public static void CountCharactersWordsSentences(string text) { wordCount++; } - - // Count number of sentences + var sentenceCount = 0; foreach (var c in text) { @@ -69,10 +62,7 @@ public static void CountCharactersWordsSentences(string text) sentenceCount++; } } - - // Output results - Console.WriteLine("Character count: {0}", characterCount); - Console.WriteLine("Word count: {0}", wordCount); - Console.WriteLine("Sentence count: {0}", sentenceCount); + + return (characterCount, wordCount, sentenceCount); } -} \ No newline at end of file +} diff --git a/src/nHash.Application/nHash.Application.csproj b/src/nHash.Application/nHash.Application.csproj index d2438eb..82f7512 100644 --- a/src/nHash.Application/nHash.Application.csproj +++ b/src/nHash.Application/nHash.Application.csproj @@ -7,8 +7,8 @@ - + diff --git a/src/nHash.Infrastructure/FileProvider.cs b/src/nHash.Infrastructure/FileProvider.cs index 02212e6..57f30c4 100644 --- a/src/nHash.Infrastructure/FileProvider.cs +++ b/src/nHash.Infrastructure/FileProvider.cs @@ -2,79 +2,94 @@ namespace nHash.Infrastructure; public class FileProvider : IFileProvider { + private readonly ILogger? _logger; + + public FileProvider(ILogger? logger = null) + { + _logger = logger; + } + public Task ReadAsText(string fileName) { if (!File.Exists(fileName)) { - Console.WriteLine($"File {fileName} does not exists!"); - return Task.FromResult(string.Empty); + var message = $"File {fileName} does not exist!"; + _logger?.LogError(message); + throw new FileNotFoundException(message, fileName); } try { return File.ReadAllTextAsync(fileName); } - catch + catch (Exception ex) { - Console.WriteLine("Error reading from '{0}'", fileName); + var message = $"Error reading from '{fileName}': {ex.Message}"; + _logger?.LogError(ex, message); + throw; } - return Task.FromResult(string.Empty); } public Task ReadAsByte(string fileName) { if (!File.Exists(fileName)) { - Console.WriteLine($"File {fileName} does not exists!"); - return Task.FromResult(Array.Empty()); + var message = $"File {fileName} does not exist!"; + _logger?.LogError(message); + throw new FileNotFoundException(message, fileName); } try { return File.ReadAllBytesAsync(fileName); } - catch + catch (Exception ex) { - Console.WriteLine("Error reading from '{0}'", fileName); + var message = $"Error reading from '{fileName}': {ex.Message}"; + _logger?.LogError(ex, message); + throw; } - return Task.FromResult(Array.Empty()); } public Task Write(string fileName, string text) { if (string.IsNullOrWhiteSpace(fileName)) { - Console.WriteLine(text); - return Task.CompletedTask; + var message = "File name cannot be empty or whitespace."; + _logger?.LogError(message); + throw new ArgumentException(message, nameof(fileName)); } try { return File.WriteAllTextAsync(fileName, text); } - catch + catch (Exception ex) { - Console.WriteLine("Error writing output to '{0}'", fileName); + var message = $"Error writing output to '{fileName}': {ex.Message}"; + _logger?.LogError(ex, message); + throw; } - return Task.CompletedTask; } public Task Write(byte[] content, string fileName) { if (string.IsNullOrWhiteSpace(fileName)) { - Console.WriteLine(content); - return Task.CompletedTask; + var message = "File name cannot be empty or whitespace."; + _logger?.LogError(message); + throw new ArgumentException(message, nameof(fileName)); } try { return File.WriteAllBytesAsync(fileName, content); } - catch + catch (Exception ex) { - Console.WriteLine("Error writing output to '{0}'", fileName); + var message = $"Error writing output to '{fileName}': {ex.Message}"; + _logger?.LogError(ex, message); + throw; } - return Task.CompletedTask; } } \ No newline at end of file