├── Hydrogen.cs ├── LICENSE └── README.md /Hydrogen.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Managed C# wrapper for Hydrogen cryptographic library by Frank Denis 3 | * Copyright (c) 2018 Stanislav Denisov 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | using System; 25 | using System.Runtime.CompilerServices; 26 | using System.Runtime.InteropServices; 27 | using System.Security; 28 | 29 | namespace Hydrogen { 30 | [StructLayout(LayoutKind.Sequential)] 31 | public struct KeyPair { 32 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] 33 | public byte[] publicKey; 34 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] 35 | public byte[] secretKey; 36 | } 37 | 38 | [StructLayout(LayoutKind.Sequential)] 39 | public struct SessionKeyPair { 40 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] 41 | public byte[] receiveKey; 42 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] 43 | public byte[] sendKey; 44 | } 45 | 46 | [StructLayout(LayoutKind.Sequential)] 47 | public struct HashState { 48 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] 49 | private uint[] state; 50 | private byte offset; 51 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] 52 | private byte[] align; 53 | } 54 | 55 | [StructLayout(LayoutKind.Sequential)] 56 | public struct KeyState { 57 | private KeyPair ephemeralKeyPair; 58 | private HashState hashState; 59 | } 60 | 61 | [StructLayout(LayoutKind.Sequential)] 62 | public struct SignKeyPair { 63 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] 64 | public byte[] publicKey; 65 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] 66 | public byte[] secretKey; 67 | } 68 | 69 | [StructLayout(LayoutKind.Sequential)] 70 | public struct SignState { 71 | private HashState hashState; 72 | } 73 | 74 | public static class Library { 75 | public const int hashKeyBytes = 32; 76 | public const int hashBytesMin = 16; 77 | public const int hashBytesMax = 65535; 78 | public const int masterKeyBytes = 32; 79 | public const int storedBytes = 128; 80 | public const int headerBytes = 20 + 16; 81 | public const int secretKeyBytes = 32; 82 | public const int probeBytes = 16; 83 | public const int packetBytes = 32 + 16; 84 | public const int signPublicKeyBytes = 32; 85 | public const int signSecretKeyBytes = 64; 86 | public const int signBytes = 64; 87 | 88 | public static bool Initialize() { 89 | return Native.hydro_init() == 0; 90 | } 91 | 92 | [MethodImpl(256)] 93 | public static uint Random() { 94 | return Random(0); 95 | } 96 | 97 | [MethodImpl(256)] 98 | public static uint Random(uint upperBound) { 99 | if (upperBound > 0) 100 | return Native.hydro_random_uniform(upperBound); 101 | 102 | return Native.hydro_random_u32(); 103 | } 104 | 105 | [MethodImpl(256)] 106 | public static void HashKeygen(byte[] key) { 107 | if (key.Length != Library.hashKeyBytes) 108 | throw new ArgumentOutOfRangeException(); 109 | 110 | Native.hydro_hash_keygen(key); 111 | } 112 | 113 | [MethodImpl(256)] 114 | public static bool Hash(byte[] hash, int hashLength, byte[] message, int messageLength, string context) { 115 | if (hashLength < 0 || messageLength < 0 || hashLength < Library.hashBytesMin || hashLength > Library.hashBytesMax) 116 | throw new ArgumentOutOfRangeException(); 117 | 118 | return Native.hydro_hash_hash(hash, (IntPtr)hashLength, message, (IntPtr)messageLength, context, IntPtr.Zero) == 0; 119 | } 120 | 121 | [MethodImpl(256)] 122 | public static bool Hash(byte[] hash, int hashLength, byte[] message, int messageLength, string context, byte[] key) { 123 | if (hashLength < 0 || messageLength < 0 || hashLength < Library.hashBytesMin || hashLength > Library.hashBytesMax) 124 | throw new ArgumentOutOfRangeException(); 125 | 126 | return Native.hydro_hash_hash(hash, (IntPtr)hashLength, message, (IntPtr)messageLength, context, key) == 0; 127 | } 128 | 129 | [MethodImpl(256)] 130 | public static void MasterKeygen(byte[] key) { 131 | if (key.Length != Library.masterKeyBytes) 132 | throw new ArgumentOutOfRangeException(); 133 | 134 | Native.hydro_pwhash_keygen(key); 135 | } 136 | 137 | [MethodImpl(256)] 138 | public static bool DeterministicKey(byte[] key, int keyLength, string password, int passwordLength, string context, byte[] masterKey, ulong iterationsLimit, int memoryLimit, byte threads) { 139 | if (keyLength < 0 || passwordLength < 0 || memoryLimit < 0) 140 | throw new ArgumentOutOfRangeException(); 141 | 142 | return Native.hydro_pwhash_deterministic(key, (IntPtr)keyLength, password, (IntPtr)passwordLength, context, masterKey, iterationsLimit, (IntPtr)memoryLimit, threads) == 0; 143 | } 144 | 145 | [MethodImpl(256)] 146 | public static bool StorageKey(byte[] key, string password, int passwordLength, byte[] masterKey, ulong iterationsLimit, int memoryLimit, byte threads) { 147 | if (passwordLength < 0 || memoryLimit < 0 || key.Length != Library.storedBytes) 148 | throw new ArgumentOutOfRangeException(); 149 | 150 | return Native.hydro_pwhash_create(key, password, (IntPtr)passwordLength, masterKey, iterationsLimit, (IntPtr)memoryLimit, threads) == 0; 151 | } 152 | 153 | [MethodImpl(256)] 154 | public static bool VerifyKey(byte[] key, string password, int passwordLength, byte[] masterKey, ulong iterationsLimit, int memoryLimit, byte threads) { 155 | if (passwordLength < 0 || memoryLimit < 0) 156 | throw new ArgumentOutOfRangeException(); 157 | 158 | return Native.hydro_pwhash_verify(key, password, (IntPtr)passwordLength, masterKey, iterationsLimit, (IntPtr)memoryLimit, threads) == 0; 159 | } 160 | 161 | [MethodImpl(256)] 162 | public static bool ReencryptKey(byte[] key, byte[] masterKey, byte[] newMasterKey) { 163 | return Native.hydro_pwhash_reencrypt(key, masterKey, newMasterKey) == 0; 164 | } 165 | 166 | [MethodImpl(256)] 167 | public static bool UpgradeKey(byte[] key, byte[] masterKey, ulong iterationsLimit, int memoryLimit, byte threads) { 168 | if (memoryLimit < 0) 169 | throw new ArgumentOutOfRangeException(); 170 | 171 | return Native.hydro_pwhash_upgrade(key, masterKey, iterationsLimit, (IntPtr)memoryLimit, threads) == 0; 172 | } 173 | 174 | [MethodImpl(256)] 175 | public static void ExchangeKeygen(out KeyPair keyPair) { 176 | Native.hydro_kx_keygen(out keyPair); 177 | } 178 | 179 | [MethodImpl(256)] 180 | public static bool N1(out SessionKeyPair sessionKeyPair, byte[] packet, byte[] publicKey) { 181 | return Native.hydro_kx_n_1(out sessionKeyPair, packet, IntPtr.Zero, publicKey) == 0; 182 | } 183 | 184 | [MethodImpl(256)] 185 | public static bool N2(out SessionKeyPair sessionKeyPair, byte[] packet, ref KeyPair keyPair) { 186 | return Native.hydro_kx_n_2(out sessionKeyPair, packet, IntPtr.Zero, ref keyPair) == 0; 187 | } 188 | 189 | [MethodImpl(256)] 190 | public static bool KK1(out KeyState keyState, byte[] packet, byte[] publicKey, ref KeyPair keyPair) { 191 | return Native.hydro_kx_kk_1(out keyState, packet, publicKey, ref keyPair) == 0; 192 | } 193 | 194 | [MethodImpl(256)] 195 | public static bool KK2(out SessionKeyPair sessionKeyPair, byte[] packet, byte[] initialPacket, byte[] publicKey, ref KeyPair keyPair) { 196 | return Native.hydro_kx_kk_2(out sessionKeyPair, packet, initialPacket, publicKey, ref keyPair) == 0; 197 | } 198 | 199 | [MethodImpl(256)] 200 | public static bool KK3(ref KeyState keyState, out SessionKeyPair sessionKeyPair, byte[] packet, ref KeyPair keyPair) { 201 | return Native.hydro_kx_kk_3(ref keyState, out sessionKeyPair, packet, ref keyPair) == 0; 202 | } 203 | 204 | [MethodImpl(256)] 205 | public static void SecretKeygen(byte[] key) { 206 | if (key.Length != Library.secretKeyBytes) 207 | throw new ArgumentOutOfRangeException(); 208 | 209 | Native.hydro_secretbox_keygen(key); 210 | } 211 | 212 | [MethodImpl(256)] 213 | public static bool Encrypt(IntPtr packet, byte[] message, int messageLength, string context, byte[] key) { 214 | if (messageLength < 0) 215 | throw new ArgumentOutOfRangeException(); 216 | 217 | return Native.hydro_secretbox_encrypt(packet, message, messageLength, 0, context, key) == 0; 218 | } 219 | 220 | [MethodImpl(256)] 221 | public static bool Encrypt(byte[] packet, byte[] message, int messageLength, string context, byte[] key) { 222 | if (messageLength < 0) 223 | throw new ArgumentOutOfRangeException(); 224 | 225 | return Native.hydro_secretbox_encrypt(packet, message, messageLength, 0, context, key) == 0; 226 | } 227 | 228 | [MethodImpl(256)] 229 | public static bool Decrypt(byte[] message, IntPtr packet, int packetLength, string context, byte[] key) { 230 | if (packetLength < 0) 231 | throw new ArgumentOutOfRangeException(); 232 | 233 | return Native.hydro_secretbox_decrypt(message, packet, packetLength, 0, context, key) == 0; 234 | } 235 | 236 | [MethodImpl(256)] 237 | public static bool Decrypt(byte[] message, byte[] packet, int packetLength, string context, byte[] key) { 238 | if (packetLength < 0) 239 | throw new ArgumentOutOfRangeException(); 240 | 241 | return Native.hydro_secretbox_decrypt(message, packet, packetLength, 0, context, key) == 0; 242 | } 243 | 244 | [MethodImpl(256)] 245 | public static bool CreateProbe(byte[] probe, byte[] cipher, int cipherLength, string context, byte[] key) { 246 | if (probe.Length != Library.probeBytes || cipherLength < 0) 247 | throw new ArgumentOutOfRangeException(); 248 | 249 | return Native.hydro_secretbox_probe_create(probe, cipher, (IntPtr)cipherLength, context, key) == 0; 250 | } 251 | 252 | [MethodImpl(256)] 253 | public static bool VerifyProbe(byte[] probe, byte[] cipher, int cipherLength, string context, byte[] key) { 254 | if (probe.Length != Library.probeBytes || cipherLength < 0) 255 | throw new ArgumentOutOfRangeException(); 256 | 257 | return Native.hydro_secretbox_probe_verify(probe, cipher, (IntPtr)cipherLength, context, key) == 0; 258 | } 259 | 260 | [MethodImpl(256)] 261 | public static void SignKeygen(out SignKeyPair keyPair) { 262 | Native.hydro_sign_keygen(out keyPair); 263 | } 264 | 265 | [MethodImpl(256)] 266 | public static bool SignInit(out SignState signState, string context) { 267 | return Native.hydro_sign_init(out signState, context) == 0; 268 | } 269 | 270 | [MethodImpl(256)] 271 | public static bool SignCreate(byte[] sig, byte[] message, int messageLength, string context, byte[] key) { 272 | return Native.hydro_sign_create(sig, message, messageLength, context, key) == 0; 273 | } 274 | 275 | [MethodImpl(256)] 276 | public static bool SignVerify(byte[] sig, byte[] message, int messageLength, string context, byte[] key) { 277 | return Native.hydro_sign_verify(sig, message, messageLength, context, key) == 0; 278 | } 279 | } 280 | 281 | [SuppressUnmanagedCodeSecurity] 282 | internal static class Native { 283 | #if __IOS__ || UNITY_IOS && !UNITY_EDITOR 284 | private const string nativeLibrary = "__Internal"; 285 | #else 286 | private const string nativeLibrary = "hydrogen"; 287 | #endif 288 | 289 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 290 | internal static extern int hydro_init(); 291 | 292 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 293 | internal static extern uint hydro_random_u32(); 294 | 295 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 296 | internal static extern uint hydro_random_uniform(uint upperBound); 297 | 298 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 299 | internal static extern void hydro_hash_keygen(byte[] key); 300 | 301 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 302 | internal static extern int hydro_hash_hash(byte[] hash, IntPtr hashLength, byte[] message, IntPtr messageLength, string context, IntPtr key); 303 | 304 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 305 | internal static extern int hydro_hash_hash(byte[] hash, IntPtr hashLength, byte[] message, IntPtr messageLength, string context, byte[] key); 306 | 307 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 308 | internal static extern void hydro_pwhash_keygen(byte[] key); 309 | 310 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 311 | internal static extern int hydro_pwhash_deterministic(byte[] key, IntPtr keyLength, string password, IntPtr passwordLength, string context, byte[] masterKey, ulong iterationsLimit, IntPtr memoryLimit, byte threads); 312 | 313 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 314 | internal static extern int hydro_pwhash_create(byte[] key, string password, IntPtr passwordLength, byte[] masterKey, ulong iterationsLimit, IntPtr memoryLimit, byte threads); 315 | 316 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 317 | internal static extern int hydro_pwhash_verify(byte[] key, string password, IntPtr passwordLength, byte[] masterKey, ulong iterationsLimit, IntPtr memoryLimit, byte threads); 318 | 319 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 320 | internal static extern int hydro_pwhash_reencrypt(byte[] key, byte[] masterKey, byte[] newMasterKey); 321 | 322 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 323 | internal static extern int hydro_pwhash_upgrade(byte[] key, byte[] masterKey, ulong iterationsLimit, IntPtr memoryLimit, byte threads); 324 | 325 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 326 | internal static extern void hydro_kx_keygen(out KeyPair keyPair); 327 | 328 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 329 | internal static extern int hydro_kx_n_1(out SessionKeyPair sessionKeyPair, byte[] packet, IntPtr secretKey, byte[] publicKey); 330 | 331 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 332 | internal static extern int hydro_kx_n_2(out SessionKeyPair sessionKeyPair, byte[] packet, IntPtr secretKey, ref KeyPair keyPair); 333 | 334 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 335 | internal static extern int hydro_kx_kk_1(out KeyState keyState, byte[] packet, byte[] publicKey, ref KeyPair keyPair); 336 | 337 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 338 | internal static extern int hydro_kx_kk_2(out SessionKeyPair sessionKeyPair, byte[] packet, byte[] initialPacket, byte[] publicKey, ref KeyPair keyPair); 339 | 340 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 341 | internal static extern int hydro_kx_kk_3(ref KeyState keyState, out SessionKeyPair sessionKeyPair, byte[] packet, ref KeyPair keyPair); 342 | 343 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 344 | internal static extern void hydro_secretbox_keygen(byte[] key); 345 | 346 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 347 | internal static extern int hydro_secretbox_encrypt(IntPtr packet, byte[] message, int messageLength, ulong messageID, string context, byte[] key); 348 | 349 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 350 | internal static extern int hydro_secretbox_encrypt(byte[] packet, byte[] message, int messageLength, ulong messageID, string context, byte[] key); 351 | 352 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 353 | internal static extern int hydro_secretbox_decrypt(byte[] message, IntPtr packet, int packetLength, ulong messageID, string context, byte[] key); 354 | 355 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 356 | internal static extern int hydro_secretbox_decrypt(byte[] message, byte[] packet, int packetLength, ulong messageID, string context, byte[] key); 357 | 358 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 359 | internal static extern int hydro_secretbox_probe_create(byte[] probe, byte[] cipher, IntPtr cipherLength, string context, byte[] key); 360 | 361 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 362 | internal static extern int hydro_secretbox_probe_verify(byte[] probe, byte[] cipher, IntPtr cipherLength, string context, byte[] key); 363 | 364 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 365 | internal static extern void hydro_sign_keygen(out SignKeyPair keyPair); 366 | 367 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 368 | internal static extern int hydro_sign_init(out SignState signState, string context); 369 | 370 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 371 | internal static extern int hydro_sign_create(byte[] csig, byte[] message, int messageLength, string context, byte[] key); 372 | 373 | [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] 374 | internal static extern int hydro_sign_verify(byte[] csig, byte[] message, int messageLength, string context, byte[] key); 375 | } 376 | } 377 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Stanislav Denisov (nxrighthere@gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | alt logo 3 |

4 | 5 | This repository provides a managed C# wrapper for [Hydrogen](https://github.com/jedisct1/libhydrogen) cryptographic library which is created and maintained by [Frank Denis](https://github.com/jedisct1). You will need to [build](https://github.com/jedisct1/libhydrogen/wiki/Installation#downloading-the-source-code) the native library before you get started. 6 | 7 | Building 8 | -------- 9 | A managed assembly can be built using any available compiling platform that supports C# 3.0 or higher. 10 | 11 | Usage 12 | -------- 13 | Before starting to work, the library should be initialized using `Hydrogen.Library.Initialize();` function. 14 | 15 | ##### Generate random data 16 | ```c# 17 | // Unbounded 18 | uint data = Hydrogen.Library.Random(); 19 | 20 | // Bounded 21 | uint upperBound = 1000000; 22 | uint data = Hydrogen.Library.Random(upperBound); 23 | ``` 24 | 25 | ##### Declare a new context 26 | ```c# 27 | // Only the first 8 characters will be used 28 | string context = "hydrocontext"; 29 | ``` 30 | 31 | ##### Generic hashing 32 | ```c# 33 | string message = "Arbitrary data to hash"; 34 | byte[] data = Encoding.ASCII.GetBytes(message); 35 | int hashLength = 16; 36 | byte[] hash = new byte[hashLength]; // Storage for hash 37 | 38 | // Without a key 39 | if (Hydrogen.Library.Hash(hash, hashLength, data, data.Length, context)) 40 | Console.WriteLine("Hash successfully generated!"); 41 | 42 | // With a key 43 | byte[] hashKey = new byte[Hydrogen.Library.hashKeyBytes]; 44 | 45 | Hydrogen.Library.HashKeygen(hashKey); 46 | 47 | if (Hydrogen.Library.Hash(hash, hashLength, data, data.Length, context, hashKey)) 48 | Console.WriteLine("Hash successfully generated using key!"); 49 | ``` 50 | 51 | ##### Password hashing 52 | ```c# 53 | string password = "feelsgoodman"; 54 | byte[] masterKey = new byte[Hydrogen.Library.masterKeyBytes]; 55 | int keyLength = 32; 56 | byte[] key = new byte[keyLength]; // Storage for high-entropy key 57 | 58 | // Generate master key 59 | Hydrogen.Library.MasterKeygen(masterKey); 60 | 61 | // Generate high-entropy key from a password using master key 62 | if (Hydrogen.Library.DeterministicKey(key, keyLength, password, password.Length, context, masterKey, 1000, 1024, 1)) 63 | Console.WriteLine("High-entropy key successfully generated!"); 64 | 65 | // Generate authenticated representative of the password to store in the database 66 | byte[] storedKey = new byte[Hydrogen.Library.storedBytes]; 67 | 68 | if (Hydrogen.Library.StorageKey(storedKey, password, password.Length, masterKey, 1000, 1024, 1)) 69 | Console.WriteLine("Authenticated representative successfully generated!"); 70 | 71 | // Verify stored key 72 | if (Hydrogen.Library.VerifyKey(storedKey, password, password.Length, masterKey, 1000, 1024, 1)) 73 | Console.WriteLine("Stored key successfully verified!"); 74 | 75 | // Reencrypt stored key 76 | byte[] newMasterKey = new byte[Hydrogen.Library.masterKeyBytes]; 77 | 78 | Hydrogen.Library.MasterKeygen(newMasterKey); 79 | 80 | if (Hydrogen.Library.ReencryptKey(storedKey, masterKey, newMasterKey)) 81 | Console.WriteLine("Stored key successfully reencrypted!"); 82 | 83 | // Upgrade stored key 84 | if (Hydrogen.Library.UpgradeKey(storedKey, newMasterKey, 2000, 1024, 2)) 85 | Console.WriteLine("Stored key successfully upgraded!"); 86 | ``` 87 | 88 | ##### Secret key encryption 89 | ```c# 90 | byte[] key = new byte[Hydrogen.Library.secretKeyBytes]; // Storage for secret key 91 | 92 | // Generate secret key 93 | Hydrogen.Library.SecretKeygen(key); 94 | 95 | // Secret data 96 | string message = "Secret message for future generations"; 97 | byte[] data = Encoding.ASCII.GetBytes(message); 98 | 99 | // Encrypt data 100 | byte[] cipher = new byte[data.Length + Hydrogen.Library.headerBytes]; 101 | 102 | if (Hydrogen.Library.Encrypt(cipher, data, data.Length, context, key)) 103 | Console.WriteLine("Data successfully encrypted!"); 104 | 105 | // Create probe for cipher 106 | byte[] probe = new byte[Hydrogen.Library.probeBytes]; 107 | 108 | if (Hydrogen.Library.CreateProbe(probe, cipher, cipher.Length, context, key)) 109 | Console.WriteLine("Probe successfully created!"); 110 | 111 | // Verify probe 112 | if (Hydrogen.Library.VerifyProbe(probe, cipher, cipher.Length, context, key)) 113 | Console.WriteLine("Probe successfully verified!"); 114 | 115 | // Decrypt data 116 | byte[] data = new byte[cipher.Length - Hydrogen.Library.headerBytes]; 117 | 118 | if (Hydrogen.Library.Decrypt(data, cipher, cipher.Length, context, key)) 119 | Console.WriteLine("Data successfully decrypted!"); 120 | ``` 121 | 122 | ##### Secure network communication based on the Noise protocol (N variant) 123 | ```c# 124 | // Server 125 | KeyPair serverKeyPair = default(KeyPair); 126 | 127 | // Generate long-term key pair 128 | Hydrogen.Library.ExchangeKeygen(out serverKeyPair); 129 | 130 | /* Send `serverKeyPair.publicKey` to the client */ 131 | 132 | // Client 133 | SessionKeyPair clientSessionKeyPair = default(SessionKeyPair); 134 | byte[] packet = new byte[Hydrogen.Library.packetBytes]; 135 | 136 | // Generate session keys and a packet with an ephemeral public key 137 | if (Hydrogen.Library.N1(out clientSessionKeyPair, packet, serverKeyPair.publicKey)) 138 | Console.WriteLine("Session key pair successfully generated!"); 139 | 140 | /* Send `packet` to the server */ 141 | 142 | // Server 143 | SessionKeyPair serverSessionKeyPair = default(SessionKeyPair); 144 | 145 | // Process the initial request from the client and generate session keys 146 | if (Hydrogen.Library.N2(out serverSessionKeyPair, packet, ref serverKeyPair)) 147 | Console.WriteLine("Session key pair successfully generated!"); 148 | 149 | /* Send a signal to the client that secure communication is established */ 150 | 151 | // Client 152 | string message = "Do you want to take a look at my high-poly things tonight?"; 153 | byte[] data = Encoding.ASCII.GetBytes(message); 154 | byte[] packet = new byte[data.Length + Hydrogen.Library.headerBytes]; 155 | 156 | // Encrypt data 157 | if (Hydrogen.Library.Encrypt(packet, data, data.Length, context, clientSessionKeyPair.sendKey)) 158 | Console.WriteLine("Data successfully encrypted!"); 159 | 160 | /* Send `packet` to the server */ 161 | 162 | // Server 163 | byte[] data = new byte[packet.Length - Hydrogen.Library.headerBytes]; 164 | 165 | // Decrypt data 166 | if (Hydrogen.Library.Decrypt(data, packet, packet.Length, context, serverSessionKeyPair.receiveKey)) 167 | Console.WriteLine("Data successfully decrypted!"); 168 | 169 | Console.WriteLine("Received message: " + Encoding.ASCII.GetString(data)); 170 | ``` 171 | 172 | ##### Secure network communication based on the Noise protocol (KK variant) 173 | ```c# 174 | // Client 175 | KeyPair clientKeyPair = default(KeyPair); 176 | 177 | // Generate long-term key pair 178 | Hydrogen.Library.ExchangeKeygen(out clientKeyPair); 179 | 180 | // Server 181 | KeyPair serverKeyPair = default(KeyPair); 182 | 183 | // Generate long-term key pair 184 | Hydrogen.Library.ExchangeKeygen(out serverKeyPair); 185 | 186 | /* Send `serverKeyPair.publicKey` to the client */ 187 | 188 | // Client 189 | KeyState clientState = default(KeyState); 190 | byte[] initialPacket = new byte[Hydrogen.Library.packetBytes]; 191 | 192 | // Initiate a key exchange 193 | if (Hydrogen.Library.KK1(out clientState, initialPacket, serverKeyPair.publicKey, ref clientKeyPair)) 194 | Console.WriteLine("Initial packet successfully generated!"); 195 | 196 | /* Send `initialPacket` to the server */ 197 | 198 | // Server 199 | SessionKeyPair serverSessionKeyPair = default(SessionKeyPair); 200 | byte[] packet = new byte[Hydrogen.Library.packetBytes]; 201 | 202 | // Process the initial request from the client, and generate session keys 203 | if (Hydrogen.Library.KK2(out serverSessionKeyPair, packet, initialPacket, clientKeyPair.publicKey, ref serverKeyPair)) 204 | Console.WriteLine("Session key pair successfully generated!"); 205 | 206 | /* Send `packet` to the client */ 207 | 208 | // Client 209 | SessionKeyPair clientSessionKeyPair = default(SessionKeyPair); 210 | 211 | // Process the server packet and generate session keys 212 | if (Hydrogen.Library.KK3(ref clientState, out clientSessionKeyPair, packet, ref clientKeyPair)) 213 | Console.WriteLine("Session key pair successfully generated!"); 214 | 215 | /* Send a signal to the server that secure communication is established */ 216 | 217 | // Client 218 | string message = "Hold my beer"; 219 | byte[] data = Encoding.ASCII.GetBytes(message); 220 | byte[] packet = new byte[data.Length + Hydrogen.Library.headerBytes]; 221 | 222 | // Encrypt data 223 | if (Hydrogen.Library.Encrypt(packet, data, data.Length, context, clientSessionKeyPair.sendKey)) 224 | Console.WriteLine("Data successfully encrypted!"); 225 | 226 | /* Send `packet` to the server */ 227 | 228 | // Server 229 | byte[] data = new byte[packet.Length - Hydrogen.Library.headerBytes]; 230 | 231 | // Decrypt data 232 | if (Hydrogen.Library.Decrypt(data, packet, packet.Length, context, serverSessionKeyPair.receiveKey)) 233 | Console.WriteLine("Data successfully decrypted!"); 234 | 235 | Console.WriteLine("Received message: " + Encoding.ASCII.GetString(data)); 236 | ``` 237 | 238 | ##### Public/Private key signatures 239 | ```c# 240 | SignKeyPair keyPair = default(SignKeyPair); 241 | 242 | // Generate key pair 243 | Hydrogen.Library.SignKeygen(out keyPair); 244 | 245 | byte[] signature = new byte[signBytes]; 246 | 247 | string message = "'You can't give her that!' she screamed. 'It's not safe!' IT'S A SWORD, said the Hogfather. THEY'RE NOT MEANT TO BE SAFE."; 248 | byte[] data = Encoding.ASCII.GetBytes(message); 249 | 250 | // Sign the message 251 | if(Hydrogen.Library.SignCreate(signature, data, data.Length, context, keyPair.secretKey)) 252 | Console.WriteLine("Message successfully signed!"); 253 | 254 | // Verify the signature 255 | if(Hydrogen.Library.SignVerify(signature, data, data.Length, context, keyPair.publicKey)) 256 | Console.WriteLine("Message signature successfully verified!"); 257 | ``` 258 | --------------------------------------------------------------------------------