├── .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 | [](https://ci.appveyor.com/project/charlesportwoodii/libsodium-uwp)
4 | [](https://github.com/charlesportwoodii/libsodium-uwp/blob/master/LICENSE.md)
5 | [](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