Пример #1
0
 /// <summary>
 /// Creates a new instance of <see cref="BlockDigestAlgorithm"/> which wraps this <see cref="BlockDigestAlgorithm"/>, and adds HMAC support.
 /// </summary>
 /// <param name="algorithm">This <see cref="BlockDigestAlgorithm"/>.</param>
 /// <param name="key">The key to use in HMAC.</param>
 /// <param name="skipDisposeAlgorithm">Whether to skip disposing this <see cref="BlockDigestAlgorithm"/> when returned HMAC <see cref="BlockDigestAlgorithm"/> is disposed.</param>
 /// <param name="skipZeroingOutKey">Whether to skip zeroing out the key array when the returned HMAC <see cref="BlockDigestAlgorithm"/> is disposed.</param>
 /// <returns>A new instance of <see cref="BlockDigestAlgorithm"/> with HMAC support.</returns>
 /// <exception cref="NullReferenceException">If this <see cref="BlockDigestAlgorithm"/> is <c>null</c>.</exception>
 /// <exception cref="ArgumentNullException">If <paramref name="key"/> is <c>null</c>.</exception>
 /// <remarks>
 /// The returned <see cref="BlockDigestAlgorithm"/> will assume the given <paramref name="key"/> as its own, and will write to it. If that is undesirable, please pass a copy of an array as <paramref name="key"/>.
 /// </remarks>
 public static BlockDigestAlgorithm CreateHMAC(
     this BlockDigestAlgorithm algorithm,
     Byte[] key,
     Boolean skipDisposeAlgorithm = false,
     Boolean skipZeroingOutKey    = false
     )
 => algorithm.CreateHMAC(key, 0, key?.Length ?? 0, skipDisposeAlgorithm: skipDisposeAlgorithm, skipZeroingOutKey: skipZeroingOutKey);
Пример #2
0
 /// <summary>
 /// Creates a new instance of <see cref="SASLMechanism"/> that implements server-side SCRAM mechanism with this <see cref="BlockDigestAlgorithm"/>.
 /// </summary>
 /// <param name="algorithm">This <see cref="BlockDigestAlgorithm"/>, that will be used by SCRAM mechanism as its digest provider.</param>
 /// <param name="getCredentials">The callback to get <see cref="SASLCredentialsSCRAMForServer"/> for given username.</param>
 /// <param name="nonceGenerator">The optional custom callback to provide nonce. Please read remarks if supplying value.</param>
 /// <returns>A new <see cref="SASLMechanism"/> which will behave as server-side when authenticating with SCRAM.</returns>
 /// <remarks>
 /// <para>
 /// The returned <see cref="SASLMechanism"/> will expect the <see cref="SASLChallengeArguments.Credentials"/> field to always be non-null and of type <see cref="SASLCredentialsHolder"/>.
 /// </para>
 /// <para>
 /// The <paramref name="nonceGenerator"/>, if supplied, *must* return valid nonce (e.g. not containing any commas, printable ASCII characters, etc).
 /// The returned nonce will be directly written to the message - it is not base64-encoded!
 /// </para>
 /// </remarks>
 /// <exception cref="NullReferenceException">If this <see cref="BlockDigestAlgorithm"/> is <c>null</c>.</exception>
 /// <exception cref="ArgumentNullException">If <paramref name="getCredentials"/> is <c>null</c>.</exception>
 /// <seealso cref="SASLCredentialsSCRAMForClient"/>
 /// <seealso cref="SCRAMCommon"/>
 public static SASLMechanism CreateSASLServerSCRAM(
     this BlockDigestAlgorithm algorithm,
     Func <String, ValueTask <SASLCredentialsSCRAMForServer> > getCredentials,
     Func <Byte[]> nonceGenerator = null
     )
 {
     return(new SASLMechanismSCRAMForServer(ArgumentValidator.ValidateNotNullReference(algorithm), getCredentials, nonceGenerator));
 }
Пример #3
0
        internal static Byte[] UseNonceGenerator(BlockDigestAlgorithm algorithm, Func <Byte[]> nonceGenerator)
        {
            var retVal = nonceGenerator?.Invoke();

            return(retVal.IsNullOrEmpty() ?
                   GenerateNonce(algorithm, 24, 32) :
                   retVal); // Let's not check it after all - but document that nonce returned by factory is not checked!
        }
Пример #4
0
        private readonly ResizableArray <Byte> _clientMessage; // Temporary storage for data to be preserved between Challenge invocations

        public SASLMechanismSCRAMForClient(
            BlockDigestAlgorithm algorithm,
            Func <Byte[]> clientNonceGenerator
            )
        {
            this._algorithm      = ArgumentValidator.ValidateNotNull(nameof(algorithm), algorithm);
            this._nonceGenerator = clientNonceGenerator;
            this._clientMessage  = new ResizableArray <Byte>(exponentialResize: false);
        }
Пример #5
0
        public HMACBlockDigestAlgorithm(
            BlockDigestAlgorithm actual,
            Byte[] key,
            Int32 keyOffset,
            Int32 keyLength,
            Boolean skipDisposeAlgorithm,
            Boolean skipZeroingKeyOnDispose
            )
        {
            this._actual = ArgumentValidator.ValidateNotNull(nameof(actual), actual);
            ArgumentValidator.ValidateNotNull(nameof(key), key);

            // Check if the key is too long
            var blockSize = actual.BlockSize;

            this._skipDisposeAlgorithm    = skipDisposeAlgorithm;
            this._skipZeroingKeyOnDispose = skipZeroingKeyOnDispose;
            if (keyLength > blockSize)
            {
                // Compute hash of the key
                actual.ProcessBlock(key);
                actual.WriteDigest(key, keyOffset);
                // Explicitly set trailing zeroes
                key.Clear(keyOffset + actual.DigestByteCount, keyLength - actual.DigestByteCount);
            }
            else if (keyLength < blockSize)
            {
                if (key.Length < keyOffset + blockSize)
                {
                    var newKey = new Byte[blockSize];
                    key.CopyTo(newKey);
                    keyOffset = 0;
                    key       = newKey;                    // There will be trailing zeroes, as a new array was allocated
                    this._skipZeroingKeyOnDispose = false; // Always zero out, since we created the array here.
                }
                else
                {
                    // Explicitly set trailing zeroes
                    key.Clear(keyOffset + keyLength, blockSize - keyLength);
                }
            }

            this._key       = key;
            this._keyOffset = keyOffset;
        }
Пример #6
0
        /// <summary>
        /// This is convenience method to create new <see cref="DigestBasedRandomGenerator"/> and seed it with default, secure logic.
        /// </summary>
        /// <param name="algorithm">The algorithm that returned <see cref="DigestBasedRandomGenerator"/> should use.</param>
        /// <param name="seedCycleCount">How often to re-seed the state of returned <see cref="DigestBasedRandomGenerator"/>.</param>
        /// <param name="skipDisposeAlgorithm">Optional parameter controlling whether the <see cref="DigestBasedRandomGenerator"/> will, when disposed, dispose also the given <paramref name="algorithm"/>.</param>
        /// <returns>A new instance of <see cref="DigestBasedRandomGenerator"/> with given parameters.</returns>
        /// <exception cref="ArgumentNullException">If <paramref name="algorithm"/> is <c>null</c>.</exception>
        public static DigestBasedRandomGenerator CreateAndSeedWithDefaultLogic(
            BlockDigestAlgorithm algorithm,
            Int32 seedCycleCount         = DEFAULT_SEED_CYCLE_COUNT,
            Boolean skipDisposeAlgorithm = false
            )
        {
            var retVal = new DigestBasedRandomGenerator(algorithm, seedCycleCount, skipDisposeAlgorithm);

            // Use Guid as random source (should be version 4)
            retVal.AddSeedMaterial(Guid.NewGuid().ToByteArray());

            // Use current ticks
            retVal.AddSeedMaterial(DateTime.Now.Ticks);

            // Use Guid again
            retVal.AddSeedMaterial(Guid.NewGuid().ToByteArray());
            return(retVal);
        }
Пример #7
0
 /// <summary>
 /// Creates a new instance of <see cref="BlockDigestAlgorithm"/> which wraps this <see cref="BlockDigestAlgorithm"/>, and adds HMAC support.
 /// </summary>
 /// <param name="algorithm">This <see cref="BlockDigestAlgorithm"/>.</param>
 /// <param name="key">The key to use in HMAC.</param>
 /// <param name="offset">The offset in <paramref name="key"/> array where the key content starts.</param>
 /// <param name="count">The amount of bytes in <paramref name="key"/> which are key bytes.</param>
 /// <param name="skipDisposeAlgorithm">Whether to skip disposing this <see cref="BlockDigestAlgorithm"/> when returned HMAC <see cref="BlockDigestAlgorithm"/> is disposed.</param>
 /// <param name="skipZeroingOutKey">Whether to skip zeroing out the key array when the returned HMAC <see cref="BlockDigestAlgorithm"/> is disposed.</param>
 /// <returns>A new instance of <see cref="BlockDigestAlgorithm"/> with HMAC support.</returns>
 /// <exception cref="NullReferenceException">If this <see cref="BlockDigestAlgorithm"/> is <c>null</c>.</exception>
 /// <exception cref="ArgumentNullException">If <paramref name="key"/> is <c>null</c>.</exception>
 /// <remarks>
 /// The returned <see cref="BlockDigestAlgorithm"/> will assume the given <paramref name="key"/> as its own, and will write to it. If that is undesirable, please pass a copy of an array as <paramref name="key"/>.
 /// </remarks>
 public static BlockDigestAlgorithm CreateHMAC(
     this BlockDigestAlgorithm algorithm,
     Byte[] key,
     Int32 offset,
     Int32 count,
     Boolean skipDisposeAlgorithm = false,
     Boolean skipZeroingOutKey    = false
     )
 {
     return(new HMACBlockDigestAlgorithm(
                ArgumentValidator.ValidateNotNullReference(algorithm),
                key,
                offset,
                count,
                skipDisposeAlgorithm,
                skipZeroingOutKey
                ));
 }
Пример #8
0
        //private static void CheckCustomNonce( BlockDigestAlgorithm algorithm, Byte[] nonce )
        //{
        //   using ( var randomLazy = new LazyDisposable<SecureRandom>( () => new SecureRandom( DigestBasedRandomGenerator.CreateAndSeedWithDefaultLogic( algorithm, skipDisposeAlgorithm: true ) ) ) )
        //   {
        //      for ( var i = 0; i < nonce.Length; ++i )
        //      {
        //         var b = nonce[i];
        //         if (b < )
        //      }
        //   }

        //}

        internal static Byte[] GenerateNonce(BlockDigestAlgorithm algorithm, Int32 minSize, Int32 maxValue)
        {
            using (var random = new SecureRandom(DigestBasedRandomGenerator.CreateAndSeedWithDefaultLogic(algorithm, skipDisposeAlgorithm: true)))
            {
                var retVal = new Byte[random.Next(minSize, maxValue)];
                // Actual legal values are 0x21-0x7E
                for (var i = 0; i < retVal.Length; ++i)
                {
                    Byte nextVal;
                    do
                    {
                        nextVal   = (Byte)random.Next(0x21, 0x7F);
                        retVal[i] = nextVal;
                    } while (nextVal == COMMA); // ... except commas not allowed
                }
                return(retVal);
            }
        }