├── .gitattributes ├── .gitignore ├── .gitmodules ├── .nuget ├── CleanBuildAll.cmd ├── CreateNugetBuild.cmd ├── download-nuget.cmd ├── libsodium-uwp.nuspec └── libsodium-uwp.targets ├── LICENSE ├── README.md ├── Test ├── Assets │ ├── LockScreenLogo.scale-200.png │ ├── SplashScreen.scale-200.png │ ├── Square150x150Logo.scale-200.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── StoreLogo.png │ └── Wide310x150Logo.scale-200.png ├── CoreTest.cs ├── CryptoHashTest.cs ├── GenericHashTest.cs ├── KDFTest.cs ├── OneTimeAuthTest.cs ├── Package.appxmanifest ├── PasswordHashTest.cs ├── Properties │ ├── AssemblyInfo.cs │ └── UnitTestApp.rd.xml ├── PublicKeyAuthTest.cs ├── PublicKeyBoxTest.cs ├── ScalarMultTest.cs ├── SealedPublicKeyBoxTest.cs ├── SecretAeadTest.cs ├── SecretBoxTest.cs ├── SecretKeyAuthTest.cs ├── SecretStream.cs ├── ShortHashTest.cs ├── StreamEncryptionTest.cs ├── Test.csproj ├── Test_TemporaryKey.pfx ├── UnitTestApp.xaml ├── UnitTestApp.xaml.cs ├── UtilitiesTest.cs └── project.json ├── docs ├── Core.md ├── CryptoHash.md ├── GenericHash.md ├── HMAC-SHA2.md ├── KDF.md ├── KeyPair.md ├── OneTimeAuth.md ├── PasswordHash.md ├── PublicKeyAuth.md ├── PublicKeyBox.md ├── README.md ├── ScalarMult.md ├── SealedPublicKeyBox.md ├── SecretAead.md ├── SecretBox.md ├── SecretKeyAuth.md ├── SecretStream.md ├── ShortHash.md ├── StreamEncryption.md └── Utilities.md ├── libsodium-uwp.sln └── libsodium-uwp ├── CryptoHash.cpp ├── CryptoHash.h ├── DetachedBox.h ├── Extern.cpp ├── Extern.h ├── GenericHash.cpp ├── GenericHash.h ├── KDF.cpp ├── KDF.h ├── KeyPair.h ├── OneTimeAuth.cpp ├── OneTimeAuth.h ├── PasswordHash.cpp ├── PasswordHash.h ├── PublicKeyAuth.cpp ├── PublicKeyAuth.h ├── PublicKeyBox.cpp ├── PublicKeyBox.h ├── ScalarMult.cpp ├── ScalarMult.h ├── SealedPublicKeyBox.cpp ├── SealedPublicKeyBox.h ├── SecretAead.cpp ├── SecretAead.h ├── SecretBox.cpp ├── SecretBox.h ├── SecretKeyAuth.cpp ├── SecretKeyAuth.h ├── SecretStream.cpp ├── SecretStream.h ├── ShortHash.cpp ├── ShortHash.h ├── SodiumCore.cpp ├── SodiumCore.h ├── StreamEncryption.cpp ├── StreamEncryption.h ├── Utilities.cpp ├── Utilities.h ├── include └── randombytes_default.h ├── internal.cpp ├── internal.h ├── libsodium-uwp.vcxproj ├── libsodium-uwp.vcxproj.filters ├── pch.cpp ├── pch.h └── randombytes_default.c /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | pingme.txt 28 | 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # DNX 46 | project.lock.json 47 | artifacts/ 48 | 49 | *_i.c 50 | *_p.c 51 | *_i.h 52 | *.ilk 53 | *.meta 54 | *.obj 55 | *.pch 56 | *.pdb 57 | *.pgc 58 | *.pgd 59 | *.rsp 60 | *.sbr 61 | *.tlb 62 | *.tli 63 | *.tlh 64 | *.tmp 65 | *.tmp_proj 66 | *.log 67 | *.vspscc 68 | *.vssscc 69 | .builds 70 | *.pidb 71 | *.svclog 72 | *.scc 73 | 74 | # Chutzpah Test files 75 | _Chutzpah* 76 | 77 | # Visual C++ cache files 78 | ipch/ 79 | *.aps 80 | *.ncb 81 | *.opendb 82 | *.opensdf 83 | *.sdf 84 | *.cachefile 85 | *.VC.db 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | 145 | # TODO: Un-comment the next line if you do not want to checkin 146 | # your web deploy settings because they may include unencrypted 147 | # passwords 148 | #*.pubxml 149 | *.publishproj 150 | 151 | # NuGet Packages 152 | *.nupkg 153 | *.nupkg.asc 154 | # The packages folder can be ignored because of Package Restore 155 | **/packages/* 156 | # except build/, which is used as an MSBuild target. 157 | !**/packages/build/ 158 | # Uncomment if necessary however generally it will be regenerated when needed 159 | #!**/packages/repositories.config 160 | # NuGet v3's project.json files produces more ignoreable files 161 | *.nuget.props 162 | *.nuget.targets 163 | nuget.exe 164 | # Microsoft Azure Build Output 165 | csx/ 166 | *.build.csdef 167 | 168 | # Microsoft Azure Emulator 169 | ecf/ 170 | rcf/ 171 | 172 | # Microsoft Azure ApplicationInsights config file 173 | ApplicationInsights.config 174 | 175 | # Windows Store app package directory 176 | AppPackages/ 177 | BundleArtifacts/ 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | [Ss]tyle[Cc]op.* 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.pfx 193 | *.publishsettings 194 | node_modules/ 195 | orleans.codegen.cs 196 | 197 | # RIA/Silverlight projects 198 | Generated_Code/ 199 | 200 | # Backup & report files from converting an old project file 201 | # to a newer Visual Studio version. Backup files are not needed, 202 | # because we have git ;-) 203 | _UpgradeReport_Files/ 204 | Backup*/ 205 | UpgradeLog*.XML 206 | UpgradeLog*.htm 207 | 208 | # SQL Server files 209 | *.mdf 210 | *.ldf 211 | 212 | # Business Intelligence projects 213 | *.rdl.data 214 | *.bim.layout 215 | *.bim_*.settings 216 | 217 | # Microsoft Fakes 218 | FakesAssemblies/ 219 | 220 | # GhostDoc plugin setting file 221 | *.GhostDoc.xml 222 | 223 | # Node.js Tools for Visual Studio 224 | .ntvs_analysis.dat 225 | 226 | # Visual Studio 6 build log 227 | *.plg 228 | 229 | # Visual Studio 6 workspace options file 230 | *.opt 231 | 232 | # Visual Studio LightSwitch build output 233 | **/*.HTMLClient/GeneratedArtifacts 234 | **/*.DesktopClient/GeneratedArtifacts 235 | **/*.DesktopClient/ModelManifest.xml 236 | **/*.Server/GeneratedArtifacts 237 | **/*.Server/ModelManifest.xml 238 | _Pvt_Extensions 239 | 240 | # LightSwitch generated files 241 | GeneratedArtifacts/ 242 | ModelManifest.xml 243 | 244 | # Paket dependency manager 245 | .paket/paket.exe 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libsodium-uwp/libsodium"] 2 | path = libsodium-uwp/libsodium 3 | url = https://github.com/jedisct1/libsodium 4 | -------------------------------------------------------------------------------- /.nuget/CleanBuildAll.cmd: -------------------------------------------------------------------------------- 1 | msbuild ../libsodium-uwp.sln /t:Clean /p:Platform=ARM /p:Configuration=Debug 2 | msbuild ../libsodium-uwp.sln /t:Clean /p:Platform=ARM /p:Configuration=Release 3 | msbuild ../libsodium-uwp.sln /t:Clean /p:Platform=x86 /p:Configuration=Debug 4 | msbuild ../libsodium-uwp.sln /t:Clean /p:Platform=x86 /p:Configuration=Release 5 | msbuild ../libsodium-uwp.sln /t:Clean /p:Platform=x64 /p:Configuration=Debug 6 | msbuild ../libsodium-uwp.sln /t:Clean /p:Platform=x64 /p:Configuration=Release 7 | msbuild ../libsodium-uwp.sln /t:Build /p:Platform=ARM /p:Configuration=Debug /m /verbosity:minimal /p:OutputPath=../build/Debug/ARM 8 | msbuild ../libsodium-uwp.sln /t:Build /p:Platform=ARM /p:Configuration=Release /m /verbosity:minimal /p:OutputPath=../build/Release/ARM 9 | msbuild ../libsodium-uwp.sln /t:Build /p:Platform=x86 /p:Configuration=Debug /m /verbosity:minimal /p:OutputPath=../build/Debug/x86 10 | msbuild ../libsodium-uwp.sln /t:Build /p:Platform=x86 /p:Configuration=Release /m /verbosity:minimal /p:OutputPath=../build/Release/x86 11 | msbuild ../libsodium-uwp.sln /t:Build /p:Platform=x64 /p:Configuration=Debug /m /verbosity:minimal /p:OutputPath=../build/Debug/x64 12 | msbuild ../libsodium-uwp.sln /t:Build /p:Platform=x64 /p:Configuration=Release /m /verbosity:minimal /p:OutputPath=../build/Release/x64 13 | -------------------------------------------------------------------------------- /.nuget/CreateNugetBuild.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | WHERE /Q nuget >NUL 4 | IF %ERRORLEVEL% NEQ 0 ( 5 | ECHO nuget not found. 6 | ECHO. 7 | ECHO Run "%~pd0download-nuget.cmd" to download the latest version, or update PATH as appropriate. 8 | GOTO END 9 | ) 10 | 11 | IF "%1"=="" ( 12 | GOTO PackWithFileVersion 13 | ) 14 | SET VERSION=%1 15 | GOTO PACK 16 | 17 | 18 | :PACK 19 | SET NUGET_ARGS=^ 20 | -nopackageanalysis ^ 21 | -version %VERSION% ^ 22 | -Verbosity detailed ^ 23 | -Symbols 24 | 25 | nuget pack libsodium-uwp.nuspec %NUGET_ARGS% 26 | 27 | :END 28 | 29 | EXIT /B -------------------------------------------------------------------------------- /.nuget/download-nuget.cmd: -------------------------------------------------------------------------------- 1 | powershell -command "(New-Object System.Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%~pd0nuget.exe')" -------------------------------------------------------------------------------- /.nuget/libsodium-uwp.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | libsodium-uwp 5 | 1.0.160 6 | libsodium for UWP 7 | Charles R. Portwood II (charlesportwoodii) 8 | https://github.com/charlesportwoodii/libsodium-uwp/blob/master/LICENSE 9 | https://github.com/charlesportwoodii/libsodium-uwp 10 | true 11 | libsodium-uwp - A secure cryptographic library for Universal Windows Platform 12 | 15 | Copyright (c) 2016-2018 Charles R. Portwood II & Contributors 16 | en-US 17 | libsodium NaCL encryption cryptography XSalsa20 Curve25519 Ed25519 Poly1305 hash kdf pbdfk2 hkdf Agon2i Argon2id Scrypt 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /.nuget/libsodium-uwp.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | x86 10 | $(Platform) 11 | 12 | 13 | 14 | 15 | $(MSBuildThisFileDirectory)..\..\runtimes\win10-$(libsodium-Platform)\native\Sodium.winmd 16 | true 17 | libsodium-uwp.dll 18 | 19 | 20 | 21 | 22 | 23 | 24 | $(MSBuildThisFileDirectory)..\..\Include;%(AdditionalIncludeDirectories) 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2017, Charles R. Portwood II 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of libsodium-uwp nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libsodium-uwp 2 | 3 | [![AppVeyor](https://img.shields.io/appveyor/ci/charlesportwoodii/libsodium-uwp.svg?style=flat-square)](https://ci.appveyor.com/project/charlesportwoodii/libsodium-uwp) 4 | [![License](https://img.shields.io/github/license/charlesportwoodii/libsodium-uwp.svg?style=flat-square)](https://github.com/charlesportwoodii/libsodium-uwp/blob/master/LICENSE.md) 5 | [![Nuget](https://img.shields.io/nuget/vpre/libsodium-uwp.svg?style=flat-square)](https://www.nuget.org/packages/libsodium-uwp/) 6 | 7 | libsodium-uwp ([libsodium](https://github.com/jedisct1/libsodium) for Universal Windows Platform (UWP)) is a C++ Windows Runtime Component for UWP applications. This library is fully tested and executes on both Windows 10 and Windows 10 mobile. 8 | 9 | Cryptography is hard. This library was written to make libsodium available to the .NET community building Universal Windows Applications so that developers can safely and securely implement cryptography within their application. 10 | 11 | ## Requirements 12 | 13 | - [Visual Studio 2015](https://www.visualstudio.com/vs/) 14 | 15 | ## Installation 16 | 17 | 1. Clone this project 18 | 19 | ``` 20 | git clone --recursive https://github.com/charlesportwoodii/libsodium-uwp 21 | ``` 22 | 2. Add the project solution to your project via `File->Add->Existing Project` 23 | 3. Add a reference to `libsodium-uwp` by adding `libsodium-uwp\libsodium-uwp\libsodium-uwp.vcxproj` to your project references. 24 | 4. Add a reference to `Visual C++ Redistributable for Visual Studio 2015` to your project. 25 | 26 | 27 | ### Nuget Installation 28 | 29 | 1. Install from Nuget 30 | 31 | ``` 32 | Install-Package libsodium-uwp 33 | ``` 34 | 35 | 2. Add the following to your `Package.appxmanifest` file. 36 | 37 | ```xml 38 | 39 | 40 | 41 | libsodium-uwp.dll 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | ``` 66 | 67 | ## Documentation 68 | 69 | See the [docs](docs/) folder for complete documentation on how to use this library. 70 | 71 | ## Notes 72 | 73 | `libsodium` requires the [Visual C++ Redistributable for Visual Studio 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48145). 74 | 75 | This library is currently a work in progress. While many libsodium functions are implemented, not are all. See the [docs](docs/) folder for more information. Also see the [releases](/releases) page for more information and details as to what is available on Nuget, as the `master` branch may be ahead of what is available there. 76 | 77 | ## License 78 | 79 | NaCl has been released to the public domain to avoid copyright issues. libsodium is subject to the ISC license, and this software is subject to the BSD-3 Clause License (see LICENSE.md). 80 | -------------------------------------------------------------------------------- /Test/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charlesportwoodii/libsodium-uwp/5bb57ba8c60f0d6ec95cf88fe344df4fd4728149/Test/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /Test/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charlesportwoodii/libsodium-uwp/5bb57ba8c60f0d6ec95cf88fe344df4fd4728149/Test/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /Test/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charlesportwoodii/libsodium-uwp/5bb57ba8c60f0d6ec95cf88fe344df4fd4728149/Test/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /Test/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charlesportwoodii/libsodium-uwp/5bb57ba8c60f0d6ec95cf88fe344df4fd4728149/Test/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /Test/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charlesportwoodii/libsodium-uwp/5bb57ba8c60f0d6ec95cf88fe344df4fd4728149/Test/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /Test/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charlesportwoodii/libsodium-uwp/5bb57ba8c60f0d6ec95cf88fe344df4fd4728149/Test/Assets/StoreLogo.png -------------------------------------------------------------------------------- /Test/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charlesportwoodii/libsodium-uwp/5bb57ba8c60f0d6ec95cf88fe344df4fd4728149/Test/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /Test/CoreTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class CoreTest 9 | { 10 | [TestCategory("Core")] 11 | [TestMethod] 12 | public void SodiumVersionStringTest() 13 | { 14 | const string EXPECTED = "1.0.16"; 15 | var actual = Core.SodiumVersionString(); 16 | Assert.AreEqual(EXPECTED, actual); 17 | 18 | actual = Core.SodiumVersionString(); 19 | Assert.AreNotEqual("1.0.11", actual); 20 | } 21 | 22 | [TestCategory("Core")] 23 | [TestMethod] 24 | public void GetRandomBytesTest() 25 | { 26 | int[] numbers = new int[] { 27 | 2, 28 | 4, 29 | 8, 30 | 16, 31 | 24, 32 | 32, 33 | 64, 34 | 128, 35 | 256 36 | }; 37 | foreach (int i in numbers) 38 | { 39 | byte[] bytes = Core.GetRandomBytes(i); 40 | Assert.IsTrue(bytes.Length == i); 41 | } 42 | } 43 | 44 | [TestCategory("Core")] 45 | [TestMethod] 46 | public void GetRandomNumberTest() 47 | { 48 | int[] numbers = new int[] { 49 | 5, 50 | 8, 51 | 10, 52 | 16, 53 | 24, 54 | 32, 55 | 64, 56 | 100, 57 | 10000, 58 | 50000 59 | }; 60 | 61 | foreach (int i in numbers) 62 | { 63 | int n = Core.GetRandomNumber(i); 64 | Assert.IsTrue(n <= i); 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Test/CryptoHashTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class CryptoHashTest 9 | { 10 | // sha outputs are the corresponding sha of hashString 11 | const String hashString = "Charles R. Portwood II"; 12 | const String sha256out = "d6cbe4e3af308a3506c7f3caaa0a0541382d2d7f3d3f8c2a4698e4933d22741a"; 13 | const String sha512out = "48566c83fb3e3b65dbb0e9781d65560aaeadc4f2ac7a521a604c21eec8a5cc06c88a9ba415f4b6b4d6673be3c6d10670485660dcdb362a11ea5f79fb4fe3cf67"; 14 | 15 | [TestCategory("CryptoHash")] 16 | [TestMethod] 17 | public void Sha256Test() 18 | { 19 | var sha256 = CryptoHash.Sha256(System.Text.Encoding.UTF8.GetBytes(hashString)); 20 | string hex = BitConverter.ToString(sha256).Replace("-", string.Empty).ToLower(); 21 | Assert.AreEqual(sha256out, hex); 22 | 23 | sha256 = CryptoHash.Sha256(hashString); 24 | hex = BitConverter.ToString(sha256).Replace("-", string.Empty).ToLower(); 25 | Assert.AreEqual(sha256out, hex); 26 | } 27 | 28 | [TestCategory("CryptoHash")] 29 | [TestMethod] 30 | public void Sha512Test() 31 | { 32 | var sha512 = CryptoHash.Sha512(System.Text.Encoding.UTF8.GetBytes(hashString)); 33 | string hex = BitConverter.ToString(sha512).Replace("-", string.Empty).ToLower(); 34 | Assert.AreEqual(sha512out, hex); 35 | 36 | sha512 = CryptoHash.Sha512(hashString); 37 | hex = BitConverter.ToString(sha512).Replace("-", string.Empty).ToLower(); 38 | Assert.AreEqual(sha512out, hex); 39 | } 40 | 41 | [TestCategory("CryptoHash")] 42 | [TestMethod] 43 | public void HashTest() 44 | { 45 | var hash = CryptoHash.Hash(System.Text.Encoding.UTF8.GetBytes(hashString)); 46 | string hex = BitConverter.ToString(hash).Replace("-", string.Empty).ToLower(); 47 | Assert.AreEqual(sha512out, hex); 48 | 49 | hash = CryptoHash.Hash(hashString); 50 | hex = BitConverter.ToString(hash).Replace("-", string.Empty).ToLower(); 51 | Assert.AreEqual(sha512out, hex); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Test/OneTimeAuthTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class OneTimeAuthTest 9 | { 10 | [TestCategory("OneTimeAuth")] 11 | [TestMethod] 12 | public void GenerateKeyTest() 13 | { 14 | Assert.AreEqual(32, OneTimeAuth.GenerateKey().Length); 15 | } 16 | 17 | [TestCategory("OneTimeAuth")] 18 | [TestMethod] 19 | public void SignAndVerifyTest() 20 | { 21 | string message = "Hello, World!"; 22 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 23 | var key = OneTimeAuth.GenerateKey(); 24 | 25 | var sig1 = OneTimeAuth.Sign(message, key); 26 | var sig2 = OneTimeAuth.Sign(byteMessage, key); 27 | 28 | // Verify the outputs of the overload are equal 29 | Assert.AreEqual(Convert.ToBase64String(sig1), Convert.ToBase64String(sig2)); 30 | 31 | var result = false; 32 | 33 | result = OneTimeAuth.Verify(message, sig1, key); 34 | Assert.IsTrue(result); 35 | result = OneTimeAuth.Verify(message, sig2, key); 36 | Assert.IsTrue(result); 37 | result = OneTimeAuth.Verify(byteMessage, sig1, key); 38 | Assert.IsTrue(result); 39 | result = OneTimeAuth.Verify(byteMessage, sig2, key); 40 | Assert.IsTrue(result); 41 | 42 | result = OneTimeAuth.Verify("test", sig1, key); 43 | Assert.IsFalse(result); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Test/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Test 7 | Charles R. Portwood II 8 | Assets\StoreLogo.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | libsodium-uwp.dll 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Test/PasswordHashTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class PasswordHashTest 9 | { 10 | [TestCategory("PasswordHash")] 11 | [TestMethod] 12 | public void Argon2iTest() 13 | { 14 | var options = PasswordHash.CreateOptions(1 << 8, 3); 15 | 16 | string password = "correct horse battery staple"; 17 | var hash = PasswordHash.Hash(password, PasswordHash.Argon2i, options); 18 | Assert.IsTrue(PasswordHash.Verify(hash, password)); 19 | Assert.IsFalse(PasswordHash.Verify(hash, "the wrong password")); 20 | } 21 | 22 | [TestCategory("PasswordHash")] 23 | [TestMethod] 24 | public void Argon2idTest() 25 | { 26 | var options = PasswordHash.CreateOptions(1 << 8, 3); 27 | 28 | string password = "correct horse battery staple"; 29 | var hash = PasswordHash.Hash(password, PasswordHash.Argon2id, options); 30 | Assert.IsTrue(PasswordHash.Verify(hash, password)); 31 | Assert.IsFalse(PasswordHash.Verify(hash, "the wrong password")); 32 | } 33 | 34 | [TestCategory("PasswordHash")] 35 | [TestMethod] 36 | public void NeedsRehashTest() 37 | { 38 | var options = PasswordHash.CreateOptions(1 << 8, 3); 39 | 40 | string password = "correct horse battery staple"; 41 | var hash = PasswordHash.Hash(password, PasswordHash.Argon2id, options); 42 | Assert.IsFalse(PasswordHash.NeedsRehash(hash, options)); 43 | 44 | var newOptions = PasswordHash.CreateOptions(1 << 8, 4); 45 | Assert.IsTrue(PasswordHash.NeedsRehash(hash, newOptions)); 46 | } 47 | 48 | [TestCategory("PasswordHash")] 49 | [TestMethod] 50 | public void ScryptTest() 51 | { 52 | var options = PasswordHash.CreateOptions(1 << 8, 3); 53 | 54 | string password = "correct horse battery staple"; 55 | var hash = PasswordHash.Hash(password, PasswordHash.Scrypt, options); 56 | Assert.IsTrue(PasswordHash.Verify(hash, password)); 57 | Assert.IsFalse(PasswordHash.Verify(hash, "the wrong password")); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Test")] 9 | [assembly: AssemblyDescription("Unit Tests for libsodium-uwp")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Test")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | [assembly: AssemblyMetadata("TargetPlatform","UAP")] 17 | 18 | // Version information for an assembly consists of the following four values: 19 | // 20 | // Major Version 21 | // Minor Version 22 | // Build Number 23 | // Revision 24 | // 25 | // You can specify all the values or you can default the Build and Revision Numbers 26 | // by using the '*' as shown below: 27 | // [assembly: AssemblyVersion("1.0.*")] 28 | [assembly: AssemblyVersion("1.0.0.0")] 29 | [assembly: AssemblyFileVersion("1.0.0.0")] 30 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Test/Properties/UnitTestApp.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Test/PublicKeyAuthTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | using Windows.Storage.Streams; 5 | using Windows.Security.Cryptography; 6 | using Windows.Security.Cryptography.Core; 7 | 8 | namespace Test 9 | { 10 | [TestClass] 11 | public class PublicKeyAuthTest 12 | { 13 | [TestCategory("PublicKeyAuth")] 14 | [TestMethod] 15 | public void GenerateKeyPairTest() 16 | { 17 | var kp = PublicKeyAuth.GenerateKeyPair(); 18 | Assert.AreEqual(32, kp.Public.Length); 19 | Assert.AreEqual(64, kp.Secret.Length); 20 | } 21 | 22 | [TestCategory("PublicKeyAuth")] 23 | [TestMethod] 24 | public void GenerateKeyPairFromSeedTest() 25 | { 26 | var seed = Core.GetRandomBytes(32); 27 | var kp = PublicKeyAuth.GenerateKeyPair(seed); 28 | Assert.AreEqual(32, kp.Public.Length); 29 | Assert.AreEqual(64, kp.Secret.Length); 30 | } 31 | 32 | [TestCategory("PublicKeyAuth")] 33 | [TestMethod] 34 | public void SignTest() 35 | { 36 | var kp = PublicKeyAuth.GenerateKeyPair(); 37 | String message = "Hello, World!"; 38 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 39 | var signature = PublicKeyAuth.Sign(message, kp.Secret); 40 | 41 | // Test against a seed and expected output generated from libsodium 42 | var seed = Convert.FromBase64String("zYZceFCtMRu4FAi/a47fN+21396uv/QcUMvi/u08zCw="); 43 | var expected = Convert.FromBase64String("BlWhHIrosG+Q7jq/lMgxkw79f7dM1x2u+IR6f5nPojaVdaXpUbSpzVSPT238CCDInCnQQ5ueMetEoaXYhET+CEhlbGxvLCBXb3JsZCE="); 44 | kp = PublicKeyAuth.GenerateKeyPair(seed); 45 | signature = PublicKeyAuth.Sign(byteMessage, kp.Secret); 46 | Assert.AreEqual(expected.ToString(), signature.ToString()); 47 | 48 | signature = PublicKeyAuth.Sign(message, kp.Secret); 49 | Assert.AreEqual(expected.ToString(), signature.ToString()); 50 | } 51 | 52 | [TestCategory("PublicKeyAuth")] 53 | [TestMethod] 54 | public void VerifyTest() 55 | { 56 | var kp = PublicKeyAuth.GenerateKeyPair(); 57 | byte[] message = System.Text.Encoding.UTF8.GetBytes("Hello, World!"); 58 | var signature = PublicKeyAuth.Sign(message, kp.Secret); 59 | var verification = PublicKeyAuth.Verify(signature, kp.Public); 60 | Assert.AreEqual(message.ToString(), verification.ToString()); 61 | } 62 | 63 | [TestCategory("Curve25519 Key Extraction")] 64 | [TestMethod] 65 | public void ConvertToCurve25519Test() 66 | { 67 | // Keypair seed from libsodium-net 68 | var keypairSeed = new byte[] { 69 | 0x42, 0x11, 0x51, 0xa4, 0x59, 0xfa, 0xea, 0xde, 70 | 0x3d, 0x24, 0x71, 0x15, 0xf9, 0x4a, 0xed, 0xae, 71 | 0x42, 0x31, 0x81, 0x24, 0x09, 0x5a, 0xfa, 0xbe, 72 | 0x4d, 0x14, 0x51, 0xa5, 0x59, 0xfa, 0xed, 0xee 73 | }; 74 | 75 | var kp = PublicKeyAuth.GenerateKeyPair(keypairSeed); 76 | 77 | var ed25519Pk = kp.Public; 78 | var ed25519SkPk = kp.Secret; 79 | 80 | var curve25519Pk = PublicKeyAuth.ConvertEd25519PublicKeyToCurve25519PublicKey(ed25519Pk); 81 | var curve25519Sk = PublicKeyAuth.ConvertEd25519SecretKeyToCurve25519SecretKey(ed25519SkPk); 82 | 83 | Assert.AreEqual(Convert.ToBase64String(curve25519Pk), "8YFPDo/xBD2KRNJbq/887crmwiw+2qSPhXrnDeK6rlA="); 84 | Assert.AreEqual(Convert.ToBase64String(curve25519Sk), "gFIDA3bUcRK+f3PtegGSk90SrZELZURVeYtGZ9c94WY="); 85 | 86 | for (var i = 0; i < 500; i++) 87 | { 88 | kp = PublicKeyAuth.GenerateKeyPair(); 89 | ed25519Pk = kp.Public; 90 | ed25519SkPk = kp.Secret; 91 | curve25519Pk = PublicKeyAuth.ConvertEd25519PublicKeyToCurve25519PublicKey(ed25519Pk); 92 | curve25519Sk = PublicKeyAuth.ConvertEd25519SecretKeyToCurve25519SecretKey(ed25519SkPk); 93 | var curve25519Pk2 = ScalarMult.Base(curve25519Sk); 94 | 95 | CollectionAssert.AreEqual(curve25519Pk, curve25519Pk2); 96 | } 97 | } 98 | 99 | [TestCategory("Detached PublicKeyAuth")] 100 | [TestMethod] 101 | public void DetachedSignTest() 102 | { 103 | var kp = PublicKeyAuth.GenerateKeyPair(); 104 | string message = "Hello, World!"; 105 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 106 | 107 | var sig1 = PublicKeyAuth.SignDetached(message, kp.Secret); 108 | var sig2 = PublicKeyAuth.SignDetached(byteMessage, kp.Secret); 109 | 110 | Assert.AreEqual(Convert.ToBase64String(sig1), Convert.ToBase64String(sig2)); 111 | Assert.AreEqual(64, sig1.Length); 112 | Assert.AreEqual(64, sig2.Length); 113 | 114 | Assert.IsTrue(PublicKeyAuth.VerifyDetached(sig1, byteMessage, kp.Public)); 115 | Assert.IsTrue(PublicKeyAuth.VerifyDetached(sig1, message, kp.Public)); 116 | Assert.IsTrue(PublicKeyAuth.VerifyDetached(sig2, byteMessage, kp.Public)); 117 | Assert.IsTrue(PublicKeyAuth.VerifyDetached(sig2, message, kp.Public)); 118 | 119 | var kp2 = PublicKeyAuth.GenerateKeyPair(); 120 | Assert.IsFalse(PublicKeyAuth.VerifyDetached(sig2, message, kp2.Public)); 121 | Assert.IsFalse(PublicKeyAuth.VerifyDetached(sig2, "Invalid message test", kp.Public)); 122 | } 123 | 124 | [TestCategory("Ed25519 Key Extraction")] 125 | [TestMethod] 126 | public void ExtractEd25519SeedFromEd25519SecretKeyTest() 127 | { 128 | var kp1 = PublicKeyAuth.GenerateKeyPair(); 129 | var seed = PublicKeyAuth.ExtractEd25519SeedFromEd25519SecretKey(kp1.Secret); 130 | var kp2 = PublicKeyAuth.GenerateKeyPair(seed); 131 | 132 | Assert.AreEqual(Convert.ToBase64String(kp1.Public), Convert.ToBase64String(kp2.Public)); 133 | Assert.AreEqual(Convert.ToBase64String(kp1.Secret), Convert.ToBase64String(kp2.Secret)); 134 | } 135 | 136 | [TestCategory("Ed25519 Key Extraction")] 137 | [TestMethod] 138 | public void ExtractEd25519PublicKeyFromEd25519SecretKeyTest() 139 | { 140 | var kp = PublicKeyAuth.GenerateKeyPair(); 141 | var pub = PublicKeyAuth.ExtractEd25519PublicKeyFromEd25519SecretKey(kp.Secret); 142 | Assert.AreEqual(Convert.ToBase64String(kp.Public), Convert.ToBase64String(pub)); 143 | } 144 | 145 | [TestCategory("PublicKeyAuth")] 146 | [TestMethod] 147 | public void SignAndVerifyFromMessageTest() 148 | { 149 | var kp = PublicKeyAuth.GenerateKeyPair(); 150 | var signature = new PublicKeyAuth(); 151 | IBuffer data = CryptographicBuffer.ConvertStringToBinary("Hello, World!", BinaryStringEncoding.Utf8); 152 | signature.Append(data); 153 | 154 | var output = signature.GetValueAndReset(kp.Secret); 155 | Assert.AreEqual(64, output.Length); 156 | Assert.AreEqual(true, signature.GetValueAndVerify(output, kp.Public)); 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /Test/PublicKeyBoxTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class PublicKeyBoxTest 9 | { 10 | [TestCategory("PublicKeyBox")] 11 | [TestMethod] 12 | public void GenerateNonceText() 13 | { 14 | Assert.AreEqual(24, PublicKeyBox.GenerateNonce().Length); 15 | } 16 | 17 | [TestCategory("PublicKeyBox")] 18 | [TestMethod] 19 | public void GenerateKeyPairTest() 20 | { 21 | var kp = PublicKeyBox.GenerateKeyPair(); 22 | Assert.AreEqual(32, kp.Public.Length); 23 | Assert.AreEqual(32, kp.Secret.Length); 24 | } 25 | 26 | [TestCategory("PublicKeyBox")] 27 | [TestMethod] 28 | public void GenerateKeyPairFromSeedTest() 29 | { 30 | // Generates 32 random bytes as a seed. 31 | var key = Core.GetRandomBytes(32); 32 | var kp = PublicKeyBox.GenerateKeyPair(key); 33 | Assert.AreEqual(32, kp.Public.Length); 34 | Assert.AreEqual(32, kp.Secret.Length); 35 | 36 | // Check against a generated key from libsodium 37 | var secret = Convert.FromBase64String("xIsxKqHum01qF1EmiV8WLm2jCiEfcHsXZYYucvOStDE="); 38 | var pub = Convert.FromBase64String("JnZhWB8n7nDgMKXGy2XwXmvLQP9wY4TU3nUJtwultA8="); 39 | var kp2 = PublicKeyBox.GenerateKeyPair(secret); 40 | Assert.AreEqual(32, kp2.Public.Length); 41 | Assert.AreEqual(32, kp2.Secret.Length); 42 | Assert.AreEqual(Convert.ToBase64String(pub), Convert.ToBase64String(kp2.Public)); 43 | Assert.AreEqual(Convert.ToBase64String(secret), Convert.ToBase64String(kp2.Secret)); 44 | } 45 | 46 | [TestCategory("PublicKeyBox")] 47 | [TestMethod] 48 | public void CreateAndOpenWithOneKeyTest() 49 | { 50 | var kp = PublicKeyBox.GenerateKeyPair(); 51 | var nonce = PublicKeyBox.GenerateNonce(); 52 | byte[] message = System.Text.Encoding.UTF8.GetBytes("Hello, World!"); 53 | 54 | var encrypted = PublicKeyBox.Create(message, nonce, kp.Secret, kp.Public); 55 | var decrypted = PublicKeyBox.Open(encrypted, nonce, kp.Secret, kp.Public); 56 | Assert.AreEqual(message.ToString(), decrypted.ToString()); 57 | } 58 | 59 | [TestCategory("PublicKeyBox")] 60 | [TestMethod] 61 | public void CreateAndOpenWithKeyExchangeTest() 62 | { 63 | var alice = PublicKeyBox.GenerateKeyPair(); 64 | var bob = PublicKeyBox.GenerateKeyPair(); 65 | var nonce = PublicKeyBox.GenerateNonce(); 66 | String message = "Hello, World!"; 67 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 68 | 69 | var encrypted = PublicKeyBox.Create(byteMessage, nonce, alice.Secret, bob.Public); 70 | var decrypted = PublicKeyBox.Open(encrypted, nonce, bob.Secret, alice.Public); 71 | Assert.AreEqual(decrypted.ToString(), byteMessage.ToString()); 72 | 73 | var newEncrypted = PublicKeyBox.Create(message, nonce, alice.Secret, bob.Public); 74 | Assert.AreEqual(Convert.ToBase64String(encrypted), Convert.ToBase64String(newEncrypted)); 75 | var newDecrypted = PublicKeyBox.Open(newEncrypted, nonce, bob.Secret, alice.Public); 76 | Assert.AreEqual(decrypted.ToString(), newDecrypted.ToString()); 77 | } 78 | 79 | [TestCategory("PublicKeyBox")] 80 | [TestMethod] 81 | public void OpenWithKeyAndNonce() 82 | { 83 | // Key, CipherText, and Nonce generated from libsodium 84 | var cipherText = Convert.FromBase64String("9Zz8uwvPNqaSzebM4Lf1Gx9RmsaSiww+P0cUogk="); 85 | var nonce = Convert.FromBase64String("xMD3oIf1lzGK/3X0zFwB0pkcR4ajrb6N"); 86 | var key = Convert.FromBase64String("xIsxKqHum01qF1EmiV8WLm2jCiEfcHsXZYYucvOStDE="); 87 | var kp = PublicKeyBox.GenerateKeyPair(key); 88 | String message = "Hello, World!"; 89 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 90 | 91 | var decrypted = PublicKeyBox.Open(cipherText, nonce, kp.Secret, kp.Public); 92 | Assert.AreEqual(decrypted.ToString(), byteMessage.ToString()); 93 | } 94 | 95 | [TestCategory("Detached PublicKeyBox")] 96 | [TestMethod] 97 | public void DetachedBoxTest() 98 | { 99 | var alice = PublicKeyBox.GenerateKeyPair(); 100 | var bob = PublicKeyBox.GenerateKeyPair(); 101 | var nonce = PublicKeyBox.GenerateNonce(); 102 | String message = "Hello, World!"; 103 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 104 | 105 | var e1 = PublicKeyBox.CreateDetached(message, nonce, bob.Secret, alice.Public); 106 | var e2 = PublicKeyBox.CreateDetached(message, nonce, bob.Secret, alice.Public); 107 | 108 | Assert.AreEqual(Convert.ToBase64String(e1.Cipher), Convert.ToBase64String(e2.Cipher)); 109 | Assert.AreEqual(Convert.ToBase64String(e1.Mac), Convert.ToBase64String(e2.Mac)); 110 | 111 | var d1 = PublicKeyBox.OpenDetached(e1, nonce, alice.Secret, bob.Public); 112 | var d2 = PublicKeyBox.OpenDetached(e2, nonce, alice.Secret, bob.Public); 113 | 114 | Assert.AreEqual(message, System.Text.Encoding.UTF8.GetString(d1)); 115 | Assert.AreEqual(message, System.Text.Encoding.UTF8.GetString(d2)); 116 | 117 | d1 = PublicKeyBox.OpenDetached(e1.Cipher, e1.Mac, nonce, alice.Secret, bob.Public); 118 | d2 = PublicKeyBox.OpenDetached(e2.Cipher, e2.Mac, nonce, alice.Secret, bob.Public); 119 | 120 | Assert.AreEqual(message, System.Text.Encoding.UTF8.GetString(d1)); 121 | Assert.AreEqual(message, System.Text.Encoding.UTF8.GetString(d2)); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Test/ScalarMultTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | /// Derived from https://github.com/adamcaudill/libsodium-net/blob/master/Tests/ScalarMultTest.cs 8 | [TestClass] 9 | public class ScalarMultTest 10 | { 11 | [TestCategory("ScalarMult")] 12 | [TestMethod] 13 | public void ScalarMult1() 14 | { 15 | var aliceSk = new byte[] { 16 | 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d, 17 | 0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45, 18 | 0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a, 19 | 0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a 20 | }; 21 | 22 | var alicePk = ScalarMult.Base(aliceSk); 23 | 24 | var result = new byte[] { 25 | 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54, 26 | 0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a, 27 | 0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4, 28 | 0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a 29 | }; 30 | 31 | Assert.AreEqual(Convert.ToBase64String(alicePk), Convert.ToBase64String(result)); 32 | } 33 | 34 | [TestCategory("ScalarMult")] 35 | [TestMethod] 36 | public void ScalarMult2() 37 | { 38 | var bobSk = new byte[] { 39 | 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b, 40 | 0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6, 41 | 0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd, 42 | 0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb 43 | }; 44 | 45 | var bobPk = ScalarMult.Base(bobSk); 46 | 47 | var result = new byte[] { 48 | 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4, 49 | 0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37, 50 | 0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d, 51 | 0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f 52 | }; 53 | 54 | Assert.AreEqual(Convert.ToBase64String(bobPk), Convert.ToBase64String(result)); 55 | } 56 | 57 | [TestCategory("ScalarMult")] 58 | [TestMethod] 59 | public void ScalarMult5() 60 | { 61 | var aliceSk = new byte[] { 62 | 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d, 63 | 0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45, 64 | 0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a, 65 | 0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a 66 | }; 67 | 68 | var bobPk = new byte[] { 69 | 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4, 70 | 0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37, 71 | 0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d, 72 | 0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f 73 | }; 74 | 75 | var k = ScalarMult.Mult(aliceSk, bobPk); 76 | 77 | var result = new byte[] { 78 | 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1, 79 | 0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25, 80 | 0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33, 81 | 0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42 82 | }; 83 | 84 | Assert.AreEqual(Convert.ToBase64String(k), Convert.ToBase64String(result)); 85 | } 86 | 87 | [TestCategory("ScalarMult")] 88 | [TestMethod] 89 | public void ScalarMult6() 90 | { 91 | var bobSk = new byte[] { 92 | 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b, 93 | 0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6, 94 | 0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd, 95 | 0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb 96 | }; 97 | 98 | var alicePk = new byte[] { 99 | 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54, 100 | 0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a, 101 | 0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4, 102 | 0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a 103 | }; 104 | 105 | var k = ScalarMult.Mult(bobSk, alicePk); 106 | 107 | var result = new byte[] { 108 | 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1, 109 | 0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25, 110 | 0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33, 111 | 0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42 112 | }; 113 | 114 | Assert.AreEqual(Convert.ToBase64String(k), Convert.ToBase64String(result)); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Test/SealedPublicKeyBoxTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class SealedPublicKeyBoxTest 9 | { 10 | [TestCategory("SealedPublicKeyBox")] 11 | [TestMethod] 12 | public void CreateAndOpenSealedBoxTest() 13 | { 14 | String message = "Hello, World!"; 15 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 16 | var keyPair = PublicKeyBox.GenerateKeyPair(); 17 | 18 | var encrypted = SealedPublicKeyBox.Create(byteMessage, keyPair.Public); 19 | var decrypted = SealedPublicKeyBox.Open(encrypted, keyPair.Secret, keyPair.Public); 20 | Assert.AreEqual(byteMessage.ToString(), decrypted.ToString()); 21 | 22 | var newEncrypted = SealedPublicKeyBox.Create(message, keyPair.Public); 23 | var newDecrypted = SealedPublicKeyBox.Open(newEncrypted, keyPair.Secret, keyPair.Public); 24 | Assert.AreEqual(decrypted.ToString(), newDecrypted.ToString()); 25 | } 26 | 27 | [TestCategory("SealedPublicKeyBox")] 28 | [TestMethod] 29 | public void CreateAndOpenSealedBoxWithKeyPairTest() 30 | { 31 | String message = "Hello, World!"; 32 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 33 | var keyPair = PublicKeyBox.GenerateKeyPair(); 34 | 35 | var encrypted = SealedPublicKeyBox.Create(byteMessage, keyPair.Public); 36 | var decrypted = SealedPublicKeyBox.Open(encrypted, keyPair); 37 | Assert.AreEqual(byteMessage.ToString(), decrypted.ToString()); 38 | 39 | var newEncrypted = SealedPublicKeyBox.Create(message, keyPair.Public); 40 | var newDecrypted = SealedPublicKeyBox.Open(newEncrypted, keyPair); 41 | Assert.AreEqual(decrypted.ToString(), newDecrypted.ToString()); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Test/SecretAeadTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class SecretAeadTest 9 | { 10 | [TestCategory("SecretAead::Chacha20-Poly1309")] 11 | [TestMethod] 12 | public void GenerateNonceTest() 13 | { 14 | Assert.AreEqual(8, SecretAead.GenerateNonce().Length); 15 | } 16 | 17 | [TestCategory("SecretAead::Chacha20-Poly1309")] 18 | [TestMethod] 19 | public void EncryptAndDecryptTest() 20 | { 21 | String message = "Hello, World!"; 22 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 23 | var key = SecretBox.GenerateKey(); 24 | var nonce = SecretAead.GenerateNonce(); 25 | var encrypted = SecretAead.Encrypt(byteMessage, nonce, key); 26 | var decrypted = SecretAead.Decrypt(encrypted, nonce, key); 27 | Assert.AreEqual(byteMessage.ToString(), decrypted.ToString()); 28 | 29 | var newEncrypted = SecretAead.Encrypt(message, nonce, key); 30 | Assert.AreEqual(Convert.ToBase64String(encrypted), Convert.ToBase64String(newEncrypted)); 31 | decrypted = SecretAead.Decrypt(newEncrypted, nonce, key); 32 | Assert.AreEqual(byteMessage.ToString(), decrypted.ToString()); 33 | } 34 | 35 | [TestCategory("SecretAead::Chacha20-Poly1309")] 36 | [TestMethod] 37 | public void EncryptAndDecryptWithADTest() 38 | { 39 | String message = "Hello, World!"; 40 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 41 | byte[] ad = System.Text.Encoding.UTF8.GetBytes("Additional Data"); 42 | var key = SecretBox.GenerateKey(); 43 | var nonce = SecretAead.GenerateNonce(); 44 | var encrypted = SecretAead.Encrypt(byteMessage, nonce, key, ad); 45 | var decrypted = SecretAead.Decrypt(encrypted, nonce, key, ad); 46 | Assert.AreEqual(byteMessage.ToString(), decrypted.ToString()); 47 | 48 | encrypted = SecretAead.Encrypt(message, nonce, key, ad); 49 | decrypted = SecretAead.Decrypt(encrypted, nonce, key, ad); 50 | Assert.AreEqual(byteMessage.ToString(), decrypted.ToString()); 51 | } 52 | 53 | /// Binary source from: https://github.com/jedisct1/libsodium/blob/master/test/default/aead_chacha20poly1305.c 54 | [TestCategory("SecretAead::Chacha20-Poly1309")] 55 | [TestMethod] 56 | public void AeadWithAdditionalDataTest() 57 | { 58 | var key = new byte[] 59 | { 60 | 0x42, 0x90, 0xbc, 0xb1, 0x54, 0x17, 0x35, 0x31, 0xf3, 0x14, 0xaf, 61 | 0x57, 0xf3, 0xbe, 0x3b, 0x50, 0x06, 0xda, 0x37, 0x1e, 0xce, 0x27, 62 | 0x2a, 0xfa, 0x1b, 0x5d, 0xbd, 0xd1, 0x10, 0x0a, 0x10, 0x07 63 | }; 64 | 65 | var nonce = new byte[] 66 | { 67 | 0xcd, 0x7c, 0xf6, 0x7b, 0xe3, 0x9c, 0x79, 0x4a 68 | }; 69 | 70 | var ad = new byte[] 71 | { 72 | 0x87, 0xe2, 0x29, 0xd4, 0x50, 0x08, 0x45, 0xa0, 0x79, 0xc0 73 | }; 74 | 75 | var m = new byte[] 76 | { 77 | 0x86, 0xd0, 0x99, 0x74, 0x84, 0x0b, 0xde, 0xd2, 0xa5, 0xca 78 | }; 79 | 80 | var encrypted = SecretAead.Encrypt(m, nonce, key, ad); 81 | var decrypted = SecretAead.Decrypt(encrypted, nonce, key, ad); 82 | 83 | Assert.AreEqual(m.ToString(), decrypted.ToString()); 84 | } 85 | 86 | /// Binary source from: https://github.com/jedisct1/libsodium/blob/master/test/default/aead_chacha20poly1305.c 87 | [TestCategory("SecretAead::Chacha20-Poly1309")] 88 | [TestMethod] 89 | public void AeadWithoutAdditionalDataTest() 90 | { 91 | var key = new byte[] 92 | { 93 | 0x42, 0x90, 0xbc, 0xb1, 0x54, 0x17, 0x35, 0x31, 0xf3, 0x14, 0xaf, 94 | 0x57, 0xf3, 0xbe, 0x3b, 0x50, 0x06, 0xda, 0x37, 0x1e, 0xce, 0x27, 95 | 0x2a, 0xfa, 0x1b, 0x5d, 0xbd, 0xd1, 0x10, 0x0a, 0x10, 0x07 96 | }; 97 | 98 | var nonce = new byte[] 99 | { 100 | 0xcd, 0x7c, 0xf6, 0x7b, 0xe3, 0x9c, 0x79, 0x4a 101 | }; 102 | 103 | var m = new byte[] 104 | { 105 | 0x86, 0xd0, 0x99, 0x74, 0x84, 0x0b, 0xde, 0xd2, 0xa5, 0xca 106 | }; 107 | 108 | var encrypted = SecretAead.Encrypt(m, nonce, key); 109 | var decrypted = SecretAead.Decrypt(encrypted, nonce, key); 110 | 111 | Assert.AreEqual(m.ToString(), decrypted.ToString()); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Test/SecretBoxTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class SecretBoxTest 9 | { 10 | [TestCategory("SecretBox")] 11 | [TestMethod] 12 | public void SecretBoxGenerateNonceText() 13 | { 14 | Assert.AreEqual(24, SecretBox.GenerateNonce().Length); 15 | } 16 | 17 | [TestCategory("SecretBox")] 18 | [TestMethod] 19 | public void SecretBoxGenerateKeyTest() 20 | { 21 | Assert.AreEqual(32, SecretBox.GenerateKey().Length); 22 | } 23 | 24 | [TestCategory("SecretBox")] 25 | [TestMethod] 26 | public void SecretBoxCreateTest() 27 | { 28 | // Randomly generate key and nonce from a separate libsodium implementation 29 | var key = "7IygDz/Hy8LC/wqXb6vsrpq7Vyn7mxCoh8nYOn5yVXc="; 30 | var nonce = "bUBIsnfvIv2Wo95SEkt4DIvBqZLGGBjV"; 31 | String message = "Hello, World!"; 32 | 33 | String expectedCipherText = "cZFTGV7SrPeSdX5Q6b30PBEm5Y2uby/W5BSrrfU="; 34 | byte[] expectedCipherTextBytes = Convert.FromBase64String(expectedCipherText); 35 | 36 | byte[] bitKey = Convert.FromBase64String(key); 37 | byte[] bitNonce = Convert.FromBase64String(nonce); 38 | byte[] cipherText = SecretBox.Create(System.Text.Encoding.UTF8.GetBytes(message), bitNonce, bitKey); 39 | 40 | Assert.AreEqual(expectedCipherText, Convert.ToBase64String(cipherText)); 41 | 42 | cipherText = SecretBox.Create(message, bitNonce, bitKey); 43 | Assert.AreEqual(expectedCipherText, Convert.ToBase64String(cipherText)); 44 | } 45 | 46 | [TestCategory("SecretBox")] 47 | [TestMethod] 48 | public void SecretBoxOpenTest() 49 | { 50 | var key = "7IygDz/Hy8LC/wqXb6vsrpq7Vyn7mxCoh8nYOn5yVXc="; 51 | var nonce = "bUBIsnfvIv2Wo95SEkt4DIvBqZLGGBjV"; 52 | byte[] message = System.Text.Encoding.UTF8.GetBytes("Hello, World!"); 53 | 54 | String cipherText = "cZFTGV7SrPeSdX5Q6b30PBEm5Y2uby/W5BSrrfU="; 55 | byte[] cipherTextBytes = Convert.FromBase64String(cipherText); 56 | 57 | byte[] bitKey = Convert.FromBase64String(key); 58 | byte[] bitNonce = Convert.FromBase64String(nonce); 59 | byte[] plainText = SecretBox.Open(cipherTextBytes, bitNonce, bitKey); 60 | 61 | Assert.AreEqual(message.ToString(), plainText.ToString()); 62 | } 63 | 64 | [TestCategory("SecretBox")] 65 | [TestMethod] 66 | public void SecretBoxOpenWithGeneratedDataTest() 67 | { 68 | var key = SecretBox.GenerateKey(); 69 | var nonce = SecretBox.GenerateNonce(); 70 | String message = "Hello, World!"; 71 | 72 | byte[] plainText = System.Text.Encoding.UTF8.GetBytes(message); 73 | byte[] cipherText = SecretBox.Create(plainText, nonce, key); 74 | byte[] decrypted = SecretBox.Open(cipherText, nonce, key); 75 | 76 | Assert.AreEqual(plainText.ToString(), decrypted.ToString()); 77 | } 78 | 79 | [TestCategory("Detached SecretBox")] 80 | [TestMethod] 81 | public void DetachedSecretBoxTest() 82 | { 83 | var nonce = Sodium.SecretBox.GenerateNonce(); 84 | var key = Sodium.SecretBox.GenerateKey(); 85 | var message = System.Text.Encoding.UTF8.GetBytes("Charles R. Portwood II"); 86 | var actual = Sodium.SecretBox.CreateDetached(message, nonce, key); 87 | 88 | Assert.AreEqual(actual.Mac.Length, 16); 89 | var clear = Sodium.SecretBox.OpenDetached(actual.Cipher, actual.Mac, nonce, key); 90 | 91 | Assert.AreEqual(Convert.ToBase64String(message), Convert.ToBase64String(clear)); 92 | 93 | clear = Sodium.SecretBox.OpenDetached(actual, nonce, key); 94 | Assert.AreEqual(Convert.ToBase64String(message), Convert.ToBase64String(clear)); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Test/SecretKeyAuthTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class SecretKeyAuthTest 9 | { 10 | [TestCategory("SecretKeyAuth")] 11 | [TestMethod] 12 | public void SecretKeyAuthGenerateKeyTest() 13 | { 14 | Assert.AreEqual(32, SecretKeyAuth.GenerateKey().Length); 15 | } 16 | 17 | [TestCategory("SecretKeyAuth")] 18 | [TestMethod] 19 | public void SecretKeyAuthSignTest() 20 | { 21 | // Test signing given a known key and signature generated from libsodium 22 | byte[] key = Convert.FromBase64String("wYSsnapy7G9F+NTo/bVvIpnRv/ULd97XSMPLoe4+abM="); 23 | String expectedSignature = "hQ4vOFX+pPJNhXxnbMfzAtLjSVeRBBGCOIjlNoIWvzA="; 24 | String message = "Hello, World!"; 25 | byte[] signature = SecretKeyAuth.Sign(System.Text.Encoding.UTF8.GetBytes(message), key); 26 | 27 | Assert.AreEqual(32, signature.Length); 28 | Assert.AreEqual(expectedSignature, Convert.ToBase64String(signature)); 29 | 30 | signature = SecretKeyAuth.Sign(message, key); 31 | Assert.AreEqual(32, signature.Length); 32 | Assert.AreEqual(expectedSignature, Convert.ToBase64String(signature)); 33 | } 34 | 35 | [TestCategory("SecretKeyAuth")] 36 | [TestMethod] 37 | public void SecretKeyAuthOpenTest() 38 | { 39 | var key = Convert.FromBase64String("wYSsnapy7G9F+NTo/bVvIpnRv/ULd97XSMPLoe4+abM="); 40 | byte[] signature = Convert.FromBase64String("hQ4vOFX+pPJNhXxnbMfzAtLjSVeRBBGCOIjlNoIWvzA="); 41 | String message = "Hello, World!"; 42 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 43 | bool result = SecretKeyAuth.Verify(byteMessage, signature, key); 44 | Assert.IsTrue(result); 45 | } 46 | 47 | [TestCategory("SecretKeyAuth")] 48 | [TestMethod] 49 | public void SecretKeyAuthSignAndVerifyTest() 50 | { 51 | byte[] key = SecretKeyAuth.GenerateKey(); 52 | String message = "Hello, World!"; 53 | 54 | byte[] signature = SecretKeyAuth.Sign(System.Text.Encoding.UTF8.GetBytes(message), key); 55 | Assert.AreEqual(32, signature.Length); 56 | bool verification = SecretKeyAuth.Verify(System.Text.Encoding.UTF8.GetBytes(message), signature, key); 57 | Assert.IsTrue(verification); 58 | 59 | signature = SecretKeyAuth.Sign(message, key); 60 | Assert.AreEqual(32, signature.Length); 61 | verification = SecretKeyAuth.Verify(message, signature, key); 62 | Assert.IsTrue(verification); 63 | } 64 | 65 | [TestCategory("SecretKeyAuth")] 66 | [TestMethod] 67 | public void HmacSha256Test() 68 | { 69 | var key = SecretKeyAuth.GenerateKey(); 70 | string message = "Hello, World!"; 71 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 72 | var sig1 = SecretKeyAuth.SignHmacSha256(message, key); 73 | var sig2 = SecretKeyAuth.SignHmacSha256(byteMessage, key); 74 | 75 | // Verify the overload works 76 | Assert.AreEqual(Convert.ToBase64String(sig1), Convert.ToBase64String(sig2)); 77 | 78 | var result = SecretKeyAuth.VerifyHmacSha256(message, sig1, key); 79 | Assert.IsTrue(result); 80 | result = SecretKeyAuth.VerifyHmacSha256(message, sig2, key); 81 | Assert.IsTrue(result); 82 | 83 | result = SecretKeyAuth.VerifyHmacSha256(byteMessage, sig1, key); 84 | Assert.IsTrue(result); 85 | result = SecretKeyAuth.VerifyHmacSha256(byteMessage, sig2, key); 86 | Assert.IsTrue(result); 87 | } 88 | 89 | [TestCategory("SecretKeyAuth")] 90 | [TestMethod] 91 | public void HmacSha512Test() 92 | { 93 | var key = SecretKeyAuth.GenerateKey(); 94 | string message = "Hello, World!"; 95 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 96 | var sig1 = SecretKeyAuth.SignHmacSha512(message, key); 97 | var sig2 = SecretKeyAuth.SignHmacSha512(byteMessage, key); 98 | 99 | // Verify the overload works 100 | Assert.AreEqual(Convert.ToBase64String(sig1), Convert.ToBase64String(sig2)); 101 | 102 | var result = SecretKeyAuth.VerifyHmacSha512(message, sig1, key); 103 | Assert.IsTrue(result); 104 | result = SecretKeyAuth.VerifyHmacSha512(message, sig2, key); 105 | Assert.IsTrue(result); 106 | 107 | result = SecretKeyAuth.VerifyHmacSha512(byteMessage, sig1, key); 108 | Assert.IsTrue(result); 109 | result = SecretKeyAuth.VerifyHmacSha512(byteMessage, sig2, key); 110 | Assert.IsTrue(result); 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /Test/SecretStream.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class SecretStreamTest 9 | { 10 | [TestCategory("SecretStream")] 11 | [TestMethod] 12 | public void GenerateKeyTest() 13 | { 14 | Assert.AreEqual(32, SecretStream.GenerateKey().Length); 15 | } 16 | 17 | [TestCategory("SecretStream")] 18 | [TestMethod] 19 | public void GenerateHeaderTest() 20 | { 21 | Assert.AreEqual(24, SecretStream.GenerateHeader().Length); 22 | } 23 | 24 | [TestCategory("SecretStream")] 25 | [TestMethod] 26 | public void EncryptAndDecryptTest() 27 | { 28 | var key = SecretStream.GenerateKey(); 29 | var header = SecretStream.GenerateHeader(); 30 | var encrypter = new SecretStream(key, header, SecretStream.MODE_PUSH); 31 | var decrypter = new SecretStream(key, header, SecretStream.MODE_PULL); 32 | 33 | var message1 = "Hello, World!"; 34 | var message2 = "{ \"json\": \"data\" }"; 35 | var message3 = "Some more random messaging"; 36 | 37 | var ciphertext1 = encrypter.Push(message1); 38 | encrypter.Rekey(); 39 | var ciphertext2 = encrypter.Push(message2, SecretStream.TAG_PUSH); 40 | var ciphertext3 = encrypter.Push(message3, SecretStream.TAG_FINAL); 41 | 42 | int tag = -1; 43 | var d1 = decrypter.Pull(ciphertext1, out tag); 44 | Assert.AreEqual(tag, SecretStream.TAG_MESSAGE); 45 | decrypter.Rekey(); 46 | var d2 = decrypter.Pull(ciphertext2, out tag); 47 | Assert.AreEqual(tag, SecretStream.TAG_PUSH); 48 | var d3 = decrypter.Pull(ciphertext3, out tag); 49 | Assert.AreEqual(tag, SecretStream.TAG_FINAL); 50 | 51 | // Verify that the original string and the decrypted string are equivalent 52 | Assert.AreEqual(Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(message1)), Convert.ToBase64String(d1)); 53 | Assert.AreEqual(Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(message2)), Convert.ToBase64String(d2)); 54 | Assert.AreEqual(Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(message3)), Convert.ToBase64String(d3)); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Test/ShortHashTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class ShortHashTest 9 | { 10 | [TestCategory("ShortHash")] 11 | [TestMethod] 12 | public void GenerateKeyTest() 13 | { 14 | Assert.AreEqual(16, ShortHash.GenerateKey().Length); 15 | } 16 | 17 | [TestCategory("ShortHash")] 18 | [TestMethod] 19 | public void GenerateHashTest() 20 | { 21 | string message = "Hello, World!"; 22 | var key = ShortHash.GenerateKey(); 23 | var hash = ShortHash.Hash(message, key); 24 | Assert.AreEqual(8, hash.Length); 25 | 26 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 27 | hash = ShortHash.Hash(byteMessage, key); 28 | Assert.AreEqual(8, hash.Length); 29 | } 30 | 31 | [TestCategory("ShortHash")] 32 | [TestMethod] 33 | public void CompareHashTest() 34 | { 35 | // Test against known values generated from another libsodium implementation 36 | string message = "Charles R. Portwood II"; 37 | var expected = Convert.FromBase64String("docyE6GyPUA="); 38 | var key = Convert.FromBase64String("4f7fFH5QJtm/7nqinCcRtA=="); 39 | var hash = ShortHash.Hash(message, key); 40 | Assert.AreEqual(8, hash.Length); 41 | Assert.AreEqual(Convert.ToBase64String(expected), Convert.ToBase64String(hash)); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Test/StreamEncryptionTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class StreamEncryptionTest 9 | { 10 | [TestCategory("StreamEncryption")] 11 | [TestMethod] 12 | public void GenerateKeyTest() 13 | { 14 | Assert.AreEqual(32, StreamEncryption.GenerateKey().Length); 15 | } 16 | 17 | [TestCategory("StreamEncryption")] 18 | [TestMethod] 19 | public void GenerateNonceTest() 20 | { 21 | Assert.AreEqual(24, StreamEncryption.GenerateNonce().Length); 22 | } 23 | 24 | [TestCategory("StreamEncryption :: XSalsa20")] 25 | [TestMethod] 26 | public void GenerateNonceXSalsa20Test() 27 | { 28 | Assert.AreEqual(24, StreamEncryption.GenerateNonceXSalsa20().Length); 29 | } 30 | 31 | [TestCategory("StreamEncryption :: ChaCha20")] 32 | [TestMethod] 33 | public void GenerateNonceChaCha20Test() 34 | { 35 | Assert.AreEqual(8, StreamEncryption.GenerateNonceChaCha20().Length); 36 | } 37 | 38 | 39 | [TestCategory("StreamEncryption :: Salsa20")] 40 | [TestMethod] 41 | public void GenerateNonceSalsa20Test() 42 | { 43 | Assert.AreEqual(8, StreamEncryption.GenerateNonceSalsa20().Length); 44 | } 45 | 46 | 47 | [TestCategory("StreamEncryption :: XSalsa20")] 48 | [TestMethod] 49 | public void XSalsa20Test() 50 | { 51 | var key = StreamEncryption.GenerateKey(); 52 | var nonce = StreamEncryption.GenerateNonce(); 53 | string message = "Hello, World!"; 54 | 55 | var cipherText = StreamEncryption.Encrypt(message, nonce, key); 56 | var decrypted = StreamEncryption.Decrypt(cipherText, nonce, key); 57 | Assert.AreEqual(message, System.Text.Encoding.UTF8.GetString(decrypted)); 58 | 59 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 60 | cipherText = StreamEncryption.Encrypt(byteMessage, nonce, key); 61 | decrypted = StreamEncryption.Decrypt(cipherText, nonce, key); 62 | Assert.AreEqual(Convert.ToBase64String(byteMessage), Convert.ToBase64String(decrypted)); 63 | 64 | cipherText = StreamEncryption.EncryptXSalsa20(message, nonce, key); 65 | decrypted = StreamEncryption.DecryptXSalsa20(cipherText, nonce, key); 66 | Assert.AreEqual(message, System.Text.Encoding.UTF8.GetString(decrypted)); 67 | 68 | byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 69 | cipherText = StreamEncryption.EncryptXSalsa20(byteMessage, nonce, key); 70 | decrypted = StreamEncryption.DecryptXSalsa20(cipherText, nonce, key); 71 | Assert.AreEqual(Convert.ToBase64String(byteMessage), Convert.ToBase64String(decrypted)); 72 | } 73 | 74 | 75 | [TestCategory("StreamEncryption :: Salsa20")] 76 | [TestMethod] 77 | public void Salsa20Test() 78 | { 79 | var key = StreamEncryption.GenerateKey(); 80 | var nonce = StreamEncryption.GenerateNonceSalsa20(); 81 | string message = "Hello, World!"; 82 | 83 | var cipherText = StreamEncryption.EncryptSalsa20(message, nonce, key); 84 | var decrypted = StreamEncryption.DecryptSalsa20(cipherText, nonce, key); 85 | Assert.AreEqual(message, System.Text.Encoding.UTF8.GetString(decrypted)); 86 | 87 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 88 | cipherText = StreamEncryption.EncryptSalsa20(byteMessage, nonce, key); 89 | decrypted = StreamEncryption.EncryptSalsa20(cipherText, nonce, key); 90 | Assert.AreEqual(Convert.ToBase64String(byteMessage), Convert.ToBase64String(decrypted)); 91 | } 92 | 93 | 94 | [TestCategory("StreamEncryption :: ChaCha20")] 95 | [TestMethod] 96 | public void ChaCha20Test() 97 | { 98 | var key = StreamEncryption.GenerateKey(); 99 | var nonce = StreamEncryption.GenerateNonceChaCha20(); 100 | string message = "Hello, World!"; 101 | 102 | var cipherText = StreamEncryption.EncryptChaCha20(message, nonce, key); 103 | var decrypted = StreamEncryption.DecryptChaCha20(cipherText, nonce, key); 104 | Assert.AreEqual(message, System.Text.Encoding.UTF8.GetString(decrypted)); 105 | 106 | byte[] byteMessage = System.Text.Encoding.UTF8.GetBytes(message); 107 | cipherText = StreamEncryption.EncryptChaCha20(byteMessage, nonce, key); 108 | decrypted = StreamEncryption.DecryptChaCha20(cipherText, nonce, key); 109 | Assert.AreEqual(Convert.ToBase64String(byteMessage), Convert.ToBase64String(decrypted)); 110 | } 111 | 112 | 113 | [TestCategory("StreamEncryption :: XSalsa20")] 114 | [TestMethod] 115 | public void XSalsa20SodiumTest() 116 | { 117 | var firstkey = new byte[] 118 | { 119 | 0x1b, 0x27, 0x55, 0x64, 0x73, 0xe9, 0x85, 0xd4, 0x62, 0xcd, 0x51, 120 | 0x19, 0x7a, 0x9a, 0x46, 0xc7, 0x60, 0x09, 0x54, 0x9e, 0xac, 0x64, 121 | 0x74, 0xf2, 0x06, 0xc4, 0xee, 0x08, 0x44, 0xf6, 0x83, 0x89 122 | }; 123 | 124 | var nonce = new byte[] 125 | { 126 | 0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73, 127 | 0xcd, 0x62, 0xbd, 0xa8, 0x75, 0xfc, 0x73, 0xd6, 128 | 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37 129 | }; 130 | 131 | var m = new byte[] 132 | { 133 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135 | 0, 0, 0, 0, 0, 0, 0, 0, 0xbe, 0x07, 0x5f, 0xc5, 136 | 0x3c, 0x81, 0xf2, 0xd5, 0xcf, 0x14, 0x13, 0x16, 0xeb, 0xeb, 0x0c, 0x7b, 137 | 0x52, 0x28, 0xc5, 0x2a, 0x4c, 0x62, 0xcb, 0xd4, 0x4b, 0x66, 0x84, 0x9b, 138 | 0x64, 0x24, 0x4f, 0xfc, 0xe5, 0xec, 0xba, 0xaf, 0x33, 0xbd, 0x75, 0x1a, 139 | 0x1a, 0xc7, 0x28, 0xd4, 0x5e, 0x6c, 0x61, 0x29, 0x6c, 0xdc, 0x3c, 0x01, 140 | 0x23, 0x35, 0x61, 0xf4, 0x1d, 0xb6, 0x6c, 0xce, 0x31, 0x4a, 0xdb, 0x31, 141 | 0x0e, 0x3b, 0xe8, 0x25, 0x0c, 0x46, 0xf0, 0x6d, 0xce, 0xea, 0x3a, 0x7f, 142 | 0xa1, 0x34, 0x80, 0x57, 0xe2, 0xf6, 0x55, 0x6a, 0xd6, 0xb1, 0x31, 0x8a, 143 | 0x02, 0x4a, 0x83, 0x8f, 0x21, 0xaf, 0x1f, 0xde, 0x04, 0x89, 0x77, 0xeb, 144 | 0x48, 0xf5, 0x9f, 0xfd, 0x49, 0x24, 0xca, 0x1c, 0x60, 0x90, 0x2e, 0x52, 145 | 0xf0, 0xa0, 0x89, 0xbc, 0x76, 0x89, 0x70, 0x40, 0xe0, 0x82, 0xf9, 0x37, 146 | 0x76, 0x38, 0x48, 0x64, 0x5e, 0x07, 0x05 147 | }; 148 | 149 | var actual = StreamEncryption.Encrypt(m, nonce, firstkey); 150 | Assert.AreEqual(163, actual.Length); 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Test/Test_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charlesportwoodii/libsodium-uwp/5bb57ba8c60f0d6ec95cf88fe344df4fd4728149/Test/Test_TemporaryKey.pfx -------------------------------------------------------------------------------- /Test/UnitTestApp.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | -------------------------------------------------------------------------------- /Test/UnitTestApp.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.ApplicationModel; 7 | using Windows.ApplicationModel.Activation; 8 | using Windows.Foundation; 9 | using Windows.Foundation.Collections; 10 | using Windows.UI.Xaml; 11 | using Windows.UI.Xaml.Controls; 12 | using Windows.UI.Xaml.Controls.Primitives; 13 | using Windows.UI.Xaml.Data; 14 | using Windows.UI.Xaml.Input; 15 | using Windows.UI.Xaml.Media; 16 | using Windows.UI.Xaml.Navigation; 17 | 18 | namespace Test 19 | { 20 | /// 21 | /// Provides application-specific behavior to supplement the default Application class. 22 | /// 23 | sealed partial class App : Application 24 | { 25 | /// 26 | /// Initializes the singleton application object. This is the first line of authored code 27 | /// executed, and as such is the logical equivalent of main() or WinMain(). 28 | /// 29 | public App() 30 | { 31 | this.InitializeComponent(); 32 | this.Suspending += OnSuspending; 33 | } 34 | 35 | /// 36 | /// Invoked when the application is launched normally by the end user. Other entry points 37 | /// will be used such as when the application is launched to open a specific file. 38 | /// 39 | /// Details about the launch request and process. 40 | protected override void OnLaunched(LaunchActivatedEventArgs e) 41 | { 42 | 43 | #if DEBUG 44 | if (System.Diagnostics.Debugger.IsAttached) 45 | { 46 | this.DebugSettings.EnableFrameRateCounter = true; 47 | } 48 | #endif 49 | 50 | Frame rootFrame = Window.Current.Content as Frame; 51 | 52 | // Do not repeat app initialization when the Window already has content, 53 | // just ensure that the window is active 54 | if (rootFrame == null) 55 | { 56 | // Create a Frame to act as the navigation context and navigate to the first page 57 | rootFrame = new Frame(); 58 | 59 | rootFrame.NavigationFailed += OnNavigationFailed; 60 | 61 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 62 | { 63 | //TODO: Load state from previously suspended application 64 | } 65 | 66 | // Place the frame in the current Window 67 | Window.Current.Content = rootFrame; 68 | } 69 | 70 | Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI(); 71 | 72 | // Ensure the current window is active 73 | Window.Current.Activate(); 74 | 75 | Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.Run(e.Arguments); 76 | } 77 | 78 | /// 79 | /// Invoked when Navigation to a certain page fails 80 | /// 81 | /// The Frame which failed navigation 82 | /// Details about the navigation failure 83 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e) 84 | { 85 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName); 86 | } 87 | 88 | /// 89 | /// Invoked when application execution is being suspended. Application state is saved 90 | /// without knowing whether the application will be terminated or resumed with the contents 91 | /// of memory still intact. 92 | /// 93 | /// The source of the suspend request. 94 | /// Details about the suspend request. 95 | private void OnSuspending(object sender, SuspendingEventArgs e) 96 | { 97 | var deferral = e.SuspendingOperation.GetDeferral(); 98 | //TODO: Save application state and stop any background activity 99 | deferral.Complete(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Test/UtilitiesTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sodium; 3 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 4 | 5 | namespace Test 6 | { 7 | [TestClass] 8 | public class UtilitiesTest 9 | { 10 | [TestMethod] 11 | public void IncrementTest() 12 | { 13 | var nonce = Convert.FromBase64String("djaDJesnKwzeBvqy8BCz9ezVqAVwnpUF"); 14 | var inc = Utilities.Increment(nonce); 15 | Assert.AreNotEqual(Convert.ToBase64String(nonce), Convert.ToBase64String(inc)); 16 | } 17 | 18 | [TestMethod] 19 | public void CompareTest() 20 | { 21 | var a = new byte[] 22 | { 23 | 0xcd, 0x7c, 0xf6, 0x7b, 0xe3, 0x9c, 0x79, 0x4a 24 | }; 25 | 26 | var b = new byte[] 27 | { 28 | 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 29 | }; 30 | 31 | var c = new byte[] 32 | { 33 | 0xcd, 0x7c, 0xf6, 0x7b, 0xe3, 0x9c, 0x79, 0x4a 34 | }; 35 | 36 | var d = new byte[] 37 | { 38 | 0xcd, 0x7c, 0xf6, 0x7b, 0xe3, 0x9c 39 | }; 40 | 41 | Assert.AreEqual(false, Utilities.Compare(a, b)); 42 | Assert.AreEqual(true, Utilities.Compare(a, c)); 43 | Assert.AreEqual(false, Utilities.Compare(a, d)); 44 | Assert.AreEqual(false, Utilities.Compare(d, b)); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Test/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "6.1.5" 4 | }, 5 | "frameworks": { 6 | "uap10.0.10240": {} 7 | }, 8 | "runtimes": { 9 | "win10-arm": {}, 10 | "win10-arm-aot": {}, 11 | "win10-x86": {}, 12 | "win10-x86-aot": {}, 13 | "win10-x64": {}, 14 | "win10-x64-aot": {} 15 | } 16 | } -------------------------------------------------------------------------------- /docs/Core.md: -------------------------------------------------------------------------------- 1 | # Core 2 | 3 | Core methods for this library. 4 | 5 | ## Sodium Version 6 | 7 | __Namespace:__ _Sodium.Core_ 8 | 9 | ```C# 10 | public static String SodiumVersionString() 11 | ``` 12 | 13 | This function returns the version number of the `libsodium` library itself. The current version is `1.0.11`. 14 | 15 | > Note this will _not_ return the version of `libsodium-uwp`. 16 | 17 | ## Generating Random Data 18 | 19 | __Namespace:__ _Sodium.Core_ 20 | 21 | ```C# 22 | public static byte[] GetRandomBytes(int count) 23 | ``` 24 | 25 | The `GetRandomBytes()` method takes a integer `count`, and produces an unpredictable sequence of bytes. This method is suitable for generating keys, salts, and nonces. 26 | 27 | > This method uses an adapted version of `randombytes_sysrandom.c` to generate random bytes. As `RtlGenRandom` is not available for mobile targets, this library uses `Windows.Security.Cryptography.CryptographicBuffer.GenerateRandom()` instead to securely generate random data. 28 | 29 | __Note:__ In classes where appropriate, there are `GenerateKey()` and/or `GenerateNonce()` methods that return a byte array of the correct size. 30 | 31 | ## Generate a Random Number 32 | 33 | __Namespace:__ _Sodium.Core_ 34 | 35 | ```C# 36 | public static int GetRandomNumber(int upper_bound) 37 | ``` 38 | 39 | This method returns an unpredictable valued between 0 and `upper_bound`. 40 | 41 | > The maximum possible input for `upper_bound` is: `INT_MAX` (2147483647) -------------------------------------------------------------------------------- /docs/CryptoHash.md: -------------------------------------------------------------------------------- 1 | # CryptoHash 2 | 3 | Common hashing functions. 4 | 5 | ## Hash 6 | 7 | __Namespace:__ _Sodium.CryptoHash_ 8 | 9 | ```C# 10 | public static byte[] Sodium.CryptoHash.Hash(byte[] message) 11 | public static byte[] Sodium.CryptoHash.Hash(String message) 12 | ``` 13 | 14 | `Hash` implemented the default hashing algorithm provided by libsodium. Presently this is returns a SHA 512 byte encoding of a given message. The output hash will be a 64 byte array. 15 | 16 | _This method implements `crypto_hash`._ 17 | 18 | ## Sha256 19 | 20 | __Namespace:__ _Sodium.CryptoHash_ 21 | 22 | ```C# 23 | public static byte[] Sodium.CryptoHash.Sha256(byte[] message) 24 | public static byte[] Sodium.CryptoHash.Sha256(String message) 25 | ``` 26 | 27 | `Sha256` returns a SHA 256 byte encoding of a given message. The output hash will be a 32 byte array. 28 | 29 | _This method implements `crypto_hash_sha256`_. 30 | 31 | ## Sha512 32 | 33 | __Namespace:__ _Sodium.CryptoHash_ 34 | 35 | ```C# 36 | public static byte[] Sodium.CryptoHash.Sha512(byte[] message) 37 | public static byte[] Sodium.CryptoHash.Sha512(String message) 38 | ``` 39 | 40 | `Sha512` returns a SHA 512 byte encoding of a given message. The output hash will be a 64 byte array. 41 | 42 | _This method implements `crypto_hash_sha512`._ -------------------------------------------------------------------------------- /docs/GenericHash.md: -------------------------------------------------------------------------------- 1 | # Generic Hashing 2 | 3 | GenericHash computes a fixed length fingerprint for an arbitarily long message. This method is useful for computing hashes for: 4 | 5 | - File integrity checks 6 | - Creating unique identifies to index arbitarily long data. 7 | 8 | ## Generate Key 9 | 10 | __Namespace:__ _Sodium.GenericHash_ 11 | 12 | ```C# 13 | public static byte[] Sodium.GenericHash.GenerateKey() 14 | ``` 15 | 16 | Generates a 64 byte key 17 | 18 | ## Hashing 19 | 20 | __Namespace:__ _Sodium.GenericHash_ 21 | 22 | ```C# 23 | public static byte[] Sodium.GenericHash.Hash(byte[] message) 24 | public static byte[] Sodium.GenericHash.Hash(String message) 25 | public static byte[] Sodium.GenericHash.Hash(byte[] message, byte[] key) 26 | public static byte[] Sodium.GenericHash.Hash(String message, byte[] key) 27 | public static byte[] Sodium.GenericHash.Hash(byte[] message, byte[] key, int bytes) 28 | public static byte[] Sodium.GenericHash.Hash(String message, byte[] key, int bytes) 29 | ``` 30 | 31 | The `Hash()` generates a fingerprint of a given `message` using an optional key, and produces n `bytes` of output. 32 | 33 | The `key` should be between 16, and 64 bytes (or `null`). 34 | 35 | The `bytes` should be between 16 and 64 bytes. The minimum recommended length for `bytes`(and the length if not specified) is 32. 36 | 37 | _Internally this method uses `crypto_generichash`._ 38 | 39 | ## Multi-Part Hashing (Stream) 40 | 41 | Large files or streams can also be hashed using `GenericHash`, `GenericHashAlgorithmProvider`, and `GenericHashAlgorithmNames`. The API for `GenericHash` is identical to the API provided by `MacAlgorithmProvider` and `HashAlgorithmProvider`. The `key` and `byte` requirements are identical to those outlined by `GenericHash.Hash`. 42 | 43 | ### Large block example 44 | 45 | ```C# 46 | GenericHashAlgorithmProvider provider = GenericHashAlgorithmProvider.OpenAlgorithm(GenericHashAlgorithmNames.Blake2); 47 | var key = GenericHash.GenerateKey(); 48 | 49 | GenericHash hash = provider.CreateHash(); 50 | // GenericHash hash = provider.CreateHash(key); 51 | // GenericHash hash = provider.CreateHash(key, 64); 52 | 53 | IBuffer data = CryptographicBuffer.ConvertStringToBinary("A really really long text string...", BinaryStringEncoding.Utf8); 54 | hash.Append(data); 55 | 56 | byte[] final = hash.GetValueAndReset(); 57 | ``` 58 | 59 | ### Streaming example 60 | 61 | ```C# 62 | GenericHashAlgorithmProvider provider = GenericHashAlgorithmProvider.OpenAlgorithm(GenericHashAlgorithmNames.Blake2); 63 | var stream = await file.OpenStreamForReadAsync(); 64 | var inputStream = stream.AsInputStream(); 65 | uint capacity = 100000000; 66 | Windows.Storage.Streams.Buffer buffer = new Windows.Storage.Streams.Buffer(capacity); 67 | GenericHash hash = provider.CreateHash(); 68 | 69 | while (buffer.Length > 0) 70 | { 71 | await inputStream.ReadAsync(buffer, capacity, InputStreamOptions.None); 72 | hash.Append(buffer); 73 | } 74 | 75 | string hashText = CryptographicBuffer.EncodeToHexString(hash.GetValueAndReset()).ToUpper(); 76 | ``` 77 | 78 | _Internally this method uses `crypto_generichash_init`, `crypto_generichash_update`, and `crypto_generichash_final`._ 79 | 80 | # Algorithm Details 81 | - Blake2 -------------------------------------------------------------------------------- /docs/HMAC-SHA2.md: -------------------------------------------------------------------------------- 1 | # HMAC-SHA-2 2 | 3 | Keyed message authentication using HMAC-SHA-256, HMAC-SHA-512. 4 | 5 | > Truncated HMAC-SHA-512 (HMAC-SHA512/256) is provided by `SecretKeyAuth.Sign` and `SecretKeyAuth.Verify`, outlined in [SecretKeyAuth](SecretKeyAuth.md) 6 | 7 | ## HMAC-SHA-256 8 | 9 | ### Sign 10 | 11 | __Namespace:__ _Sodium.SecretKeyAuth_ 12 | 13 | ```C# 14 | public static byte[] SignHmacSha256(byte[] message, byte[] key); 15 | public static byte[] SignHmacSha256(string message, byte[] key); 16 | ``` 17 | 18 | This method signs a given `message` with a 32 byte `key`, and will return a 32 byte signature. 19 | 20 | _Internally this method uses `crypto_auth_hmacsha256`._ 21 | 22 | ### Verify 23 | 24 | __Namespace:__ _Sodium.SecretKeyAuth_ 25 | 26 | ```C# 27 | public static bool VerifyHmacSha256(byte[] message, byte[] signature, byte[] key); 28 | public static bool VerifyHmacSha256(string message, byte[] signature, byte[] key); 29 | ``` 30 | 31 | This method verifies a a `message` against a 32 byte `signature` generated by `SignHmacSha256` using a 32 byte `key`. This method will return `true` of the signature is valid, and `false` otherwise. 32 | 33 | _Internally this method uses `crypto_auth_hmacsha256_verify`._ 34 | 35 | ## HMAC-SHA-512 36 | 37 | ### Sign 38 | 39 | __Namespace:__ _Sodium.SecretKeyAuth_ 40 | 41 | ```C# 42 | public static byte[] SignHmacSha512(byte[] message, byte[] key); 43 | public static byte[] SignHmacSha512(string message, byte[] key); 44 | ``` 45 | 46 | This method signs a given `message` with a 32 byte `key`, and will return a 64 byte signature. 47 | 48 | _Internally this method uses `crypto_auth_hmacsha512`._ 49 | 50 | ### Verify 51 | 52 | __Namespace:__ _Sodium.SecretKeyAuth_ 53 | 54 | ```C# 55 | public static bool VerifyHmacSha512(byte[] message, byte[] signature, byte[] key); 56 | public static bool VerifyHmacSha512(string message, byte[] signature, byte[] key); 57 | ``` 58 | 59 | This method verifies a a `message` against a 64 byte `signature` generated by `SignHmacSha512` using a 32 byte `key`. This method will return `true` of the signature is valid, and `false` otherwise. 60 | 61 | _Internally this method uses `crypto_auth_hmacsha512_verify`._ -------------------------------------------------------------------------------- /docs/KDF.md: -------------------------------------------------------------------------------- 1 | # Key Derivation Functions 2 | 3 | While not part of libsodium itself, key-derivation functions are useful for generated keys from sources such as passwords or hashes. 4 | 5 | ## Password-based Key Derivation Function 2 (PBKDF2) 6 | 7 | https://tools.ietf.org/html/rfc6070 8 | 9 | __Namespace:__ _Sodium.KDF_ 10 | 11 | ```C# 12 | public static byte[] Sodium.KDF.PBKDF2(KeyDerivationAlgorithmNames|String algorithm, string password, byte[] salt, int iterationCount, int targetSize); 13 | public static byte[] Sodium.KDF.PBKDF2(KeyDerivationAlgorithmNames|String algorithm, string password, String salt, int iterationCount, int targetSize); 14 | ``` 15 | 16 | PBKDF2 takes 5 parameters: 17 | 18 | 1. The string `password`, which may be of any length 19 | 2. `salt`, either generated by `Sodium.Core.GetRandomBytes(n)` or by converting a plaintext salt `System.Text.Encoding.ASCII.GetBytes("salt")` 20 | 3. The number of iterations (`iterationCount`) that the algorithm should run for. 21 | 4. The `targetSize` of the output. 22 | 5. A `KeyDerivationAlgorithmNames `algorithm, as defined from https://msdn.microsoft.com/en-us/library/windows/apps/windows.security.cryptography.core.keyderivationalgorithmnames.aspx. 23 | 24 | ```C# 25 | KeyDerivationAlgorithmNames.Pbkdf2Md5 26 | KeyDerivationAlgorithmNames.Pbkdf2Sha1 27 | KeyDerivationAlgorithmNames.Pbkdf2Sha256 28 | KeyDerivationAlgorithmNames.Pbkdf2Sha384 29 | KeyDerivationAlgorithmNames.Pbkdf2Sha384 30 | ``` 31 | 32 | ### Example 33 | 34 | ```C# 35 | // PBKDF 2 Example from RFC607 36 | var p = "password"; 37 | var s = System.Text.Encoding.ASCII.GetBytes("salt"); 38 | var c = 1; 39 | var dkLen = 20; 40 | 41 | var result = Sodium.KDF.PBKDF2(KeyDerivationAlgorithmNames.Pbkdf2Sha1, p, s, c, dkLen); 42 | 43 | // Additional example 44 | p = "correct horse battery staple"; 45 | s = Sodium.Core.GetRandomBytes(64); 46 | c = 10000; 47 | dkLen = 32; 48 | result = Sodium.KDF.PBKDF2(KeyDerivationAlgorithmNames.Pbkdf2Sha256, p, s, c, dkLen); 49 | ``` 50 | 51 | ## HMAC-based Extract-and-Expand Key Derivation Function (HKDF) 52 | 53 | https://tools.ietf.org/html/rfc5869 54 | 55 | __Namespace:__ _Sodium.KDF_ 56 | 57 | ```C# 58 | public static byte[] Sodium.KDF.HKDF(MacAlgorithmNames|String algorithm, byte[] ikm, byte[] salt, byte[] info, int outputLength) 59 | public static byte[] Sodium.KDF.HKDF(MacAlgorithmNames|String algorithm, byte[] ikm, byte[] salt, String info, int outputLength) 60 | ``` 61 | 62 | HKDF takes 5 parameters: 63 | 64 | 1. A `MacAlgorithmNames` algorithm as defined from https://msdn.microsoft.com/en-us/library/windows/apps/windows.security.cryptography.core.macalgorithmnames.aspx. 65 | 66 | ```C# 67 | MacAlgorithmNames.HmacMd5 68 | MacAlgorithmNames.HmacSha1 69 | MacAlgorithmNames.HmacSha256 70 | MacAlgorithmNames.HmacSha384 71 | MacAlgorithmNames.HmacSha512 72 | ``` 73 | 74 | 2. The initial keying material `ikm` represented in bytes. 75 | 3. The additional authentication information `info`. 76 | 4. The desired `outputLength` represented as an integer. If `0` is set, the `outputLength` will be set to the algorithm length. 77 | 5. A byte `salt`. 78 | 79 | ### Example 80 | ```C# 81 | var salt = Sodium.Core.GetRandomBytes(32); 82 | var ikm = Sodium.Core.GetRandomBytes(32); 83 | var algorithm = MacAlgorithmNames.HmacSha256; 84 | var info = System.Text.Encoding.UTF8.GetBytes("test"); 85 | 86 | var result = Sodium.KDF.HKDF(algorithm, ikm, info, salt, 32); 87 | ``` 88 | 89 | ## HSalsa20 (intermediate key generation) 90 | 91 | __Namespace:__ _Sodium.KDF_ 92 | 93 | ```C# 94 | public static byte[] Sodium.KDF.HSalsa20(byte[] in, byte[] k, byte[] c); 95 | ``` 96 | 97 | _Internally this function uses `crypto_core_hsalsa20`._ 98 | 99 | ## Argon2i Key Derivation 100 | 101 | __Namespace:__ _Sodium.KDF_ 102 | 103 | ```C# 104 | public static byte[] Sodium.KDF.Argon2i(string password, PasswordHashOptions options) 105 | public static byte[] Sodium.KDF.Argon2i(string password, byte[] salt, PasswordHashOptions options) 106 | ``` 107 | 108 | This method will generate a 32 byte key using Argon2i provided a string `password` and `PasswordHashOptions` `options`. For more information about `PasswordHashOptions`, and acceptable parameters, see [PasswordHash](PasswordHash.md); 109 | 110 | If a salt is not provided, a 16 byte salt will be generated. 111 | 112 | _Internally this method uses `crypto_pwhash`._ 113 | 114 | ## Scrypt Key Derivation 115 | 116 | __Namespace:__ _Sodium.KDF_ 117 | 118 | ```C# 119 | public static byte[] Sodium.KDF.Scrypt(string password, PasswordHashOptions options) 120 | public static byte[] Sodium.KDF.Scrypt(string password, byte[] salt, PasswordHashOptions options) 121 | ``` 122 | 123 | This method will generate a 32 byte key using Scrypt provided a string `password` and `PasswordHashOptions` `options`. For more information about `PasswordHashOptions`, and acceptable parameters, see [PasswordHash](PasswordHash.md); 124 | 125 | If a salt is not provided, a 32 byte salt will be generated. 126 | 127 | _Internally this method uses `crypto_pwhash_scryptsalsa208sha256`._ -------------------------------------------------------------------------------- /docs/KeyPair.md: -------------------------------------------------------------------------------- 1 | # KeyPair 2 | 3 | __Namespace:__ _Sodium_ 4 | This class represents a `libsodium-uwp` key pair, and has the following properties: 5 | 6 | ```C# 7 | kp.Public; 8 | kp.Secret; 9 | ``` 10 | -------------------------------------------------------------------------------- /docs/OneTimeAuth.md: -------------------------------------------------------------------------------- 1 | # One Time Authentication 2 | 3 | One-time authentication in Sodium uses Poly1305, a Wegman-Carter authenticator designed by D. J. Bernstein. 4 | 5 | OTA takes a string message, and a 32 byte key and produces a 16 byte authentication tag that authentications the message in such a way that an adversary has a negligible chance of producing a valid tag for an inauthentiic message. 6 | 7 | > Keys should _never_ be reused, even with different message. 8 | 9 | ## Example 10 | 11 | ```C# 12 | string message = "Hello, World!"; 13 | var key = OneTimeAuth.GenerateKey(); 14 | 15 | // Get the authentication code 16 | var signature = OneTimeAuth.Sign(message, key); 17 | 18 | if (OneTimeAuth.Verify(message, signature, key)) { 19 | // message is ok 20 | } 21 | ``` 22 | 23 | ## Sign 24 | 25 | __Namespace:__ _Sodium.OneTimeAuth_ 26 | 27 | ```C# 28 | public static byte[] Sodium.OneTimeAuth.Sign(byte[] message, byte[] key); 29 | public static byte[] Sodium.OneTimeAuth.Sign(string message, byte[] key); 30 | ``` 31 | 32 | `Sign` takes a `message` and a 32 byte `key`, and produces a 16 byte authentication tag. 33 | 34 | _Internally this method uses `crypto_onetimeauth`._ 35 | 36 | ## Verify 37 | 38 | ```C# 39 | public static bool Sodium.OneTimeAuth(byte[] message, byte[] signature, byte[] key); 40 | public static bool Sodium.OneTimeAuth(String message, byte[] signature, byte[] key); 41 | ``` 42 | 43 | Authentication tags generated by `OneTimeAuth.Sign()` can be verified using this method, which accepts the original `message`, the 16 byte `signature`, and the 32 byte `key` used to authenticate the message. This method will return `true` if the `signature` is valid for `message`, and `false` otherwise. 44 | 45 | _Internally this method uses `crypto_onetimeauth_verify`._ 46 | # Algorithm Details 47 | - Poly 1305 48 | -------------------------------------------------------------------------------- /docs/PasswordHash.md: -------------------------------------------------------------------------------- 1 | # Password Hashing 2 | 3 | libsodium-uwp offers three password hashing algorithms: Argon2i, Argon2id, and Scrypt. Access to all hashing algorithms are available through a single method call 4 | 5 | ## Argon2i & Argon2id 6 | 7 | Argon2, the recommended password hashing algorithm by the Password Hashing Competition, is a modern algorithm for securely hashing passwords. Argon2 addresses several key downsides of existing algorithms in that it is designed for the highest memory filling rate, and effective use multiple computing units while still providing defense against tradeoff attacks. Unlike Bcrypt, which just takes a single cost factor, Argon2 is parameterized by three distinct factors: 8 | 9 | - A memory cost that defines memory usage of the algorithm 10 | - A time cost that defines the execution time of the algorithm and the number of iterations 11 | - And a parallelism factor, which defines the number of parallel threads 12 | 13 | Libsodium's Argon2i & Argon2id implementation exposes the time and cost factor. 14 | 15 | ## Scrypt 16 | 17 | As a conservative alternative to Argon2, Sodium provides an implementation of the Scrypt password hashing function. 18 | 19 | ## Password Hashing Options 20 | 21 | Options can be summarized by the following structure for Argon2i, Argon2id, and Scrypt 22 | 23 | ```C# 24 | var options = PasswordHash.CreateOptions(int memory, int time); 25 | ``` 26 | 27 | > Avoid calling `new PasswordHashOptions { }` directly. Use the wrapper function. 28 | 29 | The recommended minimum values are outlined below: 30 | 31 | __Argon2i & Argon2id__ 32 | 33 | For Argon2i and Argon2id, the `time_cost` represents the number of iterations, and _must_ be greater than 3. The `memory_cost` factor is represented in `MiB`. The default `memory_cost` is 16384 MiB 34 | 35 | ```C# 36 | time_cost = 3, 37 | memory_cost = 1<<14 38 | ``` 39 | 40 | __Scrypt__ 41 | 42 | For Scrypt, the `time_cost` represents the number of iterations, and the `memory_cost` factor is represented in `MiB`. 43 | 44 | ```C# 45 | time_cost = 512, 46 | memory_cost = 1<<14 47 | ``` 48 | 49 | ## Algorithm Selection 50 | 51 | The algorithm can be selected using the constants provided by `PasswordHash`. By default passwords will be hashed using `Password.Argon2id`. 52 | 53 | ```C# 54 | PasswordHash.Argon2i // Argon2i 55 | PasswordHash.Argon2id // Argon2id 56 | PasswordHash.Scrypt // Scrypt 57 | ``` 58 | 59 | ## Hashing passwords 60 | 61 | __Namespace:__ _Sodium.PasswordHash_ 62 | 63 | ```C# 64 | public static String Sodium.PasswordHash.Hash(String password, PasswordHashOptions options, int algorithm = Password.Argon2id) 65 | ``` 66 | 67 | _Internally this method will use either `crypto_pwhash_scryptsalsa208sha256_str` or `crypto_pwhash_str_alg`, depending upon the algorithm set._ 68 | 69 | ## Verifying passwords 70 | 71 | __Namespace:__ _Sodium.PasswordHash_ 72 | 73 | ```C# 74 | public static bool Sodium.PasswordHash.Verify(String hash, String password) 75 | ``` 76 | 77 | _Internally this method will use either `crypto_pwhash_scryptsalsa208sha256_str_verify` or `crypto_pwhash_str_verify`, depending upon the algorithm set._ 78 | 79 | ## Determine if password needs to be rehashed 80 | 81 | __Namespace:__ _Sodium.PasswordHash_ 82 | 83 | ```C# 84 | public static bool Sodium.PasswordHash.NeedsRehash(String hash, PasswordHashOptions options); 85 | ``` 86 | 87 | _Internally this method uses `crypto_pwhash_str_needs_rehash`. Note that this method only works with `Password.Argon2i` and `Password.Argon2id`._ -------------------------------------------------------------------------------- /docs/PublicKeyAuth.md: -------------------------------------------------------------------------------- 1 | # Public Key signatures 2 | 3 | Public key signatures are used to sign a given message which can then be verified by a third party. 4 | 5 | > Note: Verifiers need to already know and ultimatly trust the public key before they can verify it. 6 | 7 | ## Generate KeyPair 8 | 9 | __Namespace:__ _Sodium.PublicKeyAuth_ 10 | 11 | ```C# 12 | public static KeyPair Sodium.PublicKeyAuth.GenerateKeyPair() 13 | public static KeyPair Sodium.PublicKeyAuth.GenerateKeyPair(byte[] seed) 14 | ``` 15 | 16 | A new key pair can be generated by calling `GenerateKeyPair` with or without a seed. If a seed is not specified, a new keypair will be generated. If a seed is specified, the seed should be 32 bytes. 17 | 18 | _If a seed is specified, `crypto_sign_seed_keypair` will be used internally. Otherwise `crypto_sign_keypair` will be used._ 19 | 20 | # Combined mode 21 | 22 | ## Example 23 | ```C# 24 | var message = System.Text.Encoding.UTF8.GetBytes("My secret message"); 25 | var keyPair = PublicKeyAuth.GenerateKeyPair(); // 64 byte private key | 32 byte public key 26 | 27 | // Sign the message 28 | var signature = PublicKeyAuth.Sign(message, keyPair.Secret); 29 | 30 | // Verify the message signature 31 | var unsignedMessage = PublicKeyAuth.Verify(signature, keyPair.Public); 32 | 33 | // Messages should be the same. 34 | // Assert.AreEqual(message, unsignedMessage); 35 | ``` 36 | 37 | ## Sign 38 | 39 | __Namespace:__ _Sodium.PublicKeyAuth_ 40 | 41 | ```C# 42 | public static byte[] Sodium.PublicKeyAuth.Sign(string message, byte[] privateKey) 43 | public static byte[] Sodium.PublicKeyAuth.Sign(byte[] message, byte[] privateKey) 44 | ``` 45 | 46 | This method is used to sign a given `message` using a 64 byte `privateKey. This method will returns the signed message. 47 | 48 | _This method internally uses `crypto_sign`._ 49 | 50 | ## Verify 51 | 52 | __Namespace:__ _Sodium.PublicKeyAuth_ 53 | 54 | ```C# 55 | public static byte[] Sodium.PublicKeyAuth.Verify(byte[] signedMessage, byte[] publicKey) 56 | ``` 57 | 58 | This method verifies the signature of a given `signedMessage` using the 32 byte `publicKey` associated with the 64 byte private key that originally signed the message. 59 | 60 | _This method internally uses `crypto_sign_open`._ 61 | 62 | # Detached mode 63 | 64 | Detached signatures may be generated as well. In detached mode, signatures are stored without a copy of the original message. 65 | 66 | ## Example 67 | 68 | ```C# 69 | var kp = PublicKeyAuth.GenerateKeyPair(); 70 | string message = "Hello, World!"; 71 | 72 | // Generate a signature 73 | var signature = PublicKeyAuth.SignDetached(message, kp.Secret); 74 | 75 | if (PublicKeyAuth.VerifyDetached(sig1, message, kp.Public)) { 76 | // signature is valid 77 | } 78 | ``` 79 | 80 | ## Sign 81 | 82 | __Namespace:__ _Sodium.PublicKeyAuth_ 83 | 84 | ```C# 85 | public static byte[] SignDetached(byte[] message, byte[] secretKey) 86 | public static byte[] SignDetached(String message, byte[] secretKey) 87 | ``` 88 | 89 | Detached signatures for a given message by calling `SignDetached()` with the `message` and a 64 byte `secretKey`. This method will return a 64 byte signature. 90 | 91 | _This method internally uses `crypto_sign_detached`._ 92 | 93 | ## Verify 94 | 95 | __Namespace:__ _Sodium.PublicKeyAuth_ 96 | 97 | ```C# 98 | public static bool VerifyDetached(byte[] signature, byte[] message, byte[] publicKey) 99 | public static bool VerifyDetached(byte[] signature, String message, byte[] publicKey) 100 | ``` 101 | 102 | Signatures generated by `SignDetached` can be verified using the `VerifyDetached()` method, which accepts a 64 byte `signature` generated by `SignDetached`, the original `message`, and the corresponding 32 byte `publicKey` associated to the `secretKey` that signed the message. 103 | 104 | _This method internally uses `crypto_sign_verify_detached`._ 105 | 106 | ## Multi Part Signing 107 | 108 | __Namespace:__ _Sodium.PublicKeyAuth_ 109 | 110 | ```C# 111 | void Append(IBuffer data) 112 | public byte[] GetValueAndReset(byte[] secretKey) 113 | public bool GetValueAndVerify(byte[] signature, byte[] public key) 114 | ``` 115 | 116 | Messages that do not fit into memory can be signed using the multi-part API as shown in the following example: 117 | 118 | ```C# 119 | var kp = PublicKeyAuth.GenerateKeyPair(); 120 | var signature = new PublicKeyAuth(); 121 | IBuffer data = CryptographicBuffer.ConvertStringToBinary("Hello, World!", BinaryStringEncoding.Utf8); 122 | signature.Append(data); 123 | 124 | var output = signature.GetValueAndReset(kp.Secret); 125 | Assert.AreEqual(64, output.Length); 126 | Assert.AreEqual(true, signature.GetValueAndVerify(output, kp.Public)); 127 | ``` 128 | 129 | Multi part data can be created using `Append()` on a new `PublicKeyAuth()` object. The signature can be retrieved by calling `GetValueAndReset()` with the secret key. The signature can be verified by calling `GetValueAndVerify()` with the signature and the public key. 130 | 131 | _This method internally used `crypto_sign_init`, `crypto_sign_update`, `crypto_sign_final_create`, and `crypto_sign_final_verify`_ 132 | ## Edd25519 to Curve25519 Key Conversion 133 | 134 | ### Convert Private Key 135 | 136 | __Namespace:__ _Sodium.PublicKeyAuth_ 137 | 138 | ```C# 139 | public static byte[] Sodium.PublicKeyAuth.ConvertEd25519SecretKeyToCurve25519SecretKey(byte[] privateKey) 140 | ``` 141 | 142 | This method converts an 64 byte Ed25519 `privateKey` to a Curve25519 `privateKey`, and will return the Curve25519 private key. 143 | 144 | _This method internally uses `crypto_sign_ed25519_pk_to_curve25519`._ 145 | 146 | ### Convert Public key 147 | 148 | __Namespace:__ _Sodium.PublicKeyAuth_ 149 | 150 | ```C# 151 | public static byte[] Sodium.PublicKeyAuth.ConvertEd25519PublicKeyToCurve25519PublicKey(byte[] publicKey) 152 | ``` 153 | 154 | This method converts an 32 byte Ed25519 `publicKey` to a Curve25519 `publicKey`, and will return the Curve25519 public key. 155 | 156 | _This method internally uses `crypto_sign_ed25519_sk_to_curve25519`._ 157 | 158 | ## Ed25519 Seed Extraction 159 | 160 | Sodium provides two methods to extract information from the Ed25519 secret key. 161 | 162 | ### Extract Ed25519 seed from Ed25519 secret key 163 | 164 | __Namespace:__ _Sodium.PublicKeyAuth_ 165 | 166 | ```C# 167 | public static byte[] ExtractEd25519SeedFromEd25519SecretKey(byte[] ed25519SecretKey) 168 | ``` 169 | 170 | _This method internally uses `crypto_sign_ed25519_sk_to_seed`._ 171 | 172 | ### Extract Ed25519 public key from Ed25519 secret key 173 | 174 | __Namespace:__ _Sodium.PublicKeyAuth_ 175 | 176 | ```C# 177 | public static byte[] ExtractEd25519PublicKeyFromEd25519SecretKey(byte[] ed25519SecretKey) 178 | ``` 179 | 180 | _This method internally uses `crypto_sign_ed25519_sk_to_pk`._ 181 | 182 | ## Algorithm Details 183 | 184 | - Signature: Ed25519 -------------------------------------------------------------------------------- /docs/PublicKeyBox.md: -------------------------------------------------------------------------------- 1 | # Public Key Cryptography 2 | 3 | Public key boxes allow an individual (Alice) to send an authenticated message to another individual (Bob) using only the public key of the recipient. 4 | 5 | Using Bob's public key, Alice can send an encrypted message to Bob. Upon recieving the message, Bob can verify the message was not tampered with during transit, and decrypt the message. Using the same system, Bob can send a new message to Alice. 6 | 7 | Public key boxes require only the secret key of the sender, the public key of the recipient, the message, and a nonce. The nonce should never be reused with a given secret and public key pair, and is not confidential. `Sodium.Utilities.Incriment` can be used to incriment the nonce so new nonces do not need to be generated. 8 | 9 | Public key boxes provided mutal authentication. 10 | 11 | ## Generate nonce 12 | 13 | __Namespace:__ _Sodium.PublicKeyBox_ 14 | 15 | ```C# 16 | public static byte[] Sodium.PublicKeyBox.GenerateNonce() 17 | ``` 18 | 19 | This method returns a 24 byte nonce. 20 | 21 | ## Generate KeyPair 22 | 23 | __Namespace:__ _Sodium.PublicKeyBox_ 24 | 25 | ```C# 26 | public static KeyPair Sodium.PublicKeyBox.GenerateKeyPair() 27 | public static KeyPair Sodium.PublicKeyBox.GenerateKeyPair(byte[] privateKey) 28 | ``` 29 | 30 | This method generates a new `KeyPair`. If a 32 byte `privateKey` is provided, this method will return the `KeyPair` (both public and secret components). 31 | 32 | _If a new `KeyPair` is generated, this method will use `crypto_box_keypair` to generate the key pair. If a `privateKey` is provided. `Sodium.ScalarMult.Base` will be used to extract the public component from the `privateKey`. 33 | 34 | # Combined mode 35 | 36 | ## Example 37 | ```C# 38 | var message = System.Text.Encoding.UTF8.GetBytes("My secret message"); 39 | var alice = PublicKeyBox.GenerateKeyPair(); 40 | var bob = PublicKeyBox.GenerateKeyPair(); 41 | 42 | var nonce = PublicKeyBox.GenerateNonce(); 43 | 44 | // Alice encrypts a message for Bob 45 | var encrypted = PublicKeyBox.Create(message, nonce, alice.Secret, bob.Public); 46 | 47 | // Bob decrypts the message 48 | var decrypted = PublicKeyBox.Open(encrypted, nonce, bob.Secret, alice.Public); 49 | ``` 50 | 51 | ## Encrypt 52 | 53 | __Namespace:__ _Sodium.PublicKeyBox_ 54 | 55 | ```C# 56 | public static byte[] Sodium.PublicKeyBox.Create(string message, byte[] nonce, byte[] secretKey, byte[] publicKey) 57 | public static byte[] Sodium.PublicKeyBox.Create(byte[] message, byte[] nonce, byte[] secretKey, byte[] publicKey) 58 | ``` 59 | 60 | This method is used to encrypt a given message using a 24 byte `nonce`, a 32 byte `secretKey` belonging to the sender, and a 32 byte `publicKey` belonging to the recipient. 61 | 62 | _This method internally uses `crypto_box_easy`._ 63 | 64 | ## Decrypt 65 | 66 | __Namespace:__ _Sodium.PublicKeyBox_ 67 | 68 | ```C# 69 | public static byte[] Sodium.PublicKeyBox.Open(byte[] cipherText, byte[] nonce, byte[] secretKey, byte[] publicKey) 70 | ``` 71 | 72 | This method is used to decrypt a `cipherText` generated by `Sodium.PublicKeyBox.Create` using a 24 byte `nonce`, the 32 byte `secretKey` belonging to the recipient, and the 32 byte `publicKey` belonging to the sender. 73 | 74 | _This method internally uses `crypto_box_open_easy`._ 75 | 76 | # Detached mode 77 | 78 | Detached variants of the functions above are also available. Detached boxes are represented by the following object: 79 | 80 | ```C# 81 | public DetachedBox(byte[] cipher, byte[] mac) 82 | { 83 | Cipher = cipher; 84 | Mac = mac; 85 | } 86 | ``` 87 | 88 | ## Example 89 | 90 | ```C# 91 | var alice = PublicKeyBox.GenerateKeyPair(); 92 | var bob = PublicKeyBox.GenerateKeyPair(); 93 | var nonce = PublicKeyBox.GenerateNonce(); 94 | String message = "Hello, World!"; 95 | 96 | var encrypted = PublicKeyBox.CreateDetached(message, nonce, bob.Secret, alice.Public); 97 | var decrypted = PublicKeyBox.OpenDetached(encrypted, nonce, alice.Secret, bob.Public); 98 | ``` 99 | 100 | ## Encrypt 101 | 102 | __Namespace:__ _Sodium.PublicKeyBox_ 103 | 104 | ```C# 105 | public static DetachedBox Sodium.PublicKeyBox.CreateDetached(byte[] message, byte[] nonce, byte[] secretKey, byte[] publicKey) 106 | public static DetachedBox Sodium.PublicKeyBox.CreateDetached(String message, byte[] nonce, byte[] secretKey, byte[] publicKey) 107 | ``` 108 | 109 | Public key boxes can also be created in detached mode. `CreateDetached` encrypts a given `message` with the recipients 32 byte `publicKey`, the senders 32 byte `secretKey`, and a 24 byte `nonce`. 110 | 111 | This method will return a `DetachedBox` if successful, or an exception otherwise. 112 | 113 | _This method internally uses `crypto_box_detached`._ 114 | 115 | ## Decrypt 116 | 117 | __Namespace:__ _Sodium.PublicKeyBox_ 118 | 119 | ```C# 120 | public static byte[] OpenDetached(byte[] cipherText, byte[] mac, byte[] nonce, byte[] secretKey, byte[] publicKey) 121 | public static byte[] OpenDetached(String cipherText, byte[] mac, byte[] nonce, byte[] secretKey, byte[] publicKey) 122 | public static byte[] OpenDetached(DetachedBox detached, byte[] nonce, byte[] secretKey, byte[] publicKey) 123 | ``` 124 | 125 | Public key boxes encrypted with `CreateDetached` can be decrypted using `OpenDetached`. `OpenDetached()` takes a `cipherText` encrypted by `CreateDetached`, the recipients 32 byte `secretKey`, the senders 32 byte `publicKey`, a 24 byte `nonce`, and a 16 byte `mac`. 126 | 127 | The `mac` and `cipherText` may be encapsulated by a `DetachedBox` object, or may be passed individually using one of the overloaded methods. If successful, a byte representation of the encrypted message will be returned, otherwise an exception will be thrown. 128 | 129 | _This method internally uses `crypto_box_open_detached`._ 130 | 131 | ## Algorithm Details 132 | 133 | - Key exchange: Curve25519 134 | - Encryption: XSalsa20 stream cipher 135 | - Authentication: Poly1305 MAC -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Provided Classes 2 | 3 | | Class | Description | 4 | |-------|--------------| 5 | | [Core](Core.md) | Core cryptographic functions | 6 | | [CryptoHash](CryptoHash.md) | Hashing functions | 7 | | [HMAC-SHA2](HMAC-SHA2.md) | HMAC-SHA2 message authentication | 8 | | [GenericHash](GenericHash.md) | Generic hash | 9 | | [KDF](KDF.md) | Useful Key Derivation Functions (KDF) implementations (non-libsodium) | 10 | | [KeyPair](KeyPair.md) | Curve25519/Ed25519 helpers for managing key pairs | 11 | | [OneTimeAuth](OneTimeAuth.md) | One Time Authentication | 12 | | [PasswordHash](PasswordHash.md) | Hash password | 13 | | [PublicKeyAuth](PublicKeyAuth.md) | Authenticated encryption with a public key | 14 | | [PublicKeyBox](PublicKeyAuth.md) | Encryption with a public key | 15 | | [ScalarMult](ScalarMult.md) | Scalar Multiplication | 16 | | [SealedPublicKeyBox](SealedPublicKeyBox.md) | Anonymous public key encryption | 17 | | [SecretAead](SecretAead.md) | Secret authenticated encryption with additional data | 18 | | [SecretBox](SecretBox.md) | Secret key cryptography | 19 | | [SecretKeyAuth](SecretKeyAuth.md) | Authenticated secret key cryptography | 20 | | [SecretStream](SecretStream.md) | Encrypt and decrypt streams of arbitrary length | 21 | | [ShortHash](ShortHash.md) | SigHash-2-4 Short Hashing | 22 | | [StreamEncryption](StreamEncryption.md) | Streaming encryption with Salsa20, ChaCha20, and XSalsa20 | 23 | | [Utilities](Utilities.md) | libsodium utilities | 24 | 25 | # Design Goals 26 | 27 | The initial goal of this runtime component was to implement libsodium for UWP using an API similar to that provided by [libsodium-net](https://github.com/adamcaudill/libsodium-net). When a direct 1-1 matching is not possible, the API will implement designs consistent with UWP functions (e.g. `GenericHash` mimics `HashAlgorithmProvider` behavior). 28 | 29 | # Using this library 30 | 31 | After installation, you can use this library by `using Sodium`. For more indepth examples about using this library, reference the `Tests` directory. 32 | 33 | > __NOTE:__ This library is compatible with `libsodium` 1.0.11+. Compatability with version <= 1.0.11 is not guaranteed. 34 | -------------------------------------------------------------------------------- /docs/ScalarMult.md: -------------------------------------------------------------------------------- 1 | # Scalar Multiplication 2 | 3 | The following internal functions are exposed and documented for reference purposes 4 | 5 | __Namespace:__ _Sodium.ScalarMult_ 6 | 7 | ```C# 8 | public static int Bytes(); 9 | ``` 10 | 11 | _Internally this function uses `sodium_scalarmult_base`._ 12 | 13 | ```C# 14 | public static int ScalarBytes(); 15 | ``` 16 | 17 | _Internally this function uses `crypto_scalarmult_scalarbytes`._ 18 | 19 | ```C# 20 | public static byte[] Base(byte[] secretKey); 21 | ``` 22 | 23 | _Internally this function uses `crypto_scalarmult_base`._ 24 | 25 | ```C# 26 | public static byte[] Mult(byte[] secretKey, byte[] publicKey); 27 | ``` 28 | 29 | _Internally this function uses `crypto_scalarmult`._ -------------------------------------------------------------------------------- /docs/SealedPublicKeyBox.md: -------------------------------------------------------------------------------- 1 | # Sealed Public Key Cryptography 2 | 3 | ## Example 4 | ```C# 5 | var message = System.Text.Encoding.UTF8.GetBytes("My secret message"); 6 | 7 | // Recipient creates a long-term key pair 8 | var recipientKeyPair = PublicKeyBox.GenerateKeyPair(); 9 | 10 | // Anonymous sender encrypts a message using an ephemeral key pair 11 | // and the recipient's public key 12 | var encryptedMessage = SealedPublicKeyBox.Create(message, recipientKeyPair.Public); 13 | 14 | // Recipient decrypts the ciphertext 15 | var decryptedMessage = SealedPublicKeyBox.Open(encryptedMessage, recipientKeyPair); 16 | ``` 17 | 18 | ## Purpose 19 | 20 | Sealed boxes are designed so that anonymous individuals can send a message to a given recipient using their public key. Only the recipient can decrypt the message using their private key. Consequently, without additional data the recipient will not be able to identify the sender. 21 | 22 | The message is encrypted using an ephemeral key pair whose secret part is destroyed after the message is encrypted. 23 | 24 | ## Encrypt 25 | 26 | __Namespace:__ _Sodium.SealedPublicKeyBox_ 27 | 28 | ```C# 29 | public static byte[] Sodium.SealedPublicKeyBox.Create(byte[] message, byte[] recipientPublicKey) 30 | public static byte[] Sodium.SealedPublicKeyBox.Create(string message, byte[] recipientPublicKey) 31 | public static byte[] Sodium.SealedPublicKeyBox.Create(byte[] message, KeyPair recipientKeyPair) 32 | public static byte[] Sodium.SealedPublicKeyBox.Create(string message, KeyPair recipientKeyPair) 33 | ``` 34 | 35 | This method encrypts a given message using a 32 byte `recipientPublicKey`. A new key pair is created for each message, and the corresponding public key is attached to the output ciphertext. the secret key is destroyed after the message has been encrypted, and is not available after this method returns. 36 | 37 | This method is overloaded to accept either the recipient's public key, or a `KeyPair` instance upon which the `Public` component can be extracted from. 38 | 39 | _This method uses internally `crypto_box_seal`._ 40 | 41 | ## Decrypt 42 | 43 | __Namespace:__ _Sodium.SealedPublicKeyBox_ 44 | 45 | ```C# 46 | public static byte[] Sodium.SealedPublicKeyBox.Open(byte[] cipherText, byte[] recipientSecretKey, byte[] recipientPublicKey) 47 | public static byte[] Sodium.SealedPublicKeyBox.Open(byte[] cipherText, KeyPair recipientKeyPair) 48 | ``` 49 | 50 | This method decrypts an encrypted `cipherText` encrypted by `Sodium.SealedPublicKeyBox.Create` using the 32 bytes `recipientSecretKey` and 32 bytes `recipientPublicKey`. 51 | 52 | This method is overloaded to accept either the recipient's public and private key, or a `KeyPair` instance upon which the `Public` and `Secret` component can be extracted from. 53 | 54 | _This method uses internally `crypto_box_seal_open`._ -------------------------------------------------------------------------------- /docs/SecretAead.md: -------------------------------------------------------------------------------- 1 | # Authenticated Encryption with Additional Data 2 | 3 | ## Example 4 | ```C# 5 | var message = System.Text.Encoding.UTF8.GetBytes("Hello, World!"); 6 | var key = SecretBox.GenerateKey(); 7 | var nonce = SecretAead.GenerateNonce(); 8 | var ad = System.Text.Encoding.UTF8.GetBytes("additional data"); 9 | 10 | // encrypt with additional data 11 | var encrypted = SecretAead.Encrypt(message, nonce, key, ad); 12 | 13 | // encrypt without additional data 14 | var encrypted = secretAead.Encrypt(message, nonce, key); 15 | 16 | // decrypt with additional data 17 | var decrypted = SecretAead.Decrypt(encrypted, nonce, key, ad); 18 | ``` 19 | 20 | ## Purpose 21 | 22 | This class allows you to encrypt a message with a given key and nonce, and additional computes an authenticate tag that you can use to verify both the message and the additional data (non confidential, not encrypted) haven't been tampered with. 23 | 24 | ## Generate nonce 25 | 26 | __Namespace:__ _Sodium.SecretAead_ 27 | 28 | ```C# 29 | public static byte[] Sodium.SecertAead.GenerateNonce() 30 | ``` 31 | 32 | This method generates a 8 byte `nonce` 33 | 34 | > To prevent nonce reuse, if your key is going to be reused, use `Sodium.Utilities.Increment` on your nonce rather than generating a random nonce for each message. 35 | 36 | ## Encrypt 37 | 38 | __Namespace:__ _Sodium.SecretAead_ 39 | 40 | ```C# 41 | public static byte[] Sodium.SecretAead.Encrypt(byte[] message, byte[] nonce, byte[] key) 42 | public static byte[] Sodium.SecretAead.Encrypt(string message, byte[] nonce, byte[] key) 43 | public static byte[] Sodium.SecretAead.Encrypt(byte[] message, byte[] nonce, byte[] key, byte[] additionalData) 44 | public static byte[] Sodium.SecretAead.Encrypt(string message, byte[] nonce, byte[] key, byte[] additionalData) 45 | ``` 46 | 47 | This method encrypts a message with a 8 bytes `nonce` and a 32 byte `key`. The public `nonce` should never be reused with the same key. `Sodium.Utilities.Increment` can be used to increment your nonce when computing new mesages. 48 | 49 | > This method is overloaded so that `additionalData` is optional. If you are not using `additionalData` with your message, `libsodium-uwp` will set it to be a single byte `0x00`. For portability purposes use this single byte if your application does not set `additionalData`. Note that the `additionalData` if set must be between 0 and 16 bytes. 50 | 51 | _This method uses internally `crypto_aead_chacha20poly1305_encrypt`._ 52 | 53 | ## Decrypt 54 | 55 | __Namespace:__ _Sodium.SecretAead_ 56 | 57 | ```C# 58 | public static byte[] Sodium.SecretAead.Decrypt(byte[] encrypted, byte[] nonce, byte[] key) 59 | public static byte[] Sodium.SecretAead.Decrypt(byte[] encrypted, byte[] nonce, byte[] key, byte[] additionalData) 60 | ``` 61 | 62 | This method decrypts an encrypted ciphertext generated by `Sodium.SecretAead.Encrypt` using a 8 byte `nonce` and a 32 byte `key`, and an optional `additionalData`. 63 | 64 | > This method is overloaded so that `additionalData` is optional. If you are not using `additionalData` with your message, `libsodium-uwp` will set it to be a single byte `0x00`. For portability purposes use this single byte if your application does not set `additionalData`. Note that the `additionalData` if set must be between 0 and 16 bytes. 65 | 66 | # Algorithm Details 67 | 68 | - Encryption: ChaCha20 stream cipher 69 | - Authentication: Poly1305 MAC 70 | 71 | > `libsodium` provides 3 AEAD methods. This library _only_ implements SecretAead using `chacha20_pol1305`. -------------------------------------------------------------------------------- /docs/SecretBox.md: -------------------------------------------------------------------------------- 1 | # Secret-key authenticated encryption 2 | 3 | ## Example 4 | ```C# 5 | var nonce = Sodium.SecretBox.GenerateNonce(); // 24 byte nonce 6 | var key = Sodium.SecretBox.GenerateKey(); // 32 byte key 7 | var message = System.Text.Encoding.UTF8.GetBytes("Hello, World!"); 8 | 9 | // encrypt the message 10 | var encrypted = SecretBox.Create(message, nonce, key); 11 | // decrypt it again 12 | var decrypted = SecretBox.Open(encrypted, nonce, key); 13 | ``` 14 | 15 | ## Purpose 16 | 17 | Secret Key boxes are used to encrypt a message with a key and nonce to keep it confidential. Additionally this operation will compute an authentication take that is used to ensure the message hasn't been tampered with before decryption. 18 | 19 | Secret key boxes use a single key to encrypt/sign and decrypt/verify messages. The 32 byte key that you use should be kept confidential. 20 | 21 | The nonce used does not have to be confidential, but should never be reused with the same key. 22 | 23 | ## Generate nonce 24 | 25 | __Namespace:__ _Sodium.SecretBox_ 26 | 27 | ```C# 28 | public static byte[] Sodium.SecretBox.GenerateNonce() 29 | ``` 30 | 31 | This method generates a 24 byte nonce. 32 | 33 | ## Generate key 34 | 35 | __Namespace:__ _Sodium.SecretBox_ 36 | 37 | ```C# 38 | public static byte[] Sodium.SecretBox.GenerateKey() 39 | ``` 40 | 41 | This method generates a 32 byte key. 42 | 43 | > 32 byte keys can also be generated through a KDF function such as PBKDF2, or HKDF. 44 | 45 | # Combined mode 46 | 47 | ## Encrypt a message 48 | 49 | __Namespace:__ _Sodium.SecretBox_ 50 | 51 | ```C# 52 | public static byte[] Sodium.SecretBox.Create(byte[] message, byte[] nonce, byte[] key) 53 | public static byte[] Sodium.SecretBox.Create(string message, byte[] nonce, byte[] key) 54 | ``` 55 | 56 | This method encrypts a given `message` with a 24 byte `nonce` and a 32 byte `key`. The resulting byte array will contain the encrypted message and a 16 byte authentication tag prepended to the encrypted message. 57 | 58 | _This method internally uses `crypto_secretbox_easy`._ 59 | 60 | ## Decrypt a message 61 | 62 | __Namespace:__ _Sodium.SecretBox_ 63 | 64 | ```C# 65 | public static byte[] Sodium.SecretBox.Open(byte[] ciphertext, byte[] nonce, byte[] key) 66 | ``` 67 | 68 | This method decrypts a ciphertext generated by `Sodium.SecretBox.Create` using the generated `ciphertext` and the 24 byte `nonce` and 32 byte `key` originally used to encrypt them message. 69 | 70 | This method will return a byte array on success. 71 | 72 | _This method internally uses `crypto_secretbox_open_easy`._ 73 | 74 | # Detached mode 75 | 76 | Detached variants of the functions above are also available. Detached boxes are represented by the following object: 77 | 78 | ```C# 79 | public DetachedBox(byte[] cipher, byte[] mac) 80 | { 81 | Cipher = cipher; 82 | Mac = mac; 83 | } 84 | ``` 85 | 86 | ## Encrypt 87 | 88 | __Namespace:__ _Sodium.SecretBox_ 89 | 90 | ```C# 91 | public static DetachedBox CreateDetached(byte[] message, byte[] nonce, byte[] key); 92 | public static DetachedBox CreateDetached(String message, byte[] nonce, byte[] key); 93 | ``` 94 | 95 | This method encrypts a message using a 24 byte `nonce` and a 32 byte `key`. If successful this will return a `DetachedBox` object containing the cipher text and mac. 96 | 97 | _Internally this method uses `crypto_secretbox_detached`._ 98 | 99 | ## Decrypt 100 | 101 | __Namespace:__ _Sodium.SecretBox_ 102 | 103 | ```C# 104 | public static byte[] OpenDetached(byte[] cipherText, byte[] mac, byte[] nonce, byte[] key); 105 | public static byte[] OpenDetached(String cipherText, byte[] mac, byte[] nonce, byte[] key); 106 | public static byte[] OpenDetached(DetachedBox detached, byte[] nonce, byte[] key); 107 | ``` 108 | 109 | This method decrypts a given `cipherText` produced by `CreateDetached()` with a 16 byte `mac`, a 24 byte `nonce`, and a 32 byte `key`. 110 | 111 | _Internally this method uses `crypto_secretbox_open_detached`._ 112 | 113 | # Algorithm Details 114 | 115 | - Encryption: XSalsa20 stream cipher 116 | - Authentication: Poly1305 MAC 117 | -------------------------------------------------------------------------------- /docs/SecretKeyAuth.md: -------------------------------------------------------------------------------- 1 | # Secret-key authentication 2 | 3 | ## Example 4 | ```C# 5 | var message = System.Text.Encoding.UTF8.GetBytes("Hello, World!"); 6 | var key = SecretKeyAuth.GenerateKey(); // 32 byte key 7 | 8 | // returns a 32 byte authentication code 9 | var signature = SecretKeyAuth.Sign(message, key); 10 | 11 | if (SecretKeyAuth.Verify(message, signature, key)) 12 | { 13 | // Message is valid 14 | } 15 | ``` 16 | 17 | ## Purpose 18 | 19 | This operation computes an authentication tag of a given message using a secret key, and provides a way to verify that the authentication tag is valid. This method is deterministic (the same message and key will always produce the same output). 20 | 21 | The computed authentication tag may be public, however your secret key should be kept confidential. 22 | 23 | > This operation does not encrypt the message. It only computes and verifies an authentication tag. 24 | 25 | ## Generate key 26 | 27 | __Namespace:__ _Sodium.SecretKeyAuth 28 | 29 | ```C# 30 | public static byte[] Sodium.SecretKeyAuth.GenerateKey() 31 | ``` 32 | 33 | This method generates a 32 byte key. 34 | 35 | ## Sign 36 | 37 | __Namespace:__ _Sodium.SecretKeyAuth 38 | 39 | ```C# 40 | pubic static byte[] Sodium.SecretKeyAuth.Sign(byte[] message, byte[] key) 41 | pubic static byte[] Sodium.SecretKeyAuth.Sign(string message, byte[] key) 42 | ``` 43 | 44 | This method signs a given `message` using a 32 byte `key`, and will return a 32 byte authentication tag. 45 | 46 | _This method internally uses `crypto_auth`._ 47 | 48 | ## Verify 49 | 50 | __Namespace:__ _Sodium.SecretKeyAuth 51 | 52 | ```C# 53 | public static bool Sodium.SecretKeyAuth.Verify(byte[] message, byte[] signature, byte[] key) 54 | public static bool Sodium.SecretKeyAuth.Verify(string message, byte[] signature, byte[] key) 55 | ``` 56 | 57 | This method verifies that the given 32 byte `signature` associated with a given `message` and 32 byte `key` is valid. This method will return `true` of the signature is valid, and `false` otherwise. 58 | 59 | _This method internally uses `crypto_auth_verify`._ 60 | 61 | # Algorithm Details 62 | 63 | - HMAC-SHA512/256 -------------------------------------------------------------------------------- /docs/SecretStream.md: -------------------------------------------------------------------------------- 1 | # Secret Stream 2 | 3 | Stream/file encryption is made available through a high-level API that encrypts a sequence of messages, or a single message split up into an arbitary number of chunks, using a secret key with the following properties: 4 | 5 | - Messages cannot be truncated, removed, reordered, duplicated or modified without this being detected by the decryption methods. 6 | - Non-deterministic - the same sequence encrypted twice will produce different ciphertexts. 7 | - An authentication tag is added to each encrypted message, allowing streaming corruption to be detected without having to read the stream until the end. 8 | - Each message can incldue additional data in computation of the message tag. 9 | - Messages can be of arbirary size and length. 10 | - There is no practical limit to the total length of the stream, or the total number of individual messages. 11 | - Ratcheting: at any point in the stream, it's possible to forget the key used to encrypt previous messages and to switch to a new key. 12 | - Nonce and key rotation is automatically handled. 13 | 14 | This API can be used to securely send an ordered sequence of messages to a peer. Since the length of the stream is not limited, it can also be used to encrypt files regardless of their size. 15 | > Please reference the [libsodium documentation](https://download.libsodium.org/doc/secret-key_cryptography/secretstream.html) for more information on secret streams. 16 | 17 | ## Example 18 | 19 | The following is a rough example of how to use the API. 20 | 21 | ```C# 22 | var key = SecretStream.GenerateKey(); 23 | var header = SecretStream.GenerateHeader(); 24 | var encrypter = new SecretStream(key, header, SecretStream.MODE_PUSH); 25 | var decrypter = new SecretStream(key, header, SecretStream.MODE_PULL); 26 | 27 | var message1 = "Hello, World!"; 28 | var message2 = "{ \"json\": \"data\" }"; 29 | var message3 = "Some more random messaging"; 30 | 31 | var ciphertext1 = encrypter.Push(message1); 32 | encrypter.Rekey(); 33 | var ciphertext2 = encrypter.Push(message2, SecretStream.TAG_PUSH); 34 | var ciphertext3 = encrypter.Push(message3, SecretStream.TAG_FINAL); 35 | 36 | int tag = -1; 37 | var d1 = decrypter.Pull(ciphertext1, out tag); 38 | // tag == Sodium.SecretStream.TAG_MESSAGE 39 | decrypter.Rekey(); 40 | var d2 = decrypter.Pull(ciphertext2, out tag); 41 | // tag == Sodium.SecretStream.TAG_PUSH 42 | var d3 = decrypter.Pull(ciphertext3, out tag); 43 | // tag == Sodium.SecretStream.TAG_FINAL 44 | ``` 45 | 46 | ## Stream Modes 47 | 48 | __Namespace:__ _Sodium.SecretStream_ 49 | 50 | ```C# 51 | SecretStream.MODE_PUSH 52 | SecretStream.MODE_PULL 53 | ``` 54 | 55 | The streaming API exposes two distinct modes, one for encrypting, and the other for decrypting a stream. 56 | 57 | ## Tags 58 | 59 | __Namespace:__ _Sodium.SecretStream_ 60 | 61 | A tag is attached to each message, and may be one of the following: 62 | 63 | ```C# 64 | SecretStream.TAG_MESSAGE 65 | ``` 66 | `TAG_MESSAGE` is the default tag that is added. It does not contain any additional information about the nature of the message. 67 | 68 | ```C# 69 | SecretStream.TAG_PUSH 70 | ``` 71 | `TAG_PUSH` indicates that the message marks the end of a set of messages, but not the end of a stream. More messages may follow. 72 | 73 | ```C# 74 | SecretStream.TAG_REKEY 75 | ``` 76 | `TAG_REKEY` "forgets" the key used to encrypt this message and the previous one, and derives a new secret key. 77 | 78 | ```C# 79 | SecretStream.TAG_FINAL 80 | ``` 81 | `TAG_FINAL` indicates that the message marks the end of the stream, and erases the secret key used to encrypt the previous sequence. 82 | 83 | 84 | ## Key Generation 85 | 86 | Secret streams require both a key and a header to encrypt and decrypt the header. Both components are needed to encrypt and decrypt a given stream. 87 | 88 | __Namespace:__ _Sodium.SecretStream_ 89 | 90 | ```C# 91 | public static byte[] Sodium.PublicKeyBox.GenerateKey() 92 | ``` 93 | 94 | This method returns a 32 byte key. Within the same application you can use this method to generate a 32 byte key for encrypting and decrypting. When working with remote peers however, use a key exchange method such as [`Sodium::ScalarMult::Mult`](ScalarMult.md) to create a 32 byte shared key that can be safely transmitted to the remote peer. 95 | 96 | _Internally this method uses `crypto_secretstream_xchacha20poly1305_keygen`._ 97 | 98 | ```C# 99 | public static byte[] Sodium.PublicKeyBox.GenerateHeader() 100 | ``` 101 | 102 | This method returns a 24 byte header. 103 | 104 | ## Stream Handling 105 | 106 | __Namespace:__ _Sodium.SecretStream_ 107 | 108 | ```C# 109 | public SecretStream SecretStream(byte[] key, byte[] header, int mode); 110 | ``` 111 | 112 | A new stream can be created either in encrypt or decrypt mode. 113 | 114 | _Internally this method uses `crypto_secretstream_xchacha20poly1305_init_push` or `crypto_secretstream_xchacha20poly1305_init_pull`, depending upon the mode selected._ 115 | ## Encrypting a Stream 116 | 117 | __Namespace:__ _Sodium.SecretStream_ 118 | 119 | ```C# 120 | public byte[] Push(String message); 121 | public byte[] Push(byte[] message); 122 | ``` 123 | 124 | Several methods are exposed to encrypt a new message in the stream. By default, `TAG_MESSAGE` will be used for the tag. 125 | 126 | ```C# 127 | public byte[] Push(String message, int tag); 128 | public byte[] Push(byte[] message, int tag); 129 | ``` 130 | 131 | One of the aforementioned tags may be defined. This is useful for rekeying the stream or indicating that the stream is final. 132 | 133 | ```C# 134 | public byte[] Push(String message, int tag, String additionalData); 135 | public byte[] Push(byte[] message, int tag, byte[] additionalData); 136 | ``` 137 | 138 | Additional data may also be included with the stream either as a String or as a byte array. 139 | 140 | _Internally this method uses `crypto_secretstream_xchacha20poly1305_push`._ 141 | 142 | ## Decrypting a Stream 143 | 144 | __Namespace:__ _Sodium.SecretStream_ 145 | 146 | ```C# 147 | public byte[] Pull(byte[] ciphertext, out int tag); 148 | ``` 149 | 150 | The default method will return a `byte[]` containing the decrypted response, and will `out` the tag used during the encryption process. After decryption, check if `tag == Sodium.SecretStream.TAG_FINAL` to determine if there are more messages to parse. 151 | 152 | ```C# 153 | public byte[] Pull(byte[] ciphertext, out int tag, byte[] additionalData); 154 | public byte[] Pull(byte[] ciphertext, out int tag, String additionalData); 155 | ``` 156 | 157 | Additional data may also be specified 158 | 159 | _Internally this method uses `crypto_secretstream_xchacha20poly1305_pull`._ 160 | 161 | ## Rekeying 162 | 163 | __Namespace:__ _Sodium.SecretStream_ 164 | 165 | ```C# 166 | public void Rekey(); 167 | ``` 168 | 169 | Rekeying happens automatically, and transparently. If you want to manually rekey, you can either use the `TAG_REKEY` tag with your message, or explicitly call `Rekey()`. 170 | 171 | > Note that rekeying must occur at the same point on both the sender and reciever. 172 | 173 | _Internally this method uses `crypto_secretstream_xchacha20poly1305_rekey`._ 174 | -------------------------------------------------------------------------------- /docs/ShortHash.md: -------------------------------------------------------------------------------- 1 | # Short Input Hashing 2 | 3 | `ShortHash.Hash` outputs a short but unpredecitable value for a given key and message. ShortHash is optimized for short inputs. 4 | 5 | Use cases include: 6 | 7 | - Hash tables 8 | - Probabilistic data structures (such as Bloom filters) 9 | - Integrity checking interactive protocols 10 | 11 | > Note: `ShortHash.Hash` will only generate 64 bits of output, and should _not_ be considered collision resistant. 12 | 13 | ## Example 14 | 15 | ```C# 16 | var key = ShortHash.GenerateKey(); 17 | var message = "A short message to hash"; 18 | 19 | var hash = ShortHash.Hash(message, key); 20 | ``` 21 | 22 | ## Key generation 23 | 24 | __Namespace:__ _Sodium.ShortHash_ 25 | 26 | ```C# 27 | public static byte[] Sodium.ShortHash.GenerateKey() 28 | ``` 29 | 30 | Generates a 16 byte key 31 | 32 | _Internally this method will used `Sodium.Core.GenerateBytes(32)`_ 33 | 34 | ## Hashing 35 | 36 | __Namespace:__ _Sodium.ShortHash_ 37 | 38 | ```C# 39 | public static byte[] Hash(byte[] message, byte[] key) 40 | public static byte[] Hash(string message, byte[] key) 41 | public static byte[] Hash(string message, string key) 42 | ``` 43 | 44 | This method computes an 8 byte fingerprint for the given `message`, using a 16 byte `key`. This method is deterministic, in that the same input with the same key will always produce the same hash. 45 | 46 | _Internally this method used `crypto_shorthash`._ 47 | 48 | ## Algorithm Details 49 | 50 | - SipHash-2-4 -------------------------------------------------------------------------------- /docs/StreamEncryption.md: -------------------------------------------------------------------------------- 1 | # Stream Cipher 2 | 3 | libsodium-uwp provides access to all 3 streaming ciphers provided by libsodium 4 | 5 | ## Key Generating 6 | 7 | __Namespace:__ _Sodium.StreamEncryption_ 8 | 9 | ```C# 10 | static byte[] Sodium.StreamEncryption.GenerateKey() 11 | ``` 12 | 13 | This will generate a 32 byte key from `Sodium.Core.GetRandomBytes(32)` 14 | 15 | ## XSalsa20 16 | 17 | XSalsa20 is a stream cipher based on Salsa20, but has a 192 bit nonce instead of a 64 bit nonce. 18 | 19 | XSalsa20 uses a 256 bit key, and the first 128 bits of the nonce to compute a subkey, which is then used with the remaining 64 bits of the nonce to generate the stream. 20 | 21 | XSalsa20 is immune to timing attacks, and provides its own 64 bit block counter to avoid incrementing the nonce after each block. 22 | 23 | ### Generate nonce 24 | 25 | __Namespace:__ _Sodium.StreamEncryption_ 26 | 27 | ```C# 28 | static byte[] Sodium.StreamEncryption.GenerateNonce() 29 | static byte[] Sodium.StreamEncryption.GenerateNonceXSalsa20() 30 | ``` 31 | 32 | This will generate a 32 byte nonce from `Sodium.Core.GetRandomBytes(32)`. 33 | 34 | > For compatability with `libsodium-net`, `GenerateNonce` is exposed in addition to `GenerateNonceXSalsa20` 35 | 36 | ### Encrypt 37 | 38 | __Namespace:__ _Sodium.StreamEncryption_ 39 | 40 | ```C# 41 | public static byte[] Encrypt(byte[] message, byte[] nonce, byte[] key) 42 | public static byte[] Encrypt(String message, byte[] nonce, byte[] key) 43 | public static byte[] EncryptXSalsa20(byte[] message, byte[] nonce, byte[] key) 44 | public static byte[] EncryptXSalsa20(String message, byte[] nonce, byte[] key) 45 | ``` 46 | 47 | Encrypt expects a `message`, a 24 byte `nonce`, and a 32 byte `key`, and will return a ciphertext (which is the message combined with the output of the stream cipher using the XOR operation, and does not include an authentication tag). 48 | 49 | > For compatability with `libsodium-net`, `Encrypt` is directly exposed. `EncryptXSalsa20` is a direct reference to this method. 50 | 51 | _Internally this method used `crypto_stream_xsalsa20_xor`._ 52 | 53 | ### Decrypt 54 | 55 | __Namespace:__ _Sodium.StreamEncryption_ 56 | 57 | ```C# 58 | public static byte[] Decrypt(byte[] cipherText, byte[] nonce, byte[] key) 59 | public static byte[] Decrypt(String cipherText, byte[] nonce, byte[] key) 60 | public static byte[] DecryptXSalsa20(byte[] cipherText, byte[] nonce, byte[] key) 61 | public static byte[] DecryptXSalsa20(String cipherText, byte[] nonce, byte[] key) 62 | ``` 63 | 64 | Decrypt expects a `ciphertext`, a 24 byte `nonce`, and a 32 byte `key`, and will return a decrypted byte array message. 65 | 66 | > For compatability with `libsodium-net`, `Decrypt` is directly exposed. `DecryptXSalsa20` is a direct reference to this method. 67 | 68 | _Internally this method used `crypto_stream_xsalsa20_xor`._ 69 | 70 | ## ChaCha20 71 | 72 | ChaCha20 is a stream cipher variant of Salsa20 developed by Daniel J.Bernstein with better diffusion. ChaCha20 expands a 256 bit key int 2^64 randomly accessible streams, each containing 2^64 randomly accessible 64 byte blocks. 73 | 74 | ChaCha20 doesn't require any lookup tables, and avoids the possibility of timing attacks. ChaCha20 works like a block cipher used in counter mode. It has a dedicated 64 bit block counter to avoid incrementing the nonce after each block. 75 | 76 | ### Generate nonce 77 | 78 | __Namespace:__ _Sodium.StreamEncryption_ 79 | 80 | ```C# 81 | static byte[] Sodium.StreamEncryption.GenerateNonceChaCha20() 82 | ``` 83 | 84 | This will generate a 8 byte nonce from `Sodium.Core.GetRandomBytes(8)`. 85 | 86 | ### Encrypt 87 | 88 | __Namespace:__ _Sodium.StreamEncryption_ 89 | 90 | ```C# 91 | public static byte[] EncryptChaCha20(byte[] message, byte[] nonce, byte[] key) 92 | public static byte[] EncryptChaCha20(String message, byte[] nonce, byte[] key) 93 | ``` 94 | 95 | Encrypt expects a `message`, a 8 byte `nonce`, and a 32 byte `key`, and will return a ciphertext (which is the message combined with the output of the stream cipher using the XOR operation, and does not include an authentication tag). 96 | 97 | _Internally this method used `crypto_stream_chacha20_xor`._ 98 | 99 | ### Decrypt 100 | 101 | __Namespace:__ _Sodium.StreamEncryption_ 102 | 103 | ```C# 104 | public static byte[] DecryptChaCha20(byte[] cipherText, byte[] nonce, byte[] key) 105 | public static byte[] DecryptChaCha20(String cipherText, byte[] nonce, byte[] key) 106 | ``` 107 | 108 | Decrypt expects a `ciphertext`, a 8 byte `nonce`, and a 32 byte `key`, and will return a decrypted byte array message. 109 | 110 | _Internally this method used `crypto_stream_chacha20_xor`._ 111 | 112 | ## Salsa20 113 | 114 | Salsa20 is a stream cipher developed by Daniel J.Bernstein. Salsa20 expands a 256 bit key int 2^64 randomly accessible streams, each containing 2^64 randomly accessible 64 byte blocks. 115 | 116 | Salsa20 doesn't require any lookup tables, and avoids the possibility of timing attacks. Salsa20 works like a block cipher used in counter mode. It has a dedicated 64 bit block counter to avoid incrementing the nonce after each block. 117 | 118 | ### Generate nonce 119 | 120 | __Namespace:__ _Sodium.StreamEncryption_ 121 | 122 | ```C# 123 | static byte[] Sodium.StreamEncryption.GenerateNonceSalsa20() 124 | ``` 125 | 126 | This will generate a 24 byte nonce from `Sodium.Core.GetRandomBytes(24)`. 127 | 128 | ### Encrypt 129 | 130 | __Namespace:__ _Sodium.StreamEncryption_ 131 | 132 | ```C# 133 | public static byte[] EncryptSalsa20(byte[] message, byte[] nonce, byte[] key) 134 | public static byte[] EncryptSalsa20(String message, byte[] nonce, byte[] key) 135 | ``` 136 | 137 | Encrypt expects a `message`, a 24 byte `nonce`, and a 32 byte `key`, and will return a ciphertext (which is the message combined with the output of the stream cipher using the XOR operation, and does not include an authentication tag). 138 | 139 | _Internally this method used `crypto_stream_salsa20_xor`._ 140 | 141 | ### Decrypt 142 | 143 | __Namespace:__ _Sodium.StreamEncryption_ 144 | 145 | ```C# 146 | public static byte[] DecryptSalsa20(byte[] cipherText, byte[] nonce, byte[] key) 147 | public static byte[] DecryptSalsa20(String cipherText, byte[] nonce, byte[] key) 148 | ``` 149 | 150 | Decrypt expects a `ciphertext`, a 24 byte `nonce`, and a 32 byte `key`, and will return a decrypted byte array message. 151 | 152 | _Internally this method used `crypto_stream_salsa20_xor`._ -------------------------------------------------------------------------------- /docs/Utilities.md: -------------------------------------------------------------------------------- 1 | # Utilities 2 | 3 | Useful utilities exposed by libsodium. 4 | 5 | ## Incrementing large numbers 6 | 7 | __Namespace:__ _Sodium.Utilities_ 8 | 9 | ```C# 10 | public static byte[] Sodium.Utilities.Increment(byte[] value) 11 | ``` 12 | 13 | A constant-time function to increment a given array of bytes (nonce or a large number). This function considers the number to encoded in little-endian format. 14 | 15 | _This function implements `sodium_increment`_ 16 | 17 | ## Constant time comparison of large numbers 18 | 19 | __Namespace:__ _Sodium.Utilities_ 20 | 21 | ```C# 22 | public static bool Sodium.Utilities.Compare(byte[] a, byte[] b) 23 | ``` 24 | 25 | This function compares two values in constant-time, and will return `true` if they are the same, and `false` otherwise. 26 | 27 | _This function implements `sodium_compare`_ 28 | 29 | # Other Useful Utilities 30 | 31 | While not implemented by this library, you may find the following UWP methods useful when working with this library. 32 | 33 | ## Converting a string to byte[] 34 | 35 | ```C# 36 | String str = "My Data"; 37 | byte[] message = System.Text.Encoding.UTF8.GetBytes(str); 38 | ``` 39 | 40 | ## Convert byte[] to hex 41 | 42 | ```C# 43 | var data = Sodium.Core.GetRandomBytes(32); 44 | string hex = BitConverter.ToString(data).Replace("-", string.Empty).ToLower(); 45 | ``` 46 | 47 | ## Convert byte[] to base64 48 | 49 | ```C# 50 | var data = Sodium.Core.GetRandomBytes(32); 51 | var data = Convert.ToBase64String(bytes); 52 | ``` 53 | 54 | ## Convert base64 to byte[] 55 | 56 | ```C# 57 | byte[] data = Convert.FromBase64String("=="); 58 | ``` -------------------------------------------------------------------------------- /libsodium-uwp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsodium-uwp", "libsodium-uwp\libsodium-uwp.vcxproj", "{0DDF9CB3-1501-4952-A389-A5459D945E25}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{B0448317-E45D-434D-BC9B-FA129A974110}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|ARM = Debug|ARM 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|Any CPU = Release|Any CPU 17 | Release|ARM = Release|ARM 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Debug|Any CPU.ActiveCfg = Debug|Win32 23 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Debug|ARM.ActiveCfg = Debug|ARM 24 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Debug|ARM.Build.0 = Debug|ARM 25 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Debug|x64.ActiveCfg = Debug|x64 26 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Debug|x64.Build.0 = Debug|x64 27 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Debug|x86.ActiveCfg = Debug|Win32 28 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Debug|x86.Build.0 = Debug|Win32 29 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Release|Any CPU.ActiveCfg = Release|Win32 30 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Release|ARM.ActiveCfg = Release|ARM 31 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Release|ARM.Build.0 = Release|ARM 32 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Release|x64.ActiveCfg = Release|x64 33 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Release|x64.Build.0 = Release|x64 34 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Release|x86.ActiveCfg = Release|Win32 35 | {0DDF9CB3-1501-4952-A389-A5459D945E25}.Release|x86.Build.0 = Release|Win32 36 | {B0448317-E45D-434D-BC9B-FA129A974110}.Debug|Any CPU.ActiveCfg = Debug|x86 37 | {B0448317-E45D-434D-BC9B-FA129A974110}.Debug|ARM.ActiveCfg = Debug|ARM 38 | {B0448317-E45D-434D-BC9B-FA129A974110}.Debug|ARM.Build.0 = Debug|ARM 39 | {B0448317-E45D-434D-BC9B-FA129A974110}.Debug|ARM.Deploy.0 = Debug|ARM 40 | {B0448317-E45D-434D-BC9B-FA129A974110}.Debug|x64.ActiveCfg = Debug|x64 41 | {B0448317-E45D-434D-BC9B-FA129A974110}.Debug|x64.Build.0 = Debug|x64 42 | {B0448317-E45D-434D-BC9B-FA129A974110}.Debug|x64.Deploy.0 = Debug|x64 43 | {B0448317-E45D-434D-BC9B-FA129A974110}.Debug|x86.ActiveCfg = Debug|x86 44 | {B0448317-E45D-434D-BC9B-FA129A974110}.Debug|x86.Build.0 = Debug|x86 45 | {B0448317-E45D-434D-BC9B-FA129A974110}.Debug|x86.Deploy.0 = Debug|x86 46 | {B0448317-E45D-434D-BC9B-FA129A974110}.Release|Any CPU.ActiveCfg = Release|x86 47 | {B0448317-E45D-434D-BC9B-FA129A974110}.Release|ARM.ActiveCfg = Release|ARM 48 | {B0448317-E45D-434D-BC9B-FA129A974110}.Release|ARM.Build.0 = Release|ARM 49 | {B0448317-E45D-434D-BC9B-FA129A974110}.Release|ARM.Deploy.0 = Release|ARM 50 | {B0448317-E45D-434D-BC9B-FA129A974110}.Release|x64.ActiveCfg = Release|x64 51 | {B0448317-E45D-434D-BC9B-FA129A974110}.Release|x64.Build.0 = Release|x64 52 | {B0448317-E45D-434D-BC9B-FA129A974110}.Release|x64.Deploy.0 = Release|x64 53 | {B0448317-E45D-434D-BC9B-FA129A974110}.Release|x86.ActiveCfg = Release|x86 54 | {B0448317-E45D-434D-BC9B-FA129A974110}.Release|x86.Build.0 = Release|x86 55 | {B0448317-E45D-434D-BC9B-FA129A974110}.Release|x86.Deploy.0 = Release|x86 56 | EndGlobalSection 57 | GlobalSection(SolutionProperties) = preSolution 58 | HideSolutionNode = FALSE 59 | EndGlobalSection 60 | EndGlobal 61 | -------------------------------------------------------------------------------- /libsodium-uwp/CryptoHash.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SodiumCore.h" 3 | #include "internal.h" 4 | #include "CryptoHash.h" 5 | 6 | using namespace Sodium; 7 | using namespace Platform; 8 | using namespace Platform::Collections; 9 | using namespace Windows::Security::Cryptography; 10 | using namespace Windows::Security::Cryptography::Core; 11 | using namespace Windows::Storage::Streams; 12 | 13 | /// Calculates the SHA256 hash of the given input 14 | /// The message to generate a hash for 15 | /// 32 byte SHA256 hash of message 16 | Array^ Sodium::CryptoHash::Sha256(const Array^ message) 17 | { 18 | Array^ buffer = ref new Array(crypto_hash_sha256_BYTES); 19 | int result = crypto_hash_sha256( 20 | buffer->Data, 21 | message->Data, 22 | message->Length 23 | ); 24 | 25 | if (result == 0) { 26 | return buffer; 27 | } 28 | 29 | throw ref new Platform::Exception(result, "Unable to generate Sha256 hash"); 30 | } 31 | 32 | /// 33 | Array^ Sodium::CryptoHash::Sha256(String^ message) 34 | { 35 | return Sodium::CryptoHash::Sha256( 36 | Sodium::internal::StringToUnsignedCharArray(message) 37 | ); 38 | } 39 | 40 | /// Calculates the SHA512 hash of the given input 41 | /// The message to generate a hash for 42 | /// 64 byte SHA512 hash of message 43 | Array^ Sodium::CryptoHash::Sha512(const Array^ message) 44 | { 45 | Array^ buffer = ref new Array(crypto_hash_sha512_BYTES); 46 | int result = crypto_hash_sha512( 47 | buffer->Data, 48 | message->Data, 49 | message->Length 50 | ); 51 | 52 | if (result == 0) { 53 | return buffer; 54 | } 55 | 56 | throw ref new Platform::Exception(result, "Unable to generate Sha512 hash"); 57 | } 58 | 59 | /// 60 | Array^ Sodium::CryptoHash::Sha512(String^ message) 61 | { 62 | return Sodium::CryptoHash::Sha512( 63 | Sodium::internal::StringToUnsignedCharArray(message) 64 | ); 65 | } 66 | 67 | /// Calculates a hash of the given message using the default hashing algorithm in libsodium (SHA512) 68 | /// The message to generate a hash for 69 | /// 64 byte SHA512 hash of message 70 | Array^ Sodium::CryptoHash::Hash(const Array^ message) 71 | { 72 | Array^ buffer = ref new Array(crypto_hash_sha512_BYTES); 73 | int result = crypto_hash( 74 | buffer->Data, 75 | message->Data, 76 | message->Length 77 | ); 78 | 79 | if (result == 0) { 80 | return buffer; 81 | } 82 | 83 | throw ref new Platform::Exception(result, "Unable to generate Sha512 hash"); 84 | } 85 | 86 | /// 87 | Array^ Sodium::CryptoHash::Hash(String^ message) 88 | { 89 | return Sodium::CryptoHash::Hash( 90 | Sodium::internal::StringToUnsignedCharArray(message) 91 | ); 92 | } 93 | -------------------------------------------------------------------------------- /libsodium-uwp/CryptoHash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class CryptoHash sealed 13 | { 14 | public: 15 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 16 | static Array^ Sha256(const Array^ message); 17 | static Array^ Sha256(String^ message); 18 | 19 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 20 | static Array^ Sha512(const Array^ message); 21 | static Array^ Sha512(String^ message); 22 | 23 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 24 | static Array^ Hash(const Array^ message); 25 | static Array^ Hash(String^ message); 26 | }; 27 | } -------------------------------------------------------------------------------- /libsodium-uwp/DetachedBox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class DetachedBox sealed 13 | { 14 | public: 15 | DetachedBox(const Array^ Cipher, const Array^ Mac) 16 | { 17 | this->Cipher = Cipher; 18 | this->Mac = Mac; 19 | }; 20 | property Array^ Cipher; 21 | property Array^ Mac; 22 | }; 23 | } -------------------------------------------------------------------------------- /libsodium-uwp/Extern.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Extern.h" 3 | 4 | using namespace Platform; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Storage::Streams; 7 | 8 | extern "C" bool GenerateRandomBytes(unsigned char *bytes, unsigned int length) 9 | { 10 | IBuffer^ buffer = CryptographicBuffer::GenerateRandom(length); 11 | DataReader^ reader = DataReader::FromBuffer(buffer); 12 | reader->ReadBytes(ArrayReference(bytes, buffer->Length)); 13 | 14 | return true; 15 | } -------------------------------------------------------------------------------- /libsodium-uwp/Extern.h: -------------------------------------------------------------------------------- 1 | extern "C" bool GenerateRandomBytes(unsigned char *buffer, unsigned int length); -------------------------------------------------------------------------------- /libsodium-uwp/GenericHash.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SodiumCore.h" 3 | #include "internal.h" 4 | #include "GenericHash.h" 5 | 6 | using namespace Sodium; 7 | using namespace Platform; 8 | using namespace Platform::Collections; 9 | using namespace Windows::Security::Cryptography; 10 | using namespace Windows::Security::Cryptography::Core; 11 | using namespace Windows::Storage::Streams; 12 | 13 | 14 | /// Appends data to the generic hash state 15 | /// The data to append 16 | void Sodium::GenericHash::Append(IBuffer^ data) 17 | { 18 | Array^ d = ref new Array(data->Length); 19 | CryptographicBuffer::CopyToByteArray(data, &d); 20 | 21 | crypto_generichash_state state; 22 | memcpy(&state, this->state->Data, this->state_len); 23 | 24 | int result = crypto_generichash_update( 25 | &state, 26 | d->Data, 27 | d->Length 28 | ); 29 | 30 | Array^ s = ref new Array(sizeof state); 31 | memcpy(s->Data, &state, sizeof state); 32 | sodium_memzero(&state, sizeof state); 33 | 34 | this->state = s; 35 | } 36 | 37 | /// Finalizes the generic hash state 38 | /// Returns the hash with the originally request length 39 | Array^ Sodium::GenericHash::GetValueAndReset() 40 | { 41 | Array^ hash = ref new Array(this->bytes); 42 | 43 | crypto_generichash_state state; 44 | memcpy(&state, this->state->Data, this->state_len); 45 | 46 | int result = crypto_generichash_final( 47 | &state, 48 | hash->Data, 49 | hash->Length 50 | ); 51 | 52 | sodium_memzero(&state, sizeof state); 53 | 54 | return hash; 55 | } 56 | 57 | /// 64 byte key 58 | Array^ Sodium::GenericHash::GenerateKey() 59 | { 60 | return Sodium::Core::GetRandomBytes(crypto_generichash_KEYBYTES_MAX); 61 | } 62 | 63 | /// Hashes a message with Blake2 64 | /// The message to hash 65 | /// The key to hash the message with 66 | /// The length of the hash 67 | /// A generic hash, bytes length in bytes 68 | Array^ Sodium::GenericHash::Hash(const Array^ message, const Array^ key, int bytes) 69 | { 70 | // Validate key length 71 | if (key == nullptr || key->Length == 0) { 72 | key = nullptr; 73 | } else { 74 | if (key->Length > crypto_generichash_KEYBYTES_MAX || key->Length < crypto_generichash_KEYBYTES_MIN) { 75 | throw ref new Platform::InvalidArgumentException("Key must be between " + crypto_generichash_KEYBYTES_MIN + " and " + crypto_generichash_KEYBYTES_MAX + " bytes in length"); 76 | } 77 | } 78 | 79 | if (bytes > crypto_generichash_BYTES_MAX || bytes < crypto_generichash_BYTES_MIN) { 80 | throw ref new Platform::InvalidArgumentException("Bytes must be between " + crypto_generichash_BYTES_MIN + " and " + crypto_generichash_BYTES_MAX + " bytes in length"); 81 | } 82 | 83 | Array^ buffer = ref new Array(bytes); 84 | int result = crypto_generichash( 85 | buffer->Data, 86 | buffer->Length, 87 | message->Data, 88 | message->Length, 89 | (key == nullptr ? NULL : key->Data), 90 | (key == nullptr ? 0 : key->Length) 91 | ); 92 | 93 | return buffer; 94 | } 95 | 96 | 97 | /// Hashes a message with Blake2 98 | /// The message to hash 99 | /// The key to hash the message with 100 | /// The length of the hash 101 | /// A generic hash, bytes length in bytes 102 | Array^ Sodium::GenericHash::Hash(String^ message, const Array^ key, int bytes) 103 | { 104 | return Sodium::GenericHash::Hash( 105 | Sodium::internal::StringToUnsignedCharArray(message), 106 | key, 107 | bytes 108 | ); 109 | } 110 | 111 | /// Hashes a message with Blake2 112 | /// The message to hash 113 | /// The key to hash the message with 114 | /// 32 byte hash 115 | Array^ Sodium::GenericHash::Hash(const Array^ message, const Array^ key) 116 | { 117 | return Sodium::GenericHash::Hash( 118 | message, 119 | key, 120 | crypto_generichash_BYTES 121 | ); 122 | } 123 | 124 | /// Hashes a message with Blake2 125 | /// The message to hash 126 | /// The key to hash the message with 127 | /// 32 byte hash 128 | Array^ Sodium::GenericHash::Hash(String^ message, const Array^ key) 129 | { 130 | return Sodium::GenericHash::Hash( 131 | Sodium::internal::StringToUnsignedCharArray(message), 132 | key, 133 | crypto_generichash_BYTES 134 | ); 135 | } 136 | 137 | /// Hashes a message with Blake2 138 | /// The message to hash 139 | /// 32 byte hash 140 | Array^ Sodium::GenericHash::Hash(const Array^ message) 141 | { 142 | return Sodium::GenericHash::Hash( 143 | message, 144 | nullptr, 145 | crypto_generichash_BYTES 146 | ); 147 | } 148 | 149 | /// Hashes a message with Blake2 150 | /// The message to hash 151 | /// 32 byte hash 152 | Array^ Sodium::GenericHash::Hash(String^ message) 153 | { 154 | return Sodium::GenericHash::Hash( 155 | Sodium::internal::StringToUnsignedCharArray(message), 156 | nullptr, 157 | crypto_generichash_BYTES 158 | ); 159 | } 160 | 161 | /// Opens the specified algorithm for use with GenericHash 162 | /// The selected algorithm for GenericHashAlgorithmProvider 163 | /// A new GenericHashAlgorithmProvider instance with the provided algorithm 164 | GenericHashAlgorithmProvider^ Sodium::GenericHashAlgorithmProvider::OpenAlgorithm(String^ algorithm) 165 | { 166 | return ref new GenericHashAlgorithmProvider(algorithm); 167 | } 168 | 169 | /// Creates a new GenericHash object 170 | /// Returns a GenericHashObject with a given key, set to 32 bytes in length 171 | GenericHash^ Sodium::GenericHashAlgorithmProvider::CreateHash() 172 | { 173 | return this->CreateHash(nullptr, crypto_generichash_BYTES); 174 | } 175 | 176 | /// Creates a new GenericHash object 177 | /// The raw key data 178 | /// Returns a GenericHashObject with a null key, set to 32 bytes in length 179 | GenericHash^ Sodium::GenericHashAlgorithmProvider::CreateHash(const Array^ key) 180 | { 181 | return this->CreateHash(key, crypto_generichash_BYTES); 182 | } 183 | 184 | /// Creates a new GenericHash object 185 | /// The raw key data 186 | /// The number of bytes to use with Blake2 187 | /// Returns a GenericHashObject 188 | GenericHash^ Sodium::GenericHashAlgorithmProvider::CreateHash(const Array^ key, int bytes) 189 | { 190 | return ref new GenericHash(key, bytes); 191 | } 192 | -------------------------------------------------------------------------------- /libsodium-uwp/GenericHash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class GenericHash sealed 13 | { 14 | private: 15 | property int bytes; 16 | property Array^ state; 17 | property size_t state_len; 18 | 19 | public: 20 | GenericHash(const Array^ key, int bytes) 21 | { 22 | // Validate key length 23 | if (key == nullptr || key->Length == 0) { 24 | key = nullptr; 25 | } else { 26 | if (key->Length > crypto_generichash_KEYBYTES_MAX || key->Length < crypto_generichash_KEYBYTES_MIN) { 27 | throw ref new Platform::InvalidArgumentException("Key must be between " + crypto_generichash_KEYBYTES_MIN + " and " + crypto_generichash_KEYBYTES_MAX + " bytes in length"); 28 | } 29 | } 30 | 31 | if (bytes > crypto_generichash_BYTES_MAX || bytes < crypto_generichash_BYTES_MIN) { 32 | throw ref new Platform::InvalidArgumentException("Bytes must be between " + crypto_generichash_BYTES_MIN + " and " + crypto_generichash_BYTES_MAX + " bytes in length"); 33 | } 34 | 35 | this->bytes = bytes; 36 | 37 | crypto_generichash_state state; 38 | int state_len = sizeof(state); 39 | 40 | int result = crypto_generichash_init( 41 | &state, 42 | (key == nullptr ? NULL : key->Data), 43 | (key == nullptr ? 0 : key->Length), 44 | this->bytes 45 | ); 46 | 47 | Array^ s = ref new Array(state_len); 48 | memcpy(s->Data, &state, state_len); 49 | 50 | this->state = s; 51 | this->state_len = state_len; 52 | } 53 | 54 | // Class methods 55 | void Append(IBuffer^ data); 56 | Array^ GetValueAndReset(); 57 | 58 | // Static methods 59 | static Array^ GenerateKey(); 60 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 61 | static Array^ Hash(const Array^ message, const Array^ key, int bytes); 62 | static Array^ Hash(String^ message, const Array^ key, int bytes); 63 | 64 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 65 | static Array^ Hash(const Array^ message, const Array^ key); 66 | static Array^ Hash(String^ message, const Array^ key); 67 | 68 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 69 | static Array^ Hash(const Array^ message); 70 | static Array^ Hash(String^ message); 71 | }; 72 | 73 | public ref class GenericHashAlgorithmNames sealed 74 | { 75 | public: 76 | static property String^ Blake2 77 | { 78 | String^ get() { return "Blake2"; } 79 | } 80 | }; 81 | 82 | public ref class GenericHashAlgorithmProvider sealed 83 | { 84 | private: 85 | String^ algorithm; 86 | 87 | public: 88 | GenericHashAlgorithmProvider(String^ algorithm) { 89 | if (algorithm != GenericHashAlgorithmNames::Blake2) { 90 | throw ref new Platform::InvalidArgumentException("GenericHashAlgorithmProvider expects the algorithm to be 'Blake2'"); 91 | } 92 | 93 | this->algorithm = algorithm; 94 | } 95 | 96 | static GenericHashAlgorithmProvider^ OpenAlgorithm(String^ algorithm); 97 | GenericHash^ CreateHash(); 98 | GenericHash^ CreateHash(const Array^ key); 99 | GenericHash^ CreateHash(const Array^ key, int bytes); 100 | }; 101 | } -------------------------------------------------------------------------------- /libsodium-uwp/KDF.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "PasswordHash.h" 3 | 4 | using namespace Platform; 5 | using namespace Platform::Collections; 6 | using namespace Windows::Security::Cryptography; 7 | using namespace Windows::Security::Cryptography::Core; 8 | using namespace Windows::Storage::Streams; 9 | using namespace Windows::Foundation::Collections; 10 | 11 | namespace Sodium 12 | { 13 | public ref class KDF sealed 14 | { 15 | private: 16 | static IBuffer^ extract(IBuffer^ salt, IBuffer^ ikm, MacAlgorithmProvider^ provider); 17 | static IBuffer^ expand(IBuffer^ prk, const Array^ info, int l, MacAlgorithmProvider^ provider); 18 | static IBuffer^ HMAC(IBuffer^ key, IBuffer^ message, MacAlgorithmProvider^ provider); 19 | public: 20 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 21 | static Array^ PBKDF2(String^ algorithm, String^ password, const Array^ salt, int iterationCount, int targetSize); 22 | static Array^ PBKDF2(String^ algorithm, String^ password, String^ salt, int iterationCount, int targetSize); 23 | 24 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 25 | static Array^ HKDF(String^ algorithm, const Array^ ikm, const Array^ salt, const Array^ info, int outputLength); 26 | static Array^ HKDF(String^ algorithm, const Array^ ikm, const Array^ salt, String^ info, int outputLength); 27 | static Array^ HSalsa20(const Array^ in, const Array^ k, const Array^ c); 28 | 29 | static Array^ Argon2i(String^ password, const Array^ salt, PasswordHashOptions options); 30 | static Array^ Argon2i(String^ password, PasswordHashOptions options); 31 | 32 | static Array^ Scrypt(String^ password, const Array^ salt, PasswordHashOptions options); 33 | static Array^ Scrypt(String^ password, PasswordHashOptions options); 34 | }; 35 | } -------------------------------------------------------------------------------- /libsodium-uwp/KeyPair.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class KeyPair sealed 13 | { 14 | public: 15 | KeyPair(const Array^ Public, const Array^ Secret) 16 | { 17 | this->Public = Public; 18 | this->Secret = Secret; 19 | }; 20 | KeyPair() {}; 21 | property Array^ Public; 22 | property Array^ Secret; 23 | }; 24 | } -------------------------------------------------------------------------------- /libsodium-uwp/OneTimeAuth.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SodiumCore.h" 3 | #include "internal.h" 4 | #include "OneTimeAuth.h" 5 | 6 | using namespace Sodium; 7 | using namespace Platform; 8 | using namespace Platform::Collections; 9 | using namespace Windows::Security::Cryptography; 10 | using namespace Windows::Security::Cryptography::Core; 11 | using namespace Windows::Storage::Streams; 12 | 13 | /// Returns a 32 byte key for One-Time Authentication 14 | Array^ Sodium::OneTimeAuth::GenerateKey() 15 | { 16 | return Sodium::Core::GetRandomBytes(crypto_onetimeauth_KEYBYTES); 17 | } 18 | 19 | /// Signs a message with a 32 byte key 20 | /// The message to sign 21 | /// A 32 byte key to sign the message with 22 | /// Returns a 16 byte signature 23 | Array^ Sodium::OneTimeAuth::Sign(const Array^ message, const Array^ key) 24 | { 25 | if (key->Length != crypto_onetimeauth_KEYBYTES) { 26 | throw ref new Platform::InvalidArgumentException("key must be " + crypto_onetimeauth_KEYBYTES + " bytes in length"); 27 | } 28 | 29 | Array^ buffer = ref new Array(crypto_onetimeauth_BYTES); 30 | int result = crypto_onetimeauth( 31 | buffer->Data, 32 | message->Data, 33 | message->Length, 34 | key->Data 35 | ); 36 | 37 | return buffer; 38 | } 39 | 40 | /// Signs a message with a 32 byte key 41 | /// The message to sign 42 | /// A 32 byte key to sign the message with 43 | /// Returns a 16 byte signature 44 | Array^ Sodium::OneTimeAuth::Sign(String^ message, const Array^ key) 45 | { 46 | return Sodium::OneTimeAuth::Sign( 47 | Sodium::internal::StringToUnsignedCharArray(message), 48 | key 49 | ); 50 | } 51 | 52 | /// Verifies a signature created by Sodoium.OneTimeAuth.Sign 53 | /// The message to verify 54 | /// The 16 byte signature 55 | /// A 32 byte key to sign the message with 56 | /// Returns true of the signature is valid 57 | bool Sodium::OneTimeAuth::Verify(const Array^ message, const Array^ signature, const Array^ key) 58 | { 59 | if (key->Length != crypto_onetimeauth_KEYBYTES) { 60 | throw ref new Platform::InvalidArgumentException("key must be " + crypto_onetimeauth_KEYBYTES + " bytes in length"); 61 | } 62 | 63 | if (signature->Length != crypto_onetimeauth_BYTES) { 64 | throw ref new Platform::InvalidArgumentException("signature must be " + crypto_onetimeauth_BYTES + " bytes in length"); 65 | } 66 | 67 | int result = crypto_onetimeauth_verify( 68 | signature->Data, 69 | message->Data, 70 | message->Length, 71 | key->Data 72 | ); 73 | 74 | return result == 0; 75 | } 76 | 77 | /// Verifies a signature created by Sodoium.OneTimeAuth.Sign 78 | /// The message to verify 79 | /// The 16 byte signature 80 | /// A 32 byte key to sign the message with 81 | /// Returns true of the signature is valid 82 | bool Sodium::OneTimeAuth::Verify(String^ message, const Array^ signature, const Array^ key) 83 | { 84 | return Sodium::OneTimeAuth::Verify( 85 | Sodium::internal::StringToUnsignedCharArray(message), 86 | signature, 87 | key 88 | ); 89 | } -------------------------------------------------------------------------------- /libsodium-uwp/OneTimeAuth.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class OneTimeAuth sealed 13 | { 14 | public: 15 | static Array^ GenerateKey(); 16 | 17 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 18 | static Array^ Sign(const Array^ message, const Array^ key); 19 | static Array^ Sign(String^ message, const Array^ key); 20 | 21 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 22 | static bool Verify(const Array^ message, const Array^ signature, const Array^ key); 23 | static bool Verify(String^ message, const Array^ signature, const Array^ key); 24 | }; 25 | } -------------------------------------------------------------------------------- /libsodium-uwp/PasswordHash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | 4 | using namespace Platform; 5 | using namespace Platform::Collections; 6 | using namespace Windows::Security::Cryptography; 7 | using namespace Windows::Security::Cryptography::Core; 8 | using namespace Windows::Storage::Streams; 9 | using namespace Windows::Foundation::Collections; 10 | 11 | namespace Sodium 12 | { 13 | public value struct PasswordHashOptions 14 | { 15 | public: 16 | int memory_cost; 17 | int time_cost; 18 | }; 19 | 20 | public ref class PasswordHash sealed 21 | { 22 | private: 23 | static int DetermineAlgorithm(String^ hash); 24 | 25 | static String^ HashArgon2i(String^ password, PasswordHashOptions options, int algorithm = PasswordHash::Argon2id); 26 | static String^ HashScrypt(String^ password, PasswordHashOptions options); 27 | 28 | static bool VerifyArgon2i(String^ hash, String^ password); 29 | static bool VerifyScrypt(String^ hash, String^ password); 30 | 31 | public: 32 | static property int Argon2i 33 | { 34 | int get() { return crypto_pwhash_ALG_ARGON2I13; } 35 | }; 36 | 37 | static property int Argon2id 38 | { 39 | int get() { return crypto_pwhash_ALG_ARGON2ID13; } 40 | } 41 | 42 | static property int Scrypt 43 | { 44 | int get() { return 5; } 45 | }; 46 | 47 | static String^ Hash(String^ password, int algorithm, PasswordHashOptions options); 48 | static bool Verify(String^ hash, String^ password); 49 | static bool NeedsRehash(String^ hash, PasswordHashOptions options); 50 | static PasswordHashOptions CreateOptions(int memory_cost, int time_cost); 51 | }; 52 | } -------------------------------------------------------------------------------- /libsodium-uwp/PublicKeyAuth.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "KeyPair.h" 3 | 4 | using namespace Platform; 5 | using namespace Platform::Collections; 6 | using namespace Windows::Security::Cryptography; 7 | using namespace Windows::Security::Cryptography::Core; 8 | using namespace Windows::Storage::Streams; 9 | using namespace Windows::Foundation::Collections; 10 | 11 | namespace Sodium 12 | { 13 | public ref class PublicKeyAuth sealed 14 | { 15 | private: 16 | property Array^ state; 17 | property size_t state_len; 18 | 19 | public: 20 | PublicKeyAuth() 21 | { 22 | crypto_sign_state state; 23 | 24 | int result = crypto_sign_init(&state); 25 | 26 | Array^ s = ref new Array(sizeof state); 27 | memcpy(s->Data, &state, sizeof state); 28 | this->state = s; 29 | this->state_len = sizeof state; 30 | sodium_memzero(&state, sizeof state); 31 | } 32 | 33 | // Class methods 34 | void Append(IBuffer^ data); 35 | Array^ GetValueAndReset(const Array^ secretKey); 36 | bool GetValueAndVerify(const Array^ signature, const Array^ publicKey); 37 | 38 | static KeyPair^ GenerateKeyPair(); 39 | static KeyPair^ GenerateKeyPair(const Array^ seed); 40 | 41 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 42 | static Array^ Sign(const Array^ message, const Array^ privateKey); 43 | static Array^ Sign(String^ message, const Array^ privateKey); 44 | static Array^ Verify(const Array^ signedMessage, const Array^ publicKey); 45 | static Array^ ConvertEd25519PublicKeyToCurve25519PublicKey(const Array^ publicKey); 46 | static Array^ ConvertEd25519SecretKeyToCurve25519SecretKey(const Array^ privateKey); 47 | 48 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 49 | static Array^ SignDetached(const Array^ message, const Array^ secretKey); 50 | static Array^ SignDetached(String^ message, const Array^ secretKey); 51 | 52 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 53 | static bool VerifyDetached(const Array^ signature, const Array^ message, const Array^ publicKey); 54 | static bool VerifyDetached(const Array^ signature, String^ message, const Array^ publicKey); 55 | static Array^ ExtractEd25519SeedFromEd25519SecretKey(const Array^ ed25519SecretKey); 56 | static Array^ ExtractEd25519PublicKeyFromEd25519SecretKey(const Array^ ed25519SecretKey); 57 | }; 58 | } -------------------------------------------------------------------------------- /libsodium-uwp/PublicKeyBox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "KeyPair.h" 3 | #include "DetachedBox.h" 4 | 5 | using namespace Platform; 6 | using namespace Platform::Collections; 7 | using namespace Windows::Security::Cryptography; 8 | using namespace Windows::Security::Cryptography::Core; 9 | using namespace Windows::Storage::Streams; 10 | using namespace Windows::Foundation::Collections; 11 | 12 | namespace Sodium 13 | { 14 | public ref class PublicKeyBox sealed 15 | { 16 | public: 17 | static Array^ GenerateNonce(); 18 | static KeyPair^ GenerateKeyPair(); 19 | static KeyPair^ GenerateKeyPair(const Array^ privateKey); 20 | 21 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 22 | static Array^ Create(const Array^ message, const Array^ nonce, const Array^ secretKey, const Array^ publicKey); 23 | static Array^ Create(String^ message, const Array^ nonce, const Array^ secretKey, const Array^ publicKey); 24 | static Array^ Open(const Array^ cipherText, const Array^ nonce, const Array^ secretKey, const Array^ publicKey); 25 | 26 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 27 | static DetachedBox^ CreateDetached(const Array^ message, const Array^ nonce, const Array^ secretKey, const Array^ publicKey); 28 | static DetachedBox^ CreateDetached(String^ message, const Array^ nonce, const Array^ secretKey, const Array^ publicKey); 29 | 30 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 31 | static Array^ OpenDetached(const Array^ cipherText, const Array^ mac, const Array^ nonce, const Array^ secretKey, const Array^ publicKey); 32 | static Array^ OpenDetached(String^ cipherText, const Array^ mac, const Array^ nonce, const Array^ secretKey, const Array^ publicKey); 33 | static Array^ OpenDetached(DetachedBox^ detached, const Array^ nonce, const Array^ secretKey, const Array^ publicKey); 34 | }; 35 | } -------------------------------------------------------------------------------- /libsodium-uwp/ScalarMult.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ScalarMult.h" 3 | #include "SodiumCore.h" 4 | 5 | using namespace Sodium; 6 | using namespace Platform; 7 | using namespace Platform::Collections; 8 | using namespace Windows::Security::Cryptography; 9 | using namespace Windows::Security::Cryptography::Core; 10 | using namespace Windows::Storage::Streams; 11 | 12 | int Sodium::ScalarMult::Bytes() 13 | { 14 | return (int)crypto_scalarmult_bytes(); 15 | } 16 | 17 | int Sodium::ScalarMult::ScalarBytes() 18 | { 19 | return (int)crypto_scalarmult_scalarbytes(); 20 | } 21 | 22 | /// Extracts the public key from the secret key 23 | /// The secret key 24 | /// 32 byte public key 25 | Array^ Sodium::ScalarMult::Base(const Array^ secretKey) 26 | { 27 | if (secretKey->Length != crypto_scalarmult_SCALARBYTES) { 28 | throw ref new Platform::InvalidArgumentException("SecretKey must be " + crypto_scalarmult_SCALARBYTES + " bytes in length"); 29 | } 30 | 31 | Array^ publicKey = ref new Array(crypto_scalarmult_SCALARBYTES); 32 | int result = crypto_scalarmult_base( 33 | publicKey->Data, 34 | secretKey->Data 35 | ); 36 | 37 | if (result == 0) { 38 | return publicKey; 39 | } 40 | 41 | throw ref new Platform::Exception(result, "Failed to compute public key"); 42 | } 43 | 44 | /// Computes a shared secret between a secret and public key 45 | /// The secret key 46 | /// The public key 47 | /// 32 byte shared secret 48 | Array^ Sodium::ScalarMult::Mult(const Array^ secretKey, const Array^ publicKey) 49 | { 50 | if (secretKey->Length != crypto_scalarmult_SCALARBYTES) { 51 | throw ref new Platform::InvalidArgumentException("SecretKey must be " + crypto_scalarmult_SCALARBYTES + " bytes in length"); 52 | } 53 | 54 | if (publicKey->Length != crypto_scalarmult_BYTES) { 55 | throw ref new Platform::InvalidArgumentException("PublicKey must be " + crypto_scalarmult_BYTES + " bytes in length"); 56 | } 57 | 58 | Array^ sharedSecret = ref new Array(crypto_scalarmult_SCALARBYTES); 59 | 60 | int result = crypto_scalarmult( 61 | sharedSecret->Data, 62 | secretKey->Data, 63 | publicKey->Data 64 | ); 65 | 66 | if (result == 0) { 67 | return sharedSecret; 68 | } 69 | 70 | throw ref new Platform::Exception(result, "Failed to compute shared secret"); 71 | } -------------------------------------------------------------------------------- /libsodium-uwp/ScalarMult.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class ScalarMult sealed 13 | { 14 | public: 15 | static int Bytes(); 16 | static int ScalarBytes(); 17 | static Array^ Base(const Array^ secretKey); 18 | static Array^ Mult(const Array^ secretKey, const Array^ publicKey); 19 | }; 20 | } -------------------------------------------------------------------------------- /libsodium-uwp/SealedPublicKeyBox.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SodiumCore.h" 3 | #include "internal.h" 4 | #include "SealedPublicKeyBox.h" 5 | #include "KeyPair.h" 6 | 7 | using namespace Sodium; 8 | using namespace Platform; 9 | using namespace Platform::Collections; 10 | using namespace Windows::Security::Cryptography; 11 | using namespace Windows::Security::Cryptography::Core; 12 | using namespace Windows::Storage::Streams; 13 | 14 | /// Creates a sealed public key box 15 | /// The message to encrypt 16 | /// A 32 byte key 17 | /// The encrypted message 18 | Array^ Sodium::SealedPublicKeyBox::Create(const Array^ message, const Array^ recipientPublicKey) 19 | { 20 | if (recipientPublicKey->Length != crypto_box_PUBLICKEYBYTES) { 21 | throw ref new Platform::InvalidArgumentException("Recipient public key must be " + crypto_box_PUBLICKEYBYTES + " bytes in length"); 22 | } 23 | 24 | Array^ buffer = ref new Array(message->Length + crypto_box_SEALBYTES); 25 | int result = crypto_box_seal( 26 | buffer->Data, 27 | message->Data, 28 | message->Length, 29 | recipientPublicKey->Data 30 | ); 31 | 32 | if (result == 0) { 33 | return buffer; 34 | } 35 | 36 | throw ref new Platform::Exception(result, "Failed to create SealedPublicKeyBox"); 37 | } 38 | 39 | /// Creates a sealed public key box 40 | /// The message to encrypt 41 | /// A 32 byte key 42 | /// The encrypted message 43 | Array^ Sodium::SealedPublicKeyBox::Create(String^ message, const Array^ recipientPublicKey) 44 | { 45 | return Sodium::SealedPublicKeyBox::Create( 46 | Sodium::internal::StringToUnsignedCharArray(message), 47 | recipientPublicKey 48 | ); 49 | } 50 | 51 | /// Creates a sealed public key box 52 | /// The message to encrypt 53 | /// A KeyPair containing the public key 54 | /// The encrypted message 55 | Array^ Sodium::SealedPublicKeyBox::Create(const Array^ message, KeyPair^ recipientKeyPair) 56 | { 57 | return Sodium::SealedPublicKeyBox::Create( 58 | message, 59 | recipientKeyPair->Public 60 | ); 61 | } 62 | 63 | /// Creates a sealed public key box 64 | /// The message to encrypt 65 | /// A KeyPair containing the public key 66 | /// The encrypted message 67 | Array^ Sodium::SealedPublicKeyBox::Create(String^ message, KeyPair^ recipientKeyPair) 68 | { 69 | return Sodium::SealedPublicKeyBox::Create( 70 | Sodium::internal::StringToUnsignedCharArray(message), 71 | recipientKeyPair 72 | ); 73 | } 74 | 75 | /// Opens a sealed public key box 76 | /// The cipherTect to decrypt 77 | /// The recipient secret key 78 | /// The recipient public key 79 | /// The dencrypted message 80 | Array^ Sodium::SealedPublicKeyBox::Open(const Array^ cipherText, const Array^ recipientSecretKey, const Array^ recipientPublicKey) 81 | { 82 | if (recipientPublicKey->Length != crypto_box_PUBLICKEYBYTES) { 83 | throw ref new Platform::InvalidArgumentException("Recipient public key must be " + crypto_box_PUBLICKEYBYTES + "bytes in length"); 84 | } 85 | 86 | if (recipientSecretKey->Length != crypto_box_SECRETKEYBYTES) { 87 | throw ref new Platform::InvalidArgumentException("Recipient secret key must be " + crypto_box_SECRETKEYBYTES + " bytes in length"); 88 | } 89 | 90 | Array^ buffer = ref new Array(cipherText->Length - crypto_box_SEALBYTES); 91 | 92 | int result = crypto_box_seal_open( 93 | buffer->Data, 94 | cipherText->Data, 95 | cipherText->Length, 96 | recipientPublicKey->Data, 97 | recipientSecretKey->Data 98 | ); 99 | 100 | if (result == 0) { 101 | return buffer; 102 | } 103 | 104 | throw ref new Platform::Exception(result, "Failed to open SealedPublicKeyBox"); 105 | } 106 | 107 | /// Opens a sealed public key box 108 | /// The cipherTect to decrypt 109 | /// The recipient key pair 110 | /// The dencrypted message 111 | Array^ Sodium::SealedPublicKeyBox::Open(const Array^ cipherText, KeyPair^ recipientKeyPair) 112 | { 113 | return Sodium::SealedPublicKeyBox::Create(cipherText, recipientKeyPair->Public); 114 | } 115 | -------------------------------------------------------------------------------- /libsodium-uwp/SealedPublicKeyBox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "KeyPair.h" 3 | 4 | using namespace Platform; 5 | using namespace Platform::Collections; 6 | using namespace Windows::Security::Cryptography; 7 | using namespace Windows::Security::Cryptography::Core; 8 | using namespace Windows::Storage::Streams; 9 | using namespace Windows::Foundation::Collections; 10 | 11 | namespace Sodium 12 | { 13 | public ref class SealedPublicKeyBox sealed 14 | { 15 | public: 16 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 17 | static Array^ Create(const Array^ message, const Array^ recipientPublicKey); 18 | static Array^ Create(String^ message, const Array^ recipientPublicKey); 19 | static Array^ Create(const Array^ message, KeyPair^ recipientKeyPair); 20 | static Array^ Create(String^ message, KeyPair^ recipientKeyPair); 21 | static Array^ Open(const Array^ cipherText, const Array^ recipientSecretKey, const Array^ recipientPublicKey); 22 | static Array^ Open(const Array^ cipherText, KeyPair^ recipientKeyPair); 23 | }; 24 | } -------------------------------------------------------------------------------- /libsodium-uwp/SecretAead.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class SecretAead sealed 13 | { 14 | public: 15 | static Array^ GenerateNonce(); 16 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 17 | static Array^ Encrypt(const Array^ message, const Array^ nonce, const Array^ key); 18 | static Array^ Encrypt(String^ message, const Array^ nonce, const Array^ key); 19 | 20 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 21 | static Array^ Encrypt(const Array^ message, const Array^ nonce, const Array^ key, const Array^ additionalData); 22 | static Array^ Encrypt(String^ message, const Array^ nonce, const Array^ key, const Array^ additionalData); 23 | 24 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 25 | static Array^ Decrypt(const Array^ encrypted, const Array^ nonce, const Array^ key); 26 | static Array^ Decrypt(const Array^ encrypted, const Array^ nonce, const Array^ key, const Array^ additionalData); 27 | }; 28 | } -------------------------------------------------------------------------------- /libsodium-uwp/SecretBox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "DetachedBox.h" 3 | 4 | using namespace Platform; 5 | using namespace Platform::Collections; 6 | using namespace Windows::Security::Cryptography; 7 | using namespace Windows::Security::Cryptography::Core; 8 | using namespace Windows::Storage::Streams; 9 | using namespace Windows::Foundation::Collections; 10 | 11 | namespace Sodium 12 | { 13 | public ref class SecretBox sealed 14 | { 15 | public: 16 | static Array^ GenerateNonce(); 17 | static Array^ GenerateKey(); 18 | 19 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 20 | static Array^ Create(const Array^ message, const Array^ nonce, const Array^ key); 21 | static Array^ Create(String^ message, const Array^ nonce, const Array^ key); 22 | static Array^ Open(const Array^ ciphertext, const Array^ nonce, const Array^ key); 23 | 24 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 25 | static DetachedBox^ CreateDetached(const Array^ message, const Array^ nonce, const Array^ key); 26 | static DetachedBox^ CreateDetached(String^ message, const Array^ nonce, const Array^ key); 27 | 28 | 29 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 30 | static Array^ OpenDetached(const Array^ cipherText, const Array^ mac, const Array^ nonce, const Array^ key); 31 | static Array^ OpenDetached(String^ cipherText, const Array^ mac, const Array^ nonce, const Array^ key); 32 | static Array^ OpenDetached(DetachedBox^ detached, const Array^ nonce, const Array^ key); 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /libsodium-uwp/SecretKeyAuth.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class SecretKeyAuth sealed 13 | { 14 | public: 15 | static Array^ GenerateKey(); 16 | 17 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 18 | static Array^ Sign(const Array^ message, const Array^ key); 19 | static Array^ Sign(String^ message, const Array^ key); 20 | 21 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 22 | static bool Verify(const Array^ message, const Array^ signature, const Array^ key); 23 | static bool Verify(String^ message, const Array^ signature, const Array^ key); 24 | 25 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 26 | static Array^ SignHmacSha256(const Array^ message, const Array^ key); 27 | static Array^ SignHmacSha256(String^ message, const Array^ key); 28 | 29 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 30 | static bool VerifyHmacSha256(const Array^ message, const Array^ signature, const Array^ key); 31 | static bool VerifyHmacSha256(String^ message, const Array^ signature, const Array^ key); 32 | 33 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 34 | static Array^ SignHmacSha512(const Array^ message, const Array^ key); 35 | static Array^ SignHmacSha512(String^ message, const Array^ key); 36 | 37 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 38 | static bool VerifyHmacSha512(const Array^ message, const Array^ signature, const Array^ key); 39 | static bool VerifyHmacSha512(String^ message, const Array^ signature, const Array^ key); 40 | }; 41 | } -------------------------------------------------------------------------------- /libsodium-uwp/SecretStream.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class SecretStream sealed 13 | { 14 | private: 15 | property Array^ state; 16 | property size_t state_len; 17 | 18 | int GetIndexFromTag(unsigned char tag); 19 | unsigned char GetTagFromIndex(int tag); 20 | 21 | public: 22 | SecretStream(const Array^ key, const Array^ header, int mode) { 23 | if (key == nullptr || key->Length == 0 || key->Length != crypto_secretstream_xchacha20poly1305_KEYBYTES) { 24 | throw ref new Platform::InvalidArgumentException("Key must be " + crypto_secretstream_xchacha20poly1305_KEYBYTES + " bytes in length."); 25 | } 26 | 27 | if (header == nullptr || header->Length == 0 || header->Length != crypto_secretstream_xchacha20poly1305_HEADERBYTES) { 28 | throw ref new Platform::InvalidArgumentException("Header must be " + crypto_secretstream_xchacha20poly1305_HEADERBYTES + " bytes in length."); 29 | } 30 | 31 | // Create an initial state, then initialize it with the header and key 32 | crypto_secretstream_xchacha20poly1305_state state; 33 | if (mode == MODE_PUSH) { 34 | if (crypto_secretstream_xchacha20poly1305_init_push(&state, header->Data, key->Data) != 0) { 35 | throw ref new Platform::InvalidArgumentException("The header or key provided was not valid"); 36 | } 37 | } else if (mode == MODE_PULL) { 38 | if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header->Data, key->Data) != 0) { 39 | throw ref new Platform::InvalidArgumentException("The header or key provided was not valid"); 40 | } 41 | } else { 42 | throw ref new Platform::InvalidArgumentException("Mode must be either push or pull."); 43 | } 44 | 45 | int state_len = sizeof(state); 46 | 47 | Array^ s = ref new Array(state_len); 48 | memcpy(s->Data, &state, state_len); 49 | 50 | this->state = s; 51 | this->state_len = state_len; 52 | } 53 | 54 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 55 | Array^ Push(const Array^ message); 56 | Array^ Push(String^ message); 57 | 58 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 59 | Array^ Push(const Array^ message, int tag); 60 | Array^ Push(String^ message, int tag); 61 | 62 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 63 | Array^ Push(const Array^ message, int tag, const Array^ additionalData); 64 | Array^ Push(String^ message, int tag, String^ additionalData); 65 | 66 | Array^ Pull(const Array^ ciphertext, int *tag); 67 | 68 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 69 | Array^ Pull(const Array^ ciphertext, int *tag, const Array^ additionalData); 70 | Array^ Pull(const Array^ ciphertext, int *tag, String^ additionalData); 71 | 72 | void Rekey(); 73 | 74 | static Array^ GenerateKey(); 75 | static Array^ GenerateHeader(); 76 | 77 | static property int TAG_MESSAGE 78 | { 79 | int get() { return 0; } 80 | }; 81 | 82 | static property int TAG_PUSH 83 | { 84 | int get() { return 1; } 85 | }; 86 | 87 | static property int TAG_REKEY 88 | { 89 | int get() { return 2; } 90 | }; 91 | 92 | static property int TAG_FINAL 93 | { 94 | int get() { return 3; } 95 | }; 96 | 97 | static property int MODE_PUSH 98 | { 99 | int get() { return 0; } 100 | }; 101 | 102 | static property int MODE_PULL 103 | { 104 | int get() { return 1; } 105 | }; 106 | }; 107 | } -------------------------------------------------------------------------------- /libsodium-uwp/ShortHash.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SodiumCore.h" 3 | #include "internal.h" 4 | #include "ShortHash.h" 5 | 6 | using namespace Sodium; 7 | using namespace Platform; 8 | using namespace Platform::Collections; 9 | using namespace Windows::Security::Cryptography; 10 | using namespace Windows::Security::Cryptography::Core; 11 | using namespace Windows::Storage::Streams; 12 | 13 | /// 16 byte key 14 | Array^ Sodium::ShortHash::GenerateKey() 15 | { 16 | return Sodium::Core::GetRandomBytes(crypto_shorthash_KEYBYTES); 17 | } 18 | 19 | /// Generates a short SIP-2-4 hash of the given message 20 | /// The message to hash 21 | /// A 32 byte key 22 | /// An 8 byte hash 23 | Array^ Sodium::ShortHash::Hash(const Array^ message, const Array^ key) 24 | { 25 | if (key->Length != crypto_shorthash_KEYBYTES) { 26 | throw ref new Platform::InvalidArgumentException("key must be " + crypto_shorthash_KEYBYTES + " bytes in length"); 27 | } 28 | 29 | Array^ buffer = ref new Array(crypto_shorthash_BYTES); 30 | 31 | int result = crypto_shorthash( 32 | buffer->Data, 33 | message->Data, 34 | message->Length, 35 | key->Data 36 | ); 37 | 38 | return buffer; 39 | } 40 | 41 | /// Generates a short SIP-2-4 hash of the given message 42 | /// The message to hash 43 | /// A 32 byte key 44 | /// An 8 byte hash 45 | Array^ Sodium::ShortHash::Hash(String^ message, const Array^ key) 46 | { 47 | return Sodium::ShortHash::Hash( 48 | Sodium::internal::StringToUnsignedCharArray(message), 49 | key 50 | ); 51 | } 52 | 53 | /// Generates a short SIP-2-4 hash of the given message 54 | /// The message to hash 55 | /// A 32 byte key 56 | /// An 8 byte hash 57 | Array^ Sodium::ShortHash::Hash(String^ message, String^ key) 58 | { 59 | return Sodium::ShortHash::Hash( 60 | message, 61 | Sodium::internal::StringToUnsignedCharArray(key) 62 | ); 63 | } -------------------------------------------------------------------------------- /libsodium-uwp/ShortHash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class ShortHash sealed 13 | { 14 | public: 15 | static Array^ GenerateKey(); 16 | 17 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 18 | static Array^ Hash(const Array^ message, const Array^ key); 19 | static Array^ Hash(String^ message, const Array^ key); 20 | static Array^ Hash(String^ message, String^ key); 21 | }; 22 | } -------------------------------------------------------------------------------- /libsodium-uwp/SodiumCore.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SodiumCore.h" 3 | 4 | using namespace Sodium; 5 | using namespace Platform; 6 | using namespace Platform::Collections; 7 | using namespace Windows::Security::Cryptography; 8 | using namespace Windows::Security::Cryptography::Core; 9 | using namespace Windows::Storage::Streams; 10 | 11 | /// Returns the current version string of libsodium 12 | String^ Sodium::Core::SodiumVersionString() 13 | { 14 | return SODIUM_VERSION_STRING; 15 | } 16 | 17 | /// The number of bytes to randomly generate 18 | /// Returns "count" random bytes 19 | Array^ Sodium::Core::GetRandomBytes(int count) 20 | { 21 | if (count <= 0) { 22 | throw ref new Platform::InvalidArgumentException("count must be greater than 0"); 23 | } 24 | 25 | Array^ nonce = ref new Array(count); 26 | randombytes_buf(nonce->Data, nonce->Length); 27 | return nonce; 28 | } 29 | 30 | /// The upper bound of the random number to generate 31 | /// Returns a random numbet between 0 and upper_count 32 | int Sodium::Core::GetRandomNumber(int upper_count) 33 | { 34 | return randombytes_uniform(upper_count); 35 | } -------------------------------------------------------------------------------- /libsodium-uwp/SodiumCore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class Core sealed 13 | { 14 | public: 15 | static String^ SodiumVersionString(); 16 | static Array^ GetRandomBytes(int count); 17 | static int GetRandomNumber(int upper_count); 18 | }; 19 | } -------------------------------------------------------------------------------- /libsodium-uwp/StreamEncryption.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class StreamEncryption sealed 13 | { 14 | private: 15 | static Array^ ProcessInternal(const Array^ data, const Array^ nonce, const Array^ key, int method); 16 | public: 17 | static Array^ GenerateKey(); 18 | 19 | static Array^ GenerateNonce(); 20 | 21 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 22 | static Array^ Encrypt(const Array^ message, const Array^ nonce, const Array^ key); 23 | static Array^ Encrypt(String^ message, const Array^ nonce, const Array^ key); 24 | 25 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 26 | static Array^ Decrypt(const Array^ cipherText, const Array^ nonce, const Array^ key); 27 | static Array^ Decrypt(String^ cipherText, const Array^ nonce, const Array^ key); 28 | 29 | static Array^ GenerateNonceXSalsa20(); 30 | 31 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 32 | static Array^ EncryptXSalsa20(const Array^ message, const Array^ nonce, const Array^ key); 33 | static Array^ EncryptXSalsa20(String^ message, const Array^ nonce, const Array^ key); 34 | 35 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 36 | static Array^ DecryptXSalsa20(const Array^ cipherText, const Array^ nonce, const Array^ key); 37 | static Array^ DecryptXSalsa20(String^ cipherText, const Array^ nonce, const Array^ key); 38 | 39 | static Array^ GenerateNonceChaCha20(); 40 | 41 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 42 | static Array^ EncryptChaCha20(const Array^ message, const Array^ nonce, const Array^ key); 43 | static Array^ EncryptChaCha20(String^ message, const Array^ nonce, const Array^ key); 44 | 45 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 46 | static Array^ DecryptChaCha20(const Array^ cipherText, const Array^ nonce, const Array^ key); 47 | static Array^ DecryptChaCha20(String^ cipherText, const Array^ nonce, const Array^ key); 48 | 49 | static Array^ GenerateNonceSalsa20(); 50 | 51 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 52 | static Array^ EncryptSalsa20(const Array^ message, const Array^ nonce, const Array^ key); 53 | static Array^ EncryptSalsa20(String^ message, const Array^ nonce, const Array^ key); 54 | 55 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 56 | static Array^ DecryptSalsa20(const Array^ cipherText, const Array^ nonce, const Array^ key); 57 | static Array^ DecryptSalsa20(String^ cipherText, const Array^ nonce, const Array^ key); 58 | }; 59 | } -------------------------------------------------------------------------------- /libsodium-uwp/Utilities.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SodiumCore.h" 3 | #include "internal.h" 4 | #include "Utilities.h" 5 | 6 | using namespace Sodium; 7 | using namespace Platform; 8 | using namespace Platform::Collections; 9 | using namespace Windows::Security::Cryptography; 10 | using namespace Windows::Security::Cryptography::Core; 11 | using namespace Windows::Storage::Streams; 12 | 13 | /// Incriments a byte array (typically a nonce) 14 | /// The byte array to incriment 15 | /// Incrimented byte array 16 | Array^ Sodium::Utilities::Increment(const Array^ value) 17 | { 18 | Array^ buffer = ref new Array(value->Length); 19 | memcpy(buffer->Data, value->Data, value->Length); 20 | sodium_increment(buffer->Data, buffer->Length); 21 | 22 | return buffer; 23 | } 24 | 25 | /// Constant time string comparison of two byte arrays 26 | /// Boolean if two byte strings are equal 27 | bool Sodium::Utilities::Compare(const Array^ a, const Array^ b) 28 | { 29 | int result = sodium_compare(a->Data, b->Data, a->Length); 30 | return result == 0; 31 | } 32 | 33 | /// Constant time string comparison of string 34 | /// Boolean if two byte strings are equal 35 | bool Sodium::Utilities::Compare(String ^ a, String ^ b) 36 | { 37 | return Sodium::Utilities::Compare( 38 | Sodium::internal::StringToUnsignedCharArray(a), 39 | Sodium::internal::StringToUnsignedCharArray(b) 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /libsodium-uwp/Utilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | public ref class Utilities sealed 13 | { 14 | public: 15 | static Array^ Increment(const Array^ value); 16 | 17 | [Windows::Foundation::Metadata::DefaultOverloadAttribute] 18 | static bool Compare(const Array^ a, const Array^ b); 19 | static bool Compare(String^ a, String^ b); 20 | }; 21 | } -------------------------------------------------------------------------------- /libsodium-uwp/include/randombytes_default.h: -------------------------------------------------------------------------------- 1 | #ifndef randombytes_uwp_H 2 | #define randombytes_uwp_H 3 | 4 | #include "export.h" 5 | #include "randombytes.h" 6 | 7 | #define RANDOMBYTES_DEFAULT_IMPLEMENTATION &randombytes_uwp_implementation; 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | SODIUM_EXPORT 14 | extern struct randombytes_implementation randombytes_uwp_implementation; 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif -------------------------------------------------------------------------------- /libsodium-uwp/internal.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "internal.h" 3 | 4 | using namespace Sodium; 5 | using namespace Platform; 6 | using namespace Platform::Collections; 7 | using namespace Windows::Security::Cryptography; 8 | using namespace Windows::Security::Cryptography::Core; 9 | using namespace Windows::Storage::Streams; 10 | 11 | /// Internal helper method to convert a string to a byte array 12 | /// The string to convert to a byte array 13 | /// Byte array 14 | Array^ Sodium::internal::StringToUnsignedCharArray(String^ str) 15 | { 16 | BinaryStringEncoding encoding = BinaryStringEncoding::Utf8; 17 | IBuffer^ buffer = CryptographicBuffer::ConvertStringToBinary(str, encoding); 18 | Array^ msg = ref new Array(buffer->Length); 19 | CryptographicBuffer::CopyToByteArray(buffer, &msg); 20 | 21 | return msg; 22 | } -------------------------------------------------------------------------------- /libsodium-uwp/internal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace Platform; 4 | using namespace Platform::Collections; 5 | using namespace Windows::Security::Cryptography; 6 | using namespace Windows::Security::Cryptography::Core; 7 | using namespace Windows::Storage::Streams; 8 | using namespace Windows::Foundation::Collections; 9 | 10 | namespace Sodium 11 | { 12 | private ref class internal sealed 13 | { 14 | public: 15 | static Array^ StringToUnsignedCharArray(String^ str); 16 | }; 17 | } -------------------------------------------------------------------------------- /libsodium-uwp/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" -------------------------------------------------------------------------------- /libsodium-uwp/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include -------------------------------------------------------------------------------- /libsodium-uwp/randombytes_default.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifndef _WIN32 4 | # include 5 | # include 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #ifndef _WIN32 15 | # include 16 | #endif 17 | 18 | #include "randombytes.h" 19 | #include "randombytes_default.h" 20 | #include "utils.h" 21 | 22 | #ifndef SSIZE_MAX 23 | # define SSIZE_MAX (SIZE_MAX / 2 - 1) 24 | #endif 25 | 26 | typedef struct uwp_ { 27 | int random_data_source_fd; 28 | int initialized; 29 | int getrandom_available; 30 | } uwp; 31 | 32 | static uwp stream = { 33 | SODIUM_C99(.random_data_source_fd =) -1, 34 | SODIUM_C99(.initialized =) 0, 35 | SODIUM_C99(.getrandom_available =) 0 36 | }; 37 | 38 | static void 39 | randombytes_uwp_init(void) 40 | { 41 | } 42 | 43 | static void 44 | randombytes_uwp_stir(void) 45 | { 46 | if (stream.initialized == 0) { 47 | randombytes_uwp_init(); 48 | stream.initialized = 1; 49 | } 50 | } 51 | 52 | static void 53 | randombytes_uwp_stir_if_needed(void) 54 | { 55 | if (stream.initialized == 0) { 56 | randombytes_uwp_stir(); 57 | } 58 | } 59 | 60 | static int 61 | randombytes_uwp_close(void) 62 | { 63 | int ret = -1; 64 | 65 | if (stream.initialized != 0) { 66 | stream.initialized = 0; 67 | ret = 0; 68 | } 69 | 70 | return ret; 71 | } 72 | 73 | static void 74 | randombytes_uwp_buf(void * const buf, const size_t size) 75 | { 76 | randombytes_uwp_stir_if_needed(); 77 | if (size > (size_t) 0xffffffff) { 78 | abort(); /* LCOV_EXCL_LINE */ 79 | } 80 | if (!GenerateRandomBytes((unsigned char*)buf, (unsigned int)size)) { 81 | abort(); /* LCOV_EXCL_LINE */ 82 | } 83 | } 84 | 85 | static uint32_t 86 | randombytes_uwp(void) 87 | { 88 | uint32_t r; 89 | 90 | randombytes_uwp_buf(&r, sizeof r); 91 | 92 | return r; 93 | } 94 | 95 | static const char * 96 | randombytes_uwp_implementation_name(void) 97 | { 98 | return "uwp"; 99 | } 100 | 101 | struct randombytes_implementation randombytes_uwp_implementation = { 102 | SODIUM_C99(.implementation_name =) randombytes_uwp_implementation_name, 103 | SODIUM_C99(.random =) randombytes_uwp, 104 | SODIUM_C99(.stir =) randombytes_uwp_stir, 105 | SODIUM_C99(.uniform =) NULL, 106 | SODIUM_C99(.buf =) randombytes_uwp_buf, 107 | SODIUM_C99(.close =) randombytes_uwp_close 108 | }; --------------------------------------------------------------------------------