//
            //   - "hashAlgId" must be a name recognized by BCryptOpenAlgorithmProvider(). Examples: MD5, SHA1, SHA256.
            //
            //   - "key" activates MAC hashing if present. If null, this HashProvider performs a regular old hash.
            //
            public HashProviderCng(String hashAlgId, byte[] key)
            {
                Cng.OpenAlgorithmProviderFlags dwFlags = Cng.OpenAlgorithmProviderFlags.NONE;
                if (key != null)
                {
                    _key     = key.CloneByteArray();
                    dwFlags |= Cng.OpenAlgorithmProviderFlags.BCRYPT_ALG_HANDLE_HMAC_FLAG;
                }
                _hAlgorithm = Cng.BCryptOpenAlgorithmProvider(hashAlgId, null, dwFlags);

                _hHash = _hAlgorithm.BCryptTryCreateReusableHash(_key);
                if (_hHash == null)
                {
                    // If we got here, we're running on a downlevel OS that doesn't support reusable CNG hash objects. Fall back to creating a
                    // new HASH object each time.
                    ResetHashObject();
                }
                else
                {
                    _reusable = true;
                }

                _hashSize = _hHash.GetHashSizeInBytes();
                return;
            }
        private static Lazy <SafeAlgorithmHandle> Open3DesAlgorithm(string cipherMode, int feedback = 0)
        {
            return(new Lazy <SafeAlgorithmHandle>(() =>
            {
                SafeAlgorithmHandle hAlg = Cng.BCryptOpenAlgorithmProvider(Cng.BCRYPT_3DES_ALGORITHM, null,
                                                                           Cng.OpenAlgorithmProviderFlags.NONE);
                hAlg.SetCipherMode(cipherMode);

                // The default feedback size is 1 (CFB8) on Windows. Do not set the CNG property
                // if we would be setting it to the default. Windows 7 only supports CFB8 and
                // does not permit setting the feedback size, so we don't call the property
                // setter at all in that case.
                if (feedback > 0 && feedback != 1)
                {
                    try
                    {
                        hAlg.SetFeedbackSize(feedback);
                    }
                    catch (CryptographicException ex)
                    {
                        throw new CryptographicException(SR.Cryptography_FeedbackSizeNotSupported, ex);
                    }
                }

                return hAlg;
            }));
        }
예제 #3
0
        private static SafeAlgorithmHandle GetCachedAlgorithmHandle(ref SafeAlgorithmHandle?handle, string algId, string?chainingMode = null)
        {
            // Do we already have a handle to this algorithm?
            SafeAlgorithmHandle?existingHandle = Volatile.Read(ref handle);

            if (existingHandle != null)
            {
                return(existingHandle);
            }

            // No cached handle exists; create a new handle. It's ok if multiple threads call
            // this concurrently. Only one handle will "win" and the rest will be destroyed.
            SafeAlgorithmHandle newHandle = Cng.BCryptOpenAlgorithmProvider(algId, null, Cng.OpenAlgorithmProviderFlags.NONE);

            if (chainingMode != null)
            {
                newHandle.SetCipherMode(chainingMode);
            }

            existingHandle = Interlocked.CompareExchange(ref handle, newHandle, null);
            if (existingHandle != null)
            {
                newHandle.Dispose();
                return(existingHandle);
            }
            else
            {
                return(newHandle);
            }
        }
예제 #4
0
        private static SafeAlgorithmHandle Open3DesAlgorithm(string cipherMode)
        {
            SafeAlgorithmHandle hAlg = Cng.BCryptOpenAlgorithmProvider(Cng.BCRYPT_3DES_ALGORITHM, null, Cng.OpenAlgorithmProviderFlags.NONE);

            hAlg.SetCipherMode(cipherMode);

            return(hAlg);
        }
예제 #5
0
        protected override string FormatNative(Oid oid, byte[] rawData, bool multiLine)
        {
            // If OID is not present, then we can force CryptFormatObject
            // to use hex formatting by providing an empty OID string.
            string oidValue = string.Empty;

            if (oid != null && oid.Value != null)
            {
                oidValue = oid.Value;
            }

            return(Cng.CryptFormatObject(oidValue, rawData, multiLine));
        }
예제 #6
0
        private static Lazy <SafeAlgorithmHandle> OpenDesAlgorithm(string cipherMode)
        {
            return(new Lazy <SafeAlgorithmHandle>(() =>
            {
                SafeAlgorithmHandle hAlg = Cng.BCryptOpenAlgorithmProvider(
                    Cng.BCRYPT_DES_ALGORITHM,
                    null,
                    Cng.OpenAlgorithmProviderFlags.NONE);
                hAlg.SetCipherMode(cipherMode);

                return hAlg;
            }));
        }
예제 #7
0
        private static SafeAlgorithmHandle OpenRC2Algorithm(string cipherMode, int effectiveKeyLength)
        {
            SafeAlgorithmHandle hAlg = Cng.BCryptOpenAlgorithmProvider(Cng.BCRYPT_RC2_ALGORITHM, null, Cng.OpenAlgorithmProviderFlags.NONE);

            hAlg.SetCipherMode(cipherMode);

            if (effectiveKeyLength != 0)
            {
                Cng.SetEffectiveKeyLength(hAlg, effectiveKeyLength);
            }

            return(hAlg);
        }
예제 #8
0
        private static Lazy <SafeAlgorithmHandle> Open3DesAlgorithm(string cipherMode, int feedback = 0)
        {
            return(new Lazy <SafeAlgorithmHandle>(() =>
            {
                SafeAlgorithmHandle hAlg = Cng.BCryptOpenAlgorithmProvider(Cng.BCRYPT_3DES_ALGORITHM, null,
                                                                           Cng.OpenAlgorithmProviderFlags.NONE);
                hAlg.SetCipherMode(cipherMode);

                if (feedback > 0)
                {
                    // feedback is in bytes!
                    hAlg.SetFeedbackSize(feedback);
                }

                return hAlg;
            }));
        }
        private byte[] _currentIv;  // CNG mutates this with the updated IV for the next stage on each Encrypt/Decrypt call.
                                    // The base IV holds a copy of the original IV for Reset(), until it is cleared by Dispose().

        public BasicSymmetricCipherBCrypt(SafeAlgorithmHandle algorithm, CipherMode cipherMode, int blockSizeInBytes, byte[] key, int effectiveKeyLength, byte[] iv, bool encrypting)
            : base(cipherMode.GetCipherIv(iv), blockSizeInBytes)
        {
            Debug.Assert(algorithm != null);

            _encrypting = encrypting;

            if (IV != null)
            {
                _currentIv = new byte[IV.Length];
            }

            _hKey = algorithm.BCryptImportKey(key);

            if (effectiveKeyLength != 0)
            {
                Cng.SetEffectiveKeyLength(_hKey, effectiveKeyLength);
            }

            Reset();
        }
예제 #10
0
        private static int DecryptInPlace(SafeKeyHandle hKey, byte[] currentIv, byte[] inOutBuffer, int offset, int count)
        {
            int numBytesWritten = Cng.BCryptDecrypt(hKey, inOutBuffer, offset, count, currentIv, inOutBuffer, offset, inOutBuffer.Length - offset);

            return(numBytesWritten);
        }