예제 #1
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>
        /// <param name="bytes">The size (in bytes) of the desired result.</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,
                                              int bytes = OUT_BYTES)
        {
            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));
            }

            //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];

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

            return(buffer);
        }