コード例 #1
0
ファイル: KeyPair.cs プロジェクト: Siiver/libsodium-net
 private void _UnprotectKey()
 {
     if (!SodiumCore.IsRunningOnMono())
     {
         ProtectedMemory.Unprotect(_privateKey, MemoryProtectionScope.SameProcess);
     }
 }
コード例 #2
0
        /// <summary>Converts a hex-encoded string to a byte array.</summary>
        /// <param name="hex">Hex-encoded data.</param>
        /// <returns>A byte array of the decoded string.</returns>
        /// <exception cref="Exception"></exception>
        public static byte[] HexToBinary(string hex)
        {
            const string IGNORED_CHARS = ":- ";

            var arr = new byte[hex.Length >> 1];
            var bin = Marshal.AllocHGlobal(arr.Length);
            int binLength;

            //we call sodium_hex2bin with some chars to be ignored
            var h   = DynamicInvoke.GetDynamicInvoke <_Hex2Bin>("sodium_hex2bin", SodiumCore.LibraryName());
            var ret = h(bin, arr.Length, hex, hex.Length, IGNORED_CHARS, out binLength, null);

            Marshal.Copy(bin, arr, 0, binLength);
            Marshal.FreeHGlobal(bin);

            if (ret != 0)
            {
                throw new Exception("Internal error, decoding failed.");
            }

            //remove the trailing nulls from the array, if there were some format characters in the hex string before
            if (arr.Length != binLength)
            {
                var tmp = new byte[binLength];
                Array.Copy(arr, 0, tmp, 0, binLength);
                return(tmp);
            }

            return(arr);
        }
コード例 #3
0
        /// <summary>Returns the hash in a string format, which includes the generated salt.</summary>
        /// <param name="password">The password.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <returns>Returns an zero-terminated ASCII encoded string of the computed password and hash.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static string ScryptHashString(string password, long opsLimit, int memLimit)
        {
            if (password == null)
            {
                throw new ArgumentNullException("password", "Password cannot be null");
            }

            if (opsLimit <= 0)
            {
                throw new ArgumentOutOfRangeException("opsLimit", "opsLimit cannot be zero or negative");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException("memLimit", "memLimit cannot be zero or negative");
            }

            var buffer = new byte[SCRYPT_SALSA208_SHA256_STRBYTES];
            var pass   = Encoding.UTF8.GetBytes(password);

            SodiumCore.Init();
            var ret = SodiumLibrary.crypto_pwhash_scryptsalsa208sha256_str(buffer, pass, pass.Length, opsLimit, memLimit);

            if (ret != 0)
            {
                throw new OutOfMemoryException("Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(Encoding.UTF8.GetString(buffer));
        }
コード例 #4
0
ファイル: PublicKeyBox.cs プロジェクト: Siiver/libsodium-net
        /// <summary>Creates a Box</summary>
        /// <param name="message">The message.</param>
        /// <param name="nonce">The 24 byte nonce.</param>
        /// <param name="secretKey">The secret key to sign message with.</param>
        /// <param name="publicKey">The recipient's public key.</param>
        /// <returns>The encrypted message.</returns>
        /// <exception cref="KeyOutOfRangeException"></exception>
        /// <exception cref="NonceOutOfRangeException"></exception>
        /// <exception cref="CryptographicException"></exception>
        public static byte[] Create(byte[] message, byte[] nonce, byte[] secretKey, byte[] publicKey)
        {
            //validate the length of the secret key
            if (secretKey == null || secretKey.Length != SecretKeyBytes)
            {
                throw new KeyOutOfRangeException("secretKey", (secretKey == null) ? 0 : secretKey.Length,
                                                 string.Format("key must be {0} bytes in length.", SecretKeyBytes));
            }

            //validate the length of the public key
            if (publicKey == null || publicKey.Length != PublicKeyBytes)
            {
                throw new KeyOutOfRangeException("publicKey", (publicKey == null) ? 0 : secretKey.Length,
                                                 string.Format("key must be {0} bytes in length.", PublicKeyBytes));
            }

            //validate the length of the nonce
            if (nonce == null || nonce.Length != NONCE_BYTES)
            {
                throw new NonceOutOfRangeException("nonce", (nonce == null) ? 0 : nonce.Length,
                                                   string.Format("nonce must be {0} bytes in length.", NONCE_BYTES));
            }

            var buffer = new byte[message.Length + MAC_BYTES];
            var create = DynamicInvoke.GetDynamicInvoke <_Create>("crypto_box_easy", SodiumCore.LibraryName());
            var ret    = create(buffer, message, message.Length, nonce, publicKey, secretKey);

            if (ret != 0)
            {
                throw new CryptographicException("Failed to create SecretBox");
            }

            return(buffer);
        }
コード例 #5
0
        /// <summary>Returns the hash in a string format, which includes the generated salt.</summary>
        /// <param name="password">The password.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <returns>Returns an zero-terminated ASCII encoded string of the computed password and hash.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static string ArgonHashString(string password, long opsLimit, int memLimit)
        {
            if (password == null)
            {
                throw new ArgumentNullException("password", "Password cannot be null");
            }

            if (opsLimit < 3)
            {
                throw new ArgumentOutOfRangeException("opsLimit",
                                                      "opsLimit the number of passes, has to be at least 3");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException("memLimit", "memLimit cannot be zero or negative");
            }

            byte[] buffer = new byte[ARGON_STRBYTES];
            byte[] pass   = Encoding.UTF8.GetBytes(password);

            SodiumCore.Init();
            int ret = SodiumLibrary.crypto_pwhash_str(buffer, pass, pass.GetLongLength(0), opsLimit, memLimit);

            if (ret != 0)
            {
                throw new OutOfMemoryException(
                          "Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(Encoding.UTF8.GetString(buffer));
        }
コード例 #6
0
ファイル: SecretAead.cs プロジェクト: Siiver/libsodium-net
        /// <summary>
        /// Encrypts a message with an authentication tag and additional data.
        /// </summary>
        /// <param name="message">The message to be encrypted.</param>
        /// <param name="nonce">The 8 byte nonce.</param>
        /// <param name="key">The 32 byte key.</param>
        /// <param name="additionalData">The additional data; may be null, otherwise between 0 and 16 bytes.</param>
        /// <returns>The encrypted message with additional data.</returns>
        /// <remarks>The nonce should never ever be reused with the same key.</remarks>
        /// <remarks>The recommended way to generate it is to use GenerateNonce() for the first message, and increment it for each subsequent message using the same key.</remarks>
        /// <exception cref="KeyOutOfRangeException"></exception>
        /// <exception cref="NonceOutOfRangeException"></exception>
        /// <exception cref="AdditionalDataOutOfRangeException"></exception>
        /// <exception cref="CryptographicException"></exception>
        public static byte[] Encrypt(byte[] message, byte[] nonce, byte[] key, byte[] additionalData = null)
        {
            //additionalData can be null
            if (additionalData == null)
            {
                additionalData = new byte[0x00];
            }

            //validate the length of the key
            if (key == null || key.Length != KEYBYTES)
            {
                throw new KeyOutOfRangeException("key", (key == null) ? 0 : key.Length,
                                                 string.Format("key must be {0} bytes in length.", KEYBYTES));
            }

            //validate the length of the nonce
            if (nonce == null || nonce.Length != NPUBBYTES)
            {
                throw new NonceOutOfRangeException("nonce", (nonce == null) ? 0 : nonce.Length,
                                                   string.Format("nonce must be {0} bytes in length.", NPUBBYTES));
            }

            //validate the length of the additionalData
            if (additionalData.Length > ABYTES || additionalData.Length < 0)
            {
                throw new AdditionalDataOutOfRangeException(
                          string.Format("additionalData must be between {0} and {1} bytes in length.", 0, ABYTES));
            }

            var  cipher = new byte[message.Length + ABYTES];
            var  bin    = Marshal.AllocHGlobal(cipher.Length);
            long cipherLength;

            var encrypt = DynamicInvoke.GetDynamicInvoke <_Encrypt>("crypto_aead_chacha20poly1305_encrypt",
                                                                    SodiumCore.LibraryName());
            var ret = encrypt(bin, out cipherLength, message, message.Length, additionalData, additionalData.Length, null,
                              nonce, key);

            Marshal.Copy(bin, cipher, 0, (int)cipherLength);
            Marshal.FreeHGlobal(bin);

            if (ret != 0)
            {
                throw new CryptographicException("Error encrypting message.");
            }

            if (cipher.Length == cipherLength)
            {
                return(cipher);
            }

            //remove the trailing nulls from the array
            var tmp = new byte[cipherLength];

            Array.Copy(cipher, 0, tmp, 0, cipherLength);

            return(tmp);
        }
コード例 #7
0
        /// <summary>Hashes a byte array using the default algorithm (This is what you want to use)</summary>
        /// <param name="message">The message.</param>
        /// <returns></returns>
        public static byte[] Hash(byte[] message)
        {
            var buffer = new byte[SHA512_BYTES];

            var hash = DynamicInvoke.GetDynamicInvoke <_CryptoHash>("crypto_hash", SodiumCore.LibraryName());

            hash(buffer, message, message.Length);

            return(buffer);
        }
コード例 #8
0
        /// <summary>Takes a byte array and returns a hex-encoded string.</summary>
        /// <param name="data">Data to be encoded.</param>
        /// <returns>Hex-encoded string, lodercase.</returns>
        /// <exception cref="OverflowException"></exception>
        public static string BinaryToHex(byte[] data)
        {
            var hex = new byte[data.Length * 2 + 1];
            var b   = DynamicInvoke.GetDynamicInvoke <_Bin2Hex>("sodium_bin2hex", SodiumCore.LibraryName());
            var ret = b(hex, hex.Length, data, data.Length);

            if (ret == IntPtr.Zero)
            {
                throw new OverflowException("Internal error, encoding failed.");
            }

            return(Marshal.PtrToStringAnsi(ret));
        }
コード例 #9
0
        public static byte[] ScryptHashLowLevel(byte[] password, byte[] salt, long N, int R, int P, uint bufferLength = SCRYPT_SALSA208_SHA256_STRBYTES)
        {
            var buffer = new byte[bufferLength];

            SodiumCore.Init();
            var ret = SodiumLibrary.crypto_pwhash_scryptsalsa208sha256_ll(password, password.Length, salt, salt.Length, N, R, P, buffer, buffer.Length);

            if (ret != 0)
            {
                throw new OutOfMemoryException("Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(buffer);
        }
コード例 #10
0
        /// <summary>
        ///     Derives a secret key of any size from a password and a salt.
        /// </summary>
        /// <param name="password">The password.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <param name="outputLength">The length of the computed output array.</param>
        /// <returns>Returns a byte array of the given size.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="SaltOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static byte[] ArgonHashBinary(byte[] password, byte[] salt, long opsLimit, int memLimit,
                                             long outputLength = ARGON_SALTBYTES)
        {
            if (password == null)
            {
                throw new ArgumentNullException("password", "Password cannot be null");
            }

            if (salt == null)
            {
                throw new ArgumentNullException("salt", "Salt cannot be null");
            }

            if (salt.Length != ARGON_SALTBYTES)
            {
                throw new SaltOutOfRangeException(string.Format("Salt must be {0} bytes in length.", ARGON_SALTBYTES));
            }

            if (opsLimit < 2)
            {
                throw new ArgumentOutOfRangeException("opsLimit",
                                                      "opsLimit the number of passes, has to be at least 3");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException("memLimit", "memLimit cannot be zero or negative");
            }

            if (outputLength <= 0)
            {
                throw new ArgumentOutOfRangeException("outputLength", "OutputLength cannot be zero or negative");
            }

            byte[] buffer = new byte[outputLength];

            SodiumCore.Init();

            int ret = SodiumLibrary.crypto_pwhash(buffer, buffer.Length, password, password.GetLongLength(0), salt,
                                                  opsLimit, memLimit, ARGON_ALGORITHM_DEFAULT);

            if (ret != 0)
            {
                throw new OutOfMemoryException(
                          "Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(buffer);
        }
コード例 #11
0
ファイル: SecretKeyAuth.cs プロジェクト: Siiver/libsodium-net
        /// <summary>Signs a message with HMAC-SHA512-256.</summary>
        /// <param name="message">The message.</param>
        /// <param name="key">The 32 byte key.</param>
        /// <returns>32 byte authentication code.</returns>
        /// <exception cref="KeyOutOfRangeException"></exception>
        public static byte[] Sign(byte[] message, byte[] key)
        {
            //validate the length of the key
            if (key == null || key.Length != KEY_BYTES)
            {
                throw new KeyOutOfRangeException("key", (key == null) ? 0 : key.Length,
                                                 string.Format("key must be {0} bytes in length.", KEY_BYTES));
            }

            var buffer = new byte[BYTES];
            var sign   = DynamicInvoke.GetDynamicInvoke <_Sign>("crypto_auth", SodiumCore.LibraryName());

            sign(buffer, message, message.Length, key);

            return(buffer);
        }
コード例 #12
0
        /// <summary>Verifies that a hash generated with ScryptHashString matches the supplied password.</summary>
        /// <param name="hash">The hash.</param>
        /// <param name="password">The password.</param>
        /// <returns><c>true</c> on success; otherwise, <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static bool ScryptHashStringVerify(byte[] hash, byte[] password)
        {
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password), "Password cannot be null");
            }
            if (hash == null)
            {
                throw new ArgumentNullException(nameof(hash), "Hash cannot be null");
            }

            SodiumCore.Init();

            var ret = SodiumLibrary.crypto_pwhash_scryptsalsa208sha256_str_verify(hash, password, password.Length);

            return(ret == 0);
        }
コード例 #13
0
        /// <summary>
        /// Derives a secret key of any size from a password and a salt.
        /// </summary>
        /// <param name="password">The password.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <param name="outputLength">The length of the computed output array.</param>
        /// <param name="alg">Argon Algorithm</param>
        /// <returns>Returns a byte array of the given size.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="SaltOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static byte[] ArgonHashBinary(byte[] password, byte[] salt, long opsLimit, int memLimit, long outputLength = ARGON_SALTBYTES,
                                             ArgonAlgorithm alg = ArgonAlgorithm.Argon_2I13)
        {
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password), "Password cannot be null");
            }

            if (salt == null)
            {
                throw new ArgumentNullException(nameof(salt), "Salt cannot be null");
            }

            if (salt.Length != ARGON_SALTBYTES)
            {
                throw new SaltOutOfRangeException($"Salt must be {ARGON_SALTBYTES} bytes in length.");
            }

            if (opsLimit < 3)
            {
                throw new ArgumentOutOfRangeException(nameof(opsLimit), "opsLimit the number of passes, has to be at least 3");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(memLimit), "memLimit cannot be zero or negative");
            }

            if (outputLength <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(outputLength), "OutputLength cannot be zero or negative");
            }

            var buffer = new byte[outputLength];

            SodiumCore.Init();

            var ret = SodiumLibrary.crypto_pwhash(buffer, buffer.Length, password, password.Length, salt, opsLimit, memLimit, (int)alg);

            if (ret != 0)
            {
                throw new OutOfMemoryException("Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(buffer);
        }
コード例 #14
0
        /// <summary>
        /// Derives a secret key of any size from a password and a salt.
        /// </summary>
        /// <param name="password">The password.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <param name="outputLength">The length of the computed output array.</param>
        /// <returns>Returns a byte array of the given size.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="SaltOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static byte[] ScryptHashBinary(byte[] password, byte[] salt, long opsLimit, int memLimit, long outputLength = SCRYPT_SALSA208_SHA256_SALTBYTES)
        {
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password), "Password cannot be null");
            }

            if (salt == null)
            {
                throw new ArgumentNullException(nameof(salt), "Salt cannot be null");
            }

            if (salt.Length != SCRYPT_SALSA208_SHA256_SALTBYTES)
            {
                throw new SaltOutOfRangeException($"Salt must be {SCRYPT_SALSA208_SHA256_SALTBYTES} bytes in length.");
            }

            if (opsLimit <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(opsLimit), "opsLimit cannot be zero or negative");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(memLimit), "memLimit cannot be zero or negative");
            }

            if (outputLength < 16)
            {
                throw new ArgumentOutOfRangeException(nameof(outputLength), "OutputLength cannot be less than 16 bytes");
            }

            var buffer = new byte[outputLength];

            SodiumCore.Init();

            var ret = SodiumLibrary.crypto_pwhash_scryptsalsa208sha256(buffer, buffer.Length, password, password.Length, salt, opsLimit, memLimit);

            if (ret != 0)
            {
                throw new OutOfMemoryException("Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(buffer);
        }
コード例 #15
0
        /// <summary>
        /// Checks if the current password hash needs rehashing
        /// </summary>
        /// <param name="password">Password that needs rehashing</param>
        /// <param name="opsLimit"></param>
        /// <param name="memLimit"></param>
        /// <returns></returns>
        public static bool ArgonPasswordNeedsRehash(byte[] password, long opsLimit, int memLimit)
        {
            if (password == null)
            {
                throw new ArgumentNullException("password", "Password cannot be null");
            }

            SodiumCore.Init();

            int status = SodiumLibrary.crypto_pwhash_str_needs_rehash(password, opsLimit, memLimit);

            if (status == -1)
            {
                throw new InvalidArgonPasswordString();
            }

            return(status == 1);
        }
コード例 #16
0
        /// <summary>Signs a message with Ed25519.</summary>
        /// <param name="message">The message.</param>
        /// <param name="key">The 64 byte private key.</param>
        /// <returns>Signed message.</returns>
        /// <exception cref="KeyOutOfRangeException"></exception>
        public static byte[] Sign(byte[] message, byte[] key)
        {
            //validate the length of the key
            if (key == null || key.Length != SECRET_KEY_BYTES)
            {
                throw new KeyOutOfRangeException("key", (key == null) ? 0 : key.Length,
                                                 string.Format("key must be {0} bytes in length.", SECRET_KEY_BYTES));
            }

            var  buffer       = new byte[message.Length + BYTES];
            long bufferLength = 0;

            var mes = DynamicInvoke.GetDynamicInvoke <_Sign>("crypto_sign", SodiumCore.LibraryName());

            mes(buffer, ref bufferLength, message, message.Length, key);

            var final = new byte[bufferLength];

            Array.Copy(buffer, 0, final, 0, bufferLength);

            return(final);
        }
コード例 #17
0
 /// <summary>Generates a random 8 byte nonce.</summary>
 /// <returns>Returns a byte array with 8 random bytes</returns>
 public static byte[] GenerateNonceXChaCha20()
 {
     return(SodiumCore.GetRandomBytes(XCHACHA20_NONCEBYTES));
 }
コード例 #18
0
 /// <summary>Generates a random 24 byte nonce.</summary>
 /// <returns>Returns a byte array with 24 random bytes</returns>
 public static byte[] GenerateNonce()
 {
     return(SodiumCore.GetRandomBytes(XSALSA20_NONCE_BYTES));
 }
コード例 #19
0
        /// <summary>Detect if the current CPU supports the required instructions (SSSE3, aesni, pcmul).</summary>
        /// <returns><c>true</c> if the CPU supports the necessary instructions, otherwise <c>false</c></returns>
        /// <remarks>Use <see cref="SecretAead" /> if portability is required.</remarks>
        public static bool IsAvailable()
        {
            SodiumCore.Init();

            return(SodiumLibrary.crypto_aead_aes256gcm_is_available() != 0);
        }
コード例 #20
0
ファイル: PublicKeyBox.cs プロジェクト: Siiver/libsodium-net
        /// <summary>Opens a detached Box</summary>
        /// <param name="cipherText">The cipherText.</param>
        /// <param name="mac">The 16 byte mac.</param>
        /// <param name="nonce">The 24 byte nonce.</param>
        /// <param name="secretKey">The recipient's secret key.</param>
        /// <param name="publicKey">The sender's public key.</param>
        /// <returns>The decrypted message.</returns>
        /// <exception cref="KeyOutOfRangeException"></exception>
        /// <exception cref="MacOutOfRangeException"></exception>
        /// <exception cref="NonceOutOfRangeException"></exception>
        /// <exception cref="CryptographicException"></exception>
        public static byte[] OpenDetached(byte[] cipherText, byte[] mac, byte[] nonce, byte[] secretKey, byte[] publicKey)
        {
            //validate the length of the secret key
            if (secretKey == null || secretKey.Length != SecretKeyBytes)
            {
                throw new KeyOutOfRangeException("secretKey", (secretKey == null) ? 0 : secretKey.Length,
                                                 string.Format("key must be {0} bytes in length.", SecretKeyBytes));
            }

            //validate the length of the public key
            if (publicKey == null || publicKey.Length != PublicKeyBytes)
            {
                throw new KeyOutOfRangeException("publicKey", (publicKey == null) ? 0 : secretKey.Length,
                                                 string.Format("key must be {0} bytes in length.", PublicKeyBytes));
            }

            //validate the length of the mac
            if (mac == null || mac.Length != MAC_BYTES)
            {
                throw new MacOutOfRangeException("mac", (mac == null) ? 0 : mac.Length,
                                                 string.Format("mac must be {0} bytes in length.", MAC_BYTES));
            }

            //validate the length of the nonce
            if (nonce == null || nonce.Length != NONCE_BYTES)
            {
                throw new NonceOutOfRangeException("nonce", (nonce == null) ? 0 : nonce.Length,
                                                   string.Format("nonce must be {0} bytes in length.", NONCE_BYTES));
            }

            var buffer = new byte[cipherText.Length];
            var open   = DynamicInvoke.GetDynamicInvoke <_OpenDetache>("crypto_box_open_detached", SodiumCore.LibraryName());
            var ret    = open(buffer, cipherText, mac, cipherText.Length, nonce, secretKey, publicKey);

            if (ret != 0)
            {
                throw new CryptographicException("Failed to open detached Box");
            }

            return(buffer);
        }
コード例 #21
0
ファイル: PublicKeyBox.cs プロジェクト: Siiver/libsodium-net
        /// <summary>Opens a Box</summary>
        /// <param name="cipherText"></param>
        /// <param name="nonce">The 24 byte nonce.</param>
        /// <param name="secretKey">The recipient's secret key.</param>
        /// <param name="publicKey">The sender's public key.</param>
        /// <returns>The decrypted message.</returns>
        /// <exception cref="KeyOutOfRangeException"></exception>
        /// <exception cref="NonceOutOfRangeException"></exception>
        /// <exception cref="CryptographicException"></exception>
        public static byte[] Open(byte[] cipherText, byte[] nonce, byte[] secretKey, byte[] publicKey)
        {
            //validate the length of the secret key
            if (secretKey == null || secretKey.Length != SecretKeyBytes)
            {
                throw new KeyOutOfRangeException("secretKey", (secretKey == null) ? 0 : secretKey.Length,
                                                 string.Format("key must be {0} bytes in length.", SecretKeyBytes));
            }

            //validate the length of the public key
            if (publicKey == null || publicKey.Length != PublicKeyBytes)
            {
                throw new KeyOutOfRangeException("publicKey", (publicKey == null) ? 0 : secretKey.Length,
                                                 string.Format("key must be {0} bytes in length.", PublicKeyBytes));
            }

            //validate the length of the nonce
            if (nonce == null || nonce.Length != NONCE_BYTES)
            {
                throw new NonceOutOfRangeException("nonce", (nonce == null) ? 0 : nonce.Length,
                                                   string.Format("nonce must be {0} bytes in length.", NONCE_BYTES));
            }

            //check to see if there are MAC_BYTES of leading nulls, if so, trim.
            //this is required due to an error in older versions.
            if (cipherText[0] == 0)
            {
                //check to see if trim is needed
                var trim = true;
                for (var i = 0; i < MAC_BYTES - 1; i++)
                {
                    if (cipherText[i] != 0)
                    {
                        trim = false;
                        break;
                    }
                }

                //if the leading MAC_BYTES are null, trim it off before going on.
                if (trim)
                {
                    var temp = new byte[cipherText.Length - MAC_BYTES];
                    Array.Copy(cipherText, MAC_BYTES, temp, 0, cipherText.Length - MAC_BYTES);

                    cipherText = temp;
                }
            }

            var buffer = new byte[cipherText.Length - MAC_BYTES];
            var open   = DynamicInvoke.GetDynamicInvoke <_Open>("crypto_box_open_easy", SodiumCore.LibraryName());
            var ret    = open(buffer, cipherText, cipherText.Length, nonce, publicKey, secretKey);

            if (ret != 0)
            {
                throw new CryptographicException("Failed to open SecretBox");
            }

            return(buffer);
        }
コード例 #22
0
        //TODO: we could implement a method which increments the nonce.

        /// <summary>Generates a random 8 byte nonce.</summary>
        /// <returns>Returns a byte array with 8 random bytes.</returns>
        public static byte[] GenerateNonce()
        {
            return(SodiumCore.GetRandomBytes(NPUBBYTES));
        }
コード例 #23
0
 /// <summary>Generates a random 32 byte salt for the Scrypt algorithm.</summary>
 /// <returns>Returns a byte array with 32 random bytes</returns>
 public static byte[] ScryptGenerateSalt()
 {
     return(SodiumCore.GetRandomBytes((int)SCRYPT_SALSA208_SHA256_SALTBYTES));
 }
コード例 #24
0
ファイル: PasswordHash.cs プロジェクト: Siiver/libsodium-net
        /// <summary>Returns the hash in a string format, which includes the generated salt.</summary>
        /// <param name="password">The password.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <returns>Returns an zero-terminated ASCII encoded string of the computed password and hash.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static string ScryptHashString(string password, long opsLimit, int memLimit)
        {
            if (password == null)
            {
                throw new ArgumentNullException("password", "Password cannot be null");
            }

            if (opsLimit <= 0)
            {
                throw new ArgumentOutOfRangeException("opsLimit", "opsLimit cannot be zero or negative");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException("memLimit", "memLimit cannot be zero or negative");
            }

            var buffer = new byte[SCRYPT_SALSA208_SHA256_BYTES];
            var pass   = Encoding.UTF8.GetBytes(password);

            var hash = DynamicInvoke.GetDynamicInvoke <_HashString>("crypto_pwhash_scryptsalsa208sha256_str", SodiumCore.LibraryName());
            var ret  = hash(buffer, pass, pass.LongLength, opsLimit, memLimit);

            if (ret != 0)
            {
                throw new OutOfMemoryException("Internal error, hash failed");
            }

            return(Encoding.UTF8.GetString(buffer));
        }
コード例 #25
0
 /// <summary>Generates a random 16 byte salt for the Argon2i algorithm.</summary>
 /// <returns>Returns a byte array with 16 random bytes</returns>
 public static byte[] ArgonGenerateSalt()
 {
     return(SodiumCore.GetRandomBytes((int)ARGON_SALTBYTES));
 }
コード例 #26
0
        /// <summary>Generates a hash based on a key, salt and personal bytes</summary>
        /// <returns><c>byte</c> hashed message</returns>
        /// <param name="message">Message.</param>
        /// <param name="key">Key.</param>
        /// <param name="salt">Salt.</param>
        /// <param name="personal">Personal string.</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="KeyOutOfRangeException"></exception>
        /// <exception cref="SaltOutOfRangeException"></exception>
        /// <exception cref="PersonalOutOfRangeException"></exception>
        public static byte[] HashSaltPersonal(byte[] message, byte[] key, byte[] salt, byte[] personal)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message", "Message cannot be null");
            }

            if (salt == null)
            {
                throw new ArgumentNullException("salt", "Salt cannot be null");
            }

            if (personal == null)
            {
                throw new ArgumentNullException("personal", "Personal string cannot be null");
            }

            if (key != null && (key.Length > KEY_BYTES_MAX || key.Length < KEY_BYTES_MIN))
            {
                throw new KeyOutOfRangeException(string.Format("key must be between {0} and {1} bytes in length.", KEY_BYTES_MIN, KEY_BYTES_MAX));
            }

            if (key == null)
            {
                key = new byte[0];
            }

            if (salt.Length != SALT_BYTES)
            {
                throw new SaltOutOfRangeException(string.Format("Salt must be {0} bytes in length.", SALT_BYTES));
            }

            if (personal.Length != PERSONAL_BYTES)
            {
                throw new PersonalOutOfRangeException(string.Format("Personal bytes must be {0} bytes in length.", PERSONAL_BYTES));
            }

            var buffer = new byte[OUT_BYTES];

            var hash = DynamicInvoke.GetDynamicInvoke <_GenericHashSaltPersonal>("crypto_generichash_blake2b_salt_personal", SodiumCore.LibraryName());

            hash(buffer, buffer.Length, message, message.LongLength, key, key.Length, salt, personal);

            return(buffer);
        }
コード例 #27
0
        /// <summary>Verifies a message signed with the Sign method.</summary>
        /// <param name="message">The message.</param>
        /// <param name="signature">The 16 byte signature.</param>
        /// <param name="key">The 32 byte key.</param>
        /// <returns>True if verified.</returns>
        /// <exception cref="KeyOutOfRangeException"></exception>
        /// <exception cref="SignatureOutOfRangeException"></exception>
        public static bool Verify(byte[] message, byte[] signature, byte[] key)
        {
            //validate the length of the key
            if (key == null || key.Length != KEY_BYTES)
            {
                throw new KeyOutOfRangeException("key", (key == null) ? 0 : key.Length,
                                                 string.Format("key must be {0} bytes in length.", KEY_BYTES));
            }

            //validate the length of the signature
            if (signature == null || signature.Length != BYTES)
            {
                throw new SignatureOutOfRangeException("signature", (signature == null) ? 0 : signature.Length,
                                                       string.Format("signature must be {0} bytes in length.", BYTES));
            }

            var verify = DynamicInvoke.GetDynamicInvoke <_Verify>("crypto_onetimeauth_verify", SodiumCore.LibraryName());
            var ret    = verify(signature, message, message.Length, key);

            return(ret == 0);
        }
コード例 #28
0
        /// <summary>Hashes a message, with an optional key, using the BLAKE2b primitive.</summary>
        /// <param name="message">The message to be hashed.</param>
        /// <param name="key">The key; may be null, otherwise between 16 and 64 bytes.</param>
        /// <param name="bytes">The size (in bytes) of the desired result.</param>
        /// <returns>Returns a byte array.</returns>
        /// <exception cref="KeyOutOfRangeException"></exception>
        /// <exception cref="BytesOutOfRangeException"></exception>
        public static byte[] Hash(byte[] message, byte[] key, int bytes)
        {
            //validate the length of the key
            int keyLength;

            if (key != null)
            {
                if (key.Length > KEY_BYTES_MAX || key.Length < KEY_BYTES_MIN)
                {
                    throw new KeyOutOfRangeException(string.Format("key must be between {0} and {1} bytes in length.",
                                                                   KEY_BYTES_MIN, KEY_BYTES_MAX));
                }

                keyLength = key.Length;
            }
            else
            {
                key       = new byte[0];
                keyLength = 0;
            }

            //validate output length
            if (bytes > BYTES_MAX || bytes < BYTES_MIN)
            {
                throw new BytesOutOfRangeException("bytes", bytes,
                                                   string.Format("bytes must be between {0} and {1} bytes in length.", BYTES_MIN, BYTES_MAX));
            }

            var buffer = new byte[bytes];
            var hash   = DynamicInvoke.GetDynamicInvoke <_GenericHash>("crypto_generichash", SodiumCore.LibraryName());

            hash(buffer, buffer.Length, message, message.Length, key, keyLength);

            return(buffer);
        }
コード例 #29
0
 /// <summary>Generates a random 32 byte key.</summary>
 /// <returns>Returns a byte array with 32 random bytes</returns>
 public static byte[] GenerateKey()
 {
     return(SodiumCore.GetRandomBytes(KEY_BYTES));
 }
コード例 #30
0
ファイル: PublicKeyBox.cs プロジェクト: Siiver/libsodium-net
        /// <summary>Creates a new key pair based on a random seed.</summary>
        /// <returns>A KeyPair.</returns>
        public static KeyPair GenerateKeyPair()
        {
            var publicKey  = new byte[PublicKeyBytes];
            var privateKey = new byte[SecretKeyBytes];

            var kp = DynamicInvoke.GetDynamicInvoke <_GenerateKeyPair>("crypto_box_keypair", SodiumCore.LibraryName());

            kp(publicKey, privateKey);

            return(new KeyPair(publicKey, privateKey));
        }