/// <summary>Gets random bytes</summary>
        /// <param name="count">The count of bytes to return.</param>
        /// <returns>An array of random bytes.</returns>
        public static byte[] GetRandomBytes(int count)
        {
            byte[] buffer = new byte[count];
            SodiumLibrary.randombytes_buf(buffer, count);

            return(buffer);
        }
Exemple #2
0
        /// <summary>Creates a Secret Box</summary>
        /// <param name="message">The message.</param>
        /// <param name="nonce">The 24 byte nonce.</param>
        /// <param name="key">The 32 byte 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[] 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 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));
            }

            byte[] buffer = new byte[MAC_BYTES + message.Length];

            SodiumCore.Init();
            int ret = SodiumLibrary.crypto_secretbox_easy(buffer, message, message.Length, nonce, key);

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

            return(buffer);
        }
        /// <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(this string hex)
        {
            const string IGNORED_CHARS = ":- ";

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

            //we call sodium_hex2bin with some chars to be ignored
            int ret = SodiumLibrary.sodium_hex2bin(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)
            {
                byte[] tmp = new byte[binLength];
                Array.Copy(arr, 0, tmp, 0, binLength);
                return(tmp);
            }

            return(arr);
        }
 /// <summary>Initialize libsodium.</summary>
 /// <remarks>This only needs to be done once, so this prevents repeated calls.</remarks>
 public static void Init()
 {
     if (!_isInit)
     {
         SodiumLibrary.sodium_init();
         _isInit = true;
     }
 }
Exemple #5
0
        /// <summary>Opens a Secret Box</summary>
        /// <param name="cipherText">The cipherText.</param>
        /// <param name="nonce">The 24 byte nonce.</param>
        /// <param name="key">The 32 byte nonce.</param>
        /// <returns>The decrypted text.</returns>
        /// <exception cref="KeyOutOfRangeException"></exception>
        /// <exception cref="NonceOutOfRangeException"></exception>
        /// <exception cref="CryptographicException"></exception>
        public static byte[] Open(byte[] cipherText, byte[] nonce, 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 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
                bool trim = true;

                for (int 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)
                {
                    byte[] temp = new byte[cipherText.Length - MAC_BYTES];
                    Array.Copy(cipherText, MAC_BYTES, temp, 0, cipherText.Length - MAC_BYTES);

                    cipherText = temp;
                }
            }

            byte[] buffer = new byte[cipherText.Length - MAC_BYTES];
            SodiumCore.Init();
            int ret = SodiumLibrary.crypto_secretbox_open_easy(buffer, cipherText, cipherText.Length, nonce, key);

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

            return(buffer);
        }
        /// <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(this byte[] data)
        {
            byte[] hex = new byte[data.Length * 2 + 1];
            IntPtr ret = SodiumLibrary.sodium_bin2hex(hex, hex.Length, data, data.Length);

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

            return(Marshal.PtrToStringAnsi(ret));
        }
        /// <summary>
        ///     Returns the version of libsodium in use.
        /// </summary>
        /// <returns>
        ///     The sodium version string.
        /// </returns>
        public static string SodiumVersionString()
        {
            IntPtr ptr = SodiumLibrary.sodium_version_string();

            return(Marshal.PtrToStringAnsi(ptr));
        }
        /// <summary>
        ///     Gets a random number.
        /// </summary>
        /// <param name="upperBound">Integer between 0 and 2147483647.</param>
        /// <returns>An unpredictable value between 0 and upperBound (excluded).</returns>
        public static int GetRandomNumber(int upperBound)
        {
            int randomNumber = SodiumLibrary.randombytes_uniform(upperBound);

            return(randomNumber);
        }