/// <summary>
 /// Routes data written to the object into the <see cref="MD4"/> hash algorithm for computing the hash.
 /// </summary>
 /// <param name="array">The array of data bytes.</param>
 /// <param name="ibStart">The offset into the byte array from which to begin using data.</param>
 /// <param name="cbSize">The number of bytes in the array to use as data.</param>
 /// <exception cref="ObjectDisposedException">The MD4CryptoServiceProvider instance has been disposed.</exception>
 /// <exception cref="CryptographicException">The data could not be hashed.</exception>
 protected override void HashCore(byte[] array, int ibStart, int cbSize)
 {
     if (m_Disposed)
     {
         throw new ObjectDisposedException(this.GetType().FullName);
     }
     byte[] copy = new byte[cbSize];
     Array.Copy(array, ibStart, copy, 0, cbSize);
     if (SspiProvider.CryptHashData(m_Hash, copy, copy.Length, 0) == 0)
     {
         throw new CryptographicException("The data could not be hashed.");
     }
 }
        public bool VerifySignature(Certificate cert, byte[] signature, byte[] hash)
        {
            int provider = 0;
            int hashptr  = 0;
            int pubKey   = 0;

            try {
                if (SspiProvider.CryptAcquireContext(ref provider, IntPtr.Zero, null, SecurityConstants.PROV_RSA_FULL, 0) == 0)
                {
                    if (Marshal.GetLastWin32Error() == SecurityConstants.NTE_BAD_KEYSET)
                    {
                        SspiProvider.CryptAcquireContext(ref provider, IntPtr.Zero, null, SecurityConstants.PROV_RSA_FULL, SecurityConstants.CRYPT_NEWKEYSET);
                    }
                }
                if (provider == 0)
                {
                    throw new CryptographicException("Unable to acquire a cryptographic context.");
                }
                if (SspiProvider.CryptCreateHash(provider, SecurityConstants.CALG_SSL3_SHAMD5, 0, 0, out hashptr) == 0)
                {
                    throw new CryptographicException("Unable to create the SHA-MD5 hash.");
                }
                if (SspiProvider.CryptSetHashParam(hashptr, SecurityConstants.HP_HASHVAL, hash, 0) == 0)
                {
                    throw new CryptographicException("Unable to set the value of the SHA-MD5 hash.");
                }
                CertificateInfo      ci  = cert.GetCertificateInfo();
                CERT_PUBLIC_KEY_INFO pki = new CERT_PUBLIC_KEY_INFO(ci);
                if (SspiProvider.CryptImportPublicKeyInfo(provider, SecurityConstants.X509_ASN_ENCODING | SecurityConstants.PKCS_7_ASN_ENCODING, ref pki, out pubKey) == 0)
                {
                    throw new CryptographicException("Unable to get a handle to the public key of the specified certificate.");
                }
                byte[] sign_rev = new byte[signature.Length];
                Array.Copy(signature, 0, sign_rev, 0, signature.Length);
                Array.Reverse(sign_rev);
                return(SspiProvider.CryptVerifySignature(hashptr, sign_rev, sign_rev.Length, pubKey, IntPtr.Zero, 0) != 0);
            } finally {
                if (pubKey != 0)
                {
                    SspiProvider.CryptDestroyKey(pubKey);
                }
                if (hashptr != 0)
                {
                    SspiProvider.CryptDestroyHash(hashptr);
                }
                if (provider != 0)
                {
                    SspiProvider.CryptReleaseContext(provider, 0);
                }
            }
        }
        /// <summary>
        /// Returns the computed <see cref="MD4CryptoServiceProvider"/> hash as an array of bytes after all data has been written to the object.
        /// </summary>
        /// <returns>The computed hash value.</returns>
        /// <exception cref="ObjectDisposedException">The MD4CryptoServiceProvider instance has been disposed.</exception>
        /// <exception cref="CryptographicException">The data could not be hashed.</exception>
        protected override byte[] HashFinal()
        {
            if (m_Disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            byte[] buffer = new byte[16];
            int    length = buffer.Length;

            if (SspiProvider.CryptGetHashParam(m_Hash, SecurityConstants.HP_HASHVAL, buffer, ref length, 0) == 0)
            {
                throw new CryptographicException("The hash value could not be read.");
            }
            return(buffer);
        }
Пример #4
0
 protected override void Dispose(bool disposing)
 {
     if (!m_Disposed)
     {
         if (m_Hash != 0)
         {
             SspiProvider.CryptDestroyHash(m_Hash);
             m_Hash = 0;
         }
         try {
             GC.SuppressFinalize(this);
         } catch {}
         m_Disposed = true;
     }
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="CertificateStoreCollection"/> class.
 /// </summary>
 /// <param name="collection">The CertificateStoreCollection whose elements are copied to the new certificate store collection.</param>
 /// <exception cref="ArgumentNullException"><paramref name="collection"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
 /// <exception cref="CertificateException">An error occurs while adding a certificate to the collection.</exception>
 public CertificateStoreCollection(CertificateStoreCollection collection) : base(SspiProvider.CertOpenStore(new IntPtr(SecurityConstants.CERT_STORE_PROV_COLLECTION), 0, 0, 0, null), false)
 {
     if (collection == null)
     {
         throw new ArgumentNullException();
     }
     m_Stores = new ArrayList(collection.m_Stores);              // used to hold references to the certificate stores so they cannot be finalized
     for (int i = 0; i < m_Stores.Count; i++)
     {
         if (SspiProvider.CertAddStoreToCollection(this.Handle, ((CertificateStore)m_Stores[i]).Handle, 0, 0) == 0)
         {
             throw new CertificateException("Could not add the store to the collection.");
         }
     }
 }
 /// <summary>
 /// Adds a certificate store to the collection.
 /// </summary>
 /// <param name="store">An instance of the <see cref="CertificateStore"/> class.</param>
 /// <exception cref="ArgumentNullException"><paramref name="store"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
 /// <exception cref="ArgumentException">The specified certificate store is a <see cref="CertificateStoreCollection"/> instance. This is not allowed to avoid circular dependencies.</exception>
 /// <exception cref="CertificateException">An error occurs while adding the certificate to the collection.</exception>
 public void AddStore(CertificateStore store)
 {
     if (store == null)
     {
         throw new ArgumentNullException();
     }
     if (store.ToString() == this.ToString())             // avoid circular dependencies
     {
         throw new ArgumentException("A certificate store collection cannot hold other certificate store collections.");
     }
     if (SspiProvider.CertAddStoreToCollection(this.Handle, store.Handle, 0, 0) == 0)
     {
         throw new CertificateException("Could not add the store to the collection.");
     }
     m_Stores.Add(store);
 }
Пример #7
0
        /// <summary>
        /// Releases all unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (m_Handle != 0)
            {
                SspiProvider.CryptDestroyKey(m_Handle);
            }
            if (m_ExponentOfOne != 0)
            {
                SspiProvider.CryptDestroyKey(m_ExponentOfOne);
            }

/*			if (m_OwnsProvider && m_Provider != 0)
 *                              SspiProvider.CryptReleaseContext(m_Provider, 0);*/
            m_Handle = m_ExponentOfOne = m_Provider = 0;
            try {
                GC.SuppressFinalize(this);
            } catch {}
        }
        public byte[] CreateSignature(Certificate cert, byte[] hash)
        {
            int flags = 0, mustFree = 0, provider = 0, keySpec = 0, hashptr = 0, size = 0;

            try {
                if (!Environment.UserInteractive)
                {
                    flags = SecurityConstants.CRYPT_ACQUIRE_SILENT_FLAG;
                }
                if (SspiProvider.CryptAcquireCertificatePrivateKey(cert.Handle, flags, IntPtr.Zero, ref provider, ref keySpec, ref mustFree) == 0)
                {
                    throw new SslException(AlertDescription.InternalError, "Could not acquire private key.");
                }
                if (SspiProvider.CryptCreateHash(provider, SecurityConstants.CALG_SSL3_SHAMD5, 0, 0, out hashptr) == 0)
                {
                    throw new CryptographicException("Unable to create the SHA-MD5 hash.");
                }
                if (SspiProvider.CryptSetHashParam(hashptr, SecurityConstants.HP_HASHVAL, hash, 0) == 0)
                {
                    throw new CryptographicException("Unable to set the value of the SHA-MD5 hash.");
                }
                SspiProvider.CryptSignHash(hashptr, keySpec, IntPtr.Zero, 0, null, ref size);
                if (size == 0)
                {
                    throw new CryptographicException("Unable to sign the data.");
                }
                byte[] buffer = new byte[size];
                if (SspiProvider.CryptSignHash(hashptr, keySpec, IntPtr.Zero, 0, buffer, ref size) == 0)
                {
                    throw new CryptographicException("Unable to sign the data.");
                }
                Array.Reverse(buffer);
                return(buffer);
            } finally {
                if (hashptr != 0)
                {
                    SspiProvider.CryptDestroyHash(hashptr);
                }
                if (mustFree != 0 && provider != 0)
                {
                    SspiProvider.CryptReleaseContext(provider, 0);
                }
            }
        }
        /// <summary>
        /// Transforms the specified region of the specified byte array.
        /// </summary>
        /// <param name="inputBuffer">The input for which to compute the transform.</param>
        /// <param name="inputOffset">The offset into the byte array from which to begin using data.</param>
        /// <param name="inputCount">The number of bytes in the byte array to use as data.</param>
        /// <returns>The computed transform.</returns>
        /// <exception cref="ObjectDisposedException">The object has been disposed.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="inputBuffer"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
        /// <exception cref="ArgumentOutOfRangeException">The combination of offset and length is invalid.</exception>
        /// <exception cref="CryptographicException">An error occurs while transforming the specified data.</exception>
        public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
        {
            if (m_Key == null)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (inputBuffer == null)
            {
                throw new ArgumentNullException();
            }
            if (inputCount < 0 || inputOffset < 0 || inputOffset + inputCount > inputBuffer.Length)
            {
                throw new ArgumentOutOfRangeException();
            }
            int length = inputCount;

            byte[] ret;
            if (m_Method == CryptoMethod.Encrypt)
            {
                if (SspiProvider.CryptEncrypt(m_Key.Handle, 0, 1, 0, null, ref length, 0) == 0)
                {
                    throw new CryptographicException("Could not encrypt data.");
                }
                ret = new byte[length];
                Buffer.BlockCopy(inputBuffer, inputOffset, ret, 0, inputCount);
                length = inputCount;
                if (SspiProvider.CryptEncrypt(m_Key.Handle, 0, 1, 0, ret, ref length, ret.Length) == 0)
                {
                    throw new CryptographicException("Could not encrypt data.");
                }
            }
            else                 // decrypt
            {
                byte[] orgCopy = new byte[inputCount];
                Buffer.BlockCopy(inputBuffer, inputOffset, orgCopy, 0, inputCount);
                if (SspiProvider.CryptDecrypt(m_Key.Handle, 0, 1, 0, orgCopy, ref length) == 0)
                {
                    throw new CryptographicException("Could not decrypt data.");
                }
                ret = new byte[length];
                Buffer.BlockCopy(orgCopy, 0, ret, 0, length);
            }
            return(ret);
        }
Пример #10
0
        /// <summary>
        /// Returns the bytes that represent the symmetric key.
        /// </summary>
        /// <returns>An array of bytes.</returns>
        /// <exception cref="ObjectDisposedException">The SymmetricKey has been disposed.</exception>
        public byte[] ToBytes()
        {
            if (m_Handle == 0)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            IntPtr pbSessionBlob = IntPtr.Zero;

            try {
                int dwSessionBlob = 0;
                if (SspiProvider.CryptExportKey(m_Handle, m_ExponentOfOne, SecurityConstants.SIMPLEBLOB, 0, IntPtr.Zero, ref dwSessionBlob) == 0)
                {
                    throw new SecurityException("Cannot export key.");
                }
                pbSessionBlob = Marshal.AllocHGlobal(dwSessionBlob);
                if (SspiProvider.CryptExportKey(m_Handle, m_ExponentOfOne, SecurityConstants.SIMPLEBLOB, 0, pbSessionBlob, ref dwSessionBlob) == 0)
                {
                    throw new SecurityException("Cannot export key.");
                }

                // Get session key size in bits
                int dwSize        = 4;          // sizeof(DWORD)
                int dwKeyMaterial = 0;
                if (SspiProvider.CryptGetKeyParam(m_Handle, SecurityConstants.KP_KEYLEN, ref dwKeyMaterial, ref dwSize, 0) == 0)
                {
                    throw new SecurityException("Cannot retrieve key parameters.");
                }
                // Get the number of bytes and allocate buffer
                dwKeyMaterial /= 8;
                byte[] pbKeyMaterial = new byte[dwKeyMaterial];
                // Skip the header
                int offset = 4 + IntPtr.Size;          // sizeof(BLOBHEADER);
                offset += IntPtr.Size;                 // sizeof(ALG_ID);
                Marshal.Copy(new IntPtr(pbSessionBlob.ToInt64() + offset), pbKeyMaterial, 0, pbKeyMaterial.Length);
                // the key is reversed
                Array.Reverse(pbKeyMaterial);
                return(pbKeyMaterial);
            } finally {
                if (pbSessionBlob != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pbSessionBlob);
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Initializes a new <see cref="CertificateChain"/> instance from a <see cref="Certificate"/>.
        /// </summary>
        /// <param name="cert">The certificate for which a chain is being built.</param>
        /// <param name="additional">Any additional store to be searched for supporting certificates and CTLs.</param>
        /// <param name="options">Additional certificate chain options.</param>
        /// <remarks><paramref name="cert"/> will always be the end certificate.</remarks>
        /// <exception cref="ArgumentNullException"><paramref name="cert"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
        /// <exception cref="CertificateException">An error occurs while building the certificate chain.</exception>
        public CertificateChain(Certificate cert, CertificateStore additional, CertificateChainOptions options)
        {
            if (cert == null)
            {
                throw new ArgumentNullException();
            }
            IntPtr          addstore = additional == null ? IntPtr.Zero : additional.Handle;
            ChainParameters para     = new ChainParameters();

            para.cbSize = Marshal.SizeOf(typeof(ChainParameters));
            para.RequestedUsagecUsageIdentifier     = 0;
            para.RequestedUsagedwType               = 0;
            para.RequestedUsagergpszUsageIdentifier = IntPtr.Zero;
            if (SspiProvider.CertGetCertificateChain(IntPtr.Zero, cert.Handle, IntPtr.Zero, addstore, ref para, (int)options, IntPtr.Zero, ref m_Handle) == 0)
            {
                throw new CertificateException("Unable to find the certificate chain.");
            }
            m_Certificate = cert;
        }
Пример #12
0
        public override void Initialize()
        {
            if (m_Disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (m_Hash != 0)
            {
                SspiProvider.CryptDestroyHash(m_Hash);
            }
            int type = SecurityConstants.CALG_SHA1;

            m_Size = 20;
            if (m_Type == HashType.MD5)
            {
                type   = SecurityConstants.CALG_MD5;
                m_Size = 16;
            }
            SspiProvider.CryptCreateHash(m_Provider, type, 0, 0, out m_Hash);
        }
        /// <summary>
        /// Releases the unmanaged resources used by the <see cref="MD4CryptoServiceProvider"/> and optionally releases the managed resources.
        /// </summary>
        /// <param name="disposing"><b>true</b> to release both managed and unmanaged resources; <b>false</b> to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (!m_Disposed)
            {
                if (m_Hash != 0)
                {
                    SspiProvider.CryptDestroyHash(m_Hash);
                    m_Hash = 0;
                }

/*				if (m_Provider != 0) {
 *                                      SspiProvider.CryptReleaseContext(m_Provider, 0);
 *                                      m_Provider = 0;
 *                              }*/
                try {
                    GC.SuppressFinalize(this);
                } catch {}
                m_Disposed = true;
            }
        }
Пример #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="RC4CryptoServiceProvider"/> class.
        /// </summary>
        public RC4CryptoServiceProvider()
        {
            // acquire an RC4 context
            m_Provider = CAPIProvider.Handle;

/*			if (SspiProvider.CryptAcquireContext(ref m_Provider, IntPtr.Zero, null, SecurityConstants.PROV_RSA_FULL, 0) == 0) {
 *                              if (Marshal.GetLastWin32Error() == SecurityConstants.NTE_BAD_KEYSET)
 *                                      SspiProvider.CryptAcquireContext(ref m_Provider, IntPtr.Zero, null, SecurityConstants.PROV_RSA_FULL, SecurityConstants.CRYPT_NEWKEYSET);
 *                      }*/
            if (m_Provider != 0)
            {
                int    dwFlags  = SecurityConstants.CRYPT_FIRST;
                bool   found    = false;
                IntPtr provEnum = Marshal.AllocHGlobal(100);
                int    dwSize;
                do
                {
                    dwSize = 100;
                    if (SspiProvider.CryptGetProvParam(m_Provider, SecurityConstants.PP_ENUMALGS_EX, provEnum, ref dwSize, dwFlags) == 0)
                    {
                        break;
                    }
                    dwFlags = 0;
                    PROV_ENUMALGS_EX eax = (PROV_ENUMALGS_EX)Marshal.PtrToStructure(provEnum, typeof(PROV_ENUMALGS_EX));
                    if (eax.aiAlgid == SecurityConstants.CALG_RC4)
                    {
                        found    = true;
                        m_MinLen = eax.dwMinLen;
                        m_MaxLen = eax.dwMaxLen;
                    }
                } while (!found);
                Marshal.FreeHGlobal(provEnum);

/*				if (!found) {
 *                                      SspiProvider.CryptReleaseContext(m_Provider, 0);
 *                                      m_Provider = 0;
 *                              }*/
            }
            m_Managed = new ARCFourManaged();
        }
Пример #15
0
        /// <summary>
        /// Returns the list of certificates in this <see cref="CertificateChain"/>.
        /// </summary>
        /// <returns>An array of <see cref="Certificate"/> instances.</returns>
        /// <remarks>
        /// The certificate with index 0 is the end certificate in the chain, the certificate with the highest index is the root certificate [if it can be found].
        /// </remarks>
        // Thanks go out to Hernan de Lahitte and Neil for notifying us about a bug in this method.
        public virtual Certificate[] GetCertificates()
        {
            ArrayList ret = new ArrayList();
            int       dwVerificationFlags;
            IntPtr    store;
            CertificateStoreCollection csc, cs = this.Certificate.Store as CertificateStoreCollection;

            if (cs != null)
            {
                csc = new CertificateStoreCollection(cs);
            }
            else
            {
                csc = new CertificateStoreCollection(new CertificateStore[0]);
                if (this.Certificate.Store == null)
                {
                    csc.AddStore(new CertificateStore(this.Certificate.m_Context.hCertStore, true));
                }
                else
                {
                    csc.AddStore(this.Certificate.Store);
                }
            }
            csc.AddStore(CertificateStore.GetCachedStore(CertificateStore.RootStore));
            csc.AddStore(CertificateStore.GetCachedStore(CertificateStore.CAStore));
            store = csc.Handle;

            IntPtr cert = this.Certificate.DuplicateHandle();

            while (cert != IntPtr.Zero)
            {
                ret.Add(new Certificate(cert, false));
                dwVerificationFlags = 0;
                cert = SspiProvider.CertGetIssuerCertificateFromStore(store, cert, IntPtr.Zero, ref dwVerificationFlags);
            }

            csc.Dispose();             // don't use csc anymore after this line!!!

            return((Certificate[])ret.ToArray(typeof(Certificate)));
        }
Пример #16
0
 protected override void HashCore(byte[] array, int ibStart, int cbSize)
 {
     if (ibStart > 0)
     {
         GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
         try {
             IntPtr address = handle.AddrOfPinnedObject();
             if (SspiProvider.CryptHashData(m_Hash, new IntPtr(address.ToInt64() + ibStart), cbSize, 0) == 0)
             {
                 throw new CryptographicException("The data could not be hashed.");
             }
         } finally {
             handle.Free();
         }
     }
     else
     {
         if (SspiProvider.CryptHashData(m_Hash, array, cbSize, 0) == 0)
         {
             throw new CryptographicException("The data could not be hashed.");
         }
     }
 }
Пример #17
0
        /// <summary>
        /// Transforms the specified region of the specified byte array.
        /// </summary>
        /// <param name="inputBuffer">The input for which to compute the transform.</param>
        /// <param name="inputOffset">The offset into the byte array from which to begin using data.</param>
        /// <param name="inputCount">The number of bytes in the byte array to use as data.</param>
        /// <returns>The computed transform.</returns>
        /// <exception cref="ObjectDisposedException">The object has been disposed.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="inputBuffer"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="inputOffset"/> or <paramref name="inputCount"/> is invalid.</exception>
        public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
        {
            if (m_Key == null)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (inputBuffer == null)
            {
                throw new ArgumentNullException();
            }
            if (inputCount < 0 || inputOffset < 0 || inputOffset + inputCount > inputBuffer.Length)
            {
                throw new ArgumentOutOfRangeException();
            }
            byte[] buffer = new byte[inputCount];
            int    length = buffer.Length;

            Buffer.BlockCopy(inputBuffer, inputOffset, buffer, 0, length);
            if (SspiProvider.CryptEncrypt(m_Key.Handle, 0, 1, 0, buffer, ref length, length) == 0)
            {
                throw new CryptographicException("Could not transform data.");
            }
            return(buffer);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="CertificateStoreCollection"/> class.
 /// </summary>
 /// <param name="stores">An array of stores that should be added to the collection.</param>
 /// <exception cref="ArgumentNullException"><paramref name="stores"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
 /// <exception cref="ArgumentException">One of the <see cref="CertificateStore"/> objects in the array is a <see cref="CertificateStoreCollection"/> instance. This is not allowed to avoid circular dependencies.</exception>
 /// <exception cref="CertificateException">An error occurs while adding a certificate to the collection.</exception>
 public CertificateStoreCollection(CertificateStore[] stores) : base(SspiProvider.CertOpenStore(new IntPtr(SecurityConstants.CERT_STORE_PROV_COLLECTION), 0, 0, 0, null), false)
 {
     if (stores == null)
     {
         throw new ArgumentNullException();
     }
     for (int i = 0; i < stores.Length; i++)
     {
         if (stores[i].ToString() == this.ToString())
         {
             // used in order to avoid circular dependencies
             throw new ArgumentException("A certificate store collection cannot hold other certificate store collections.");
         }
     }
     for (int i = 0; i < stores.Length; i++)
     {
         if (SspiProvider.CertAddStoreToCollection(this.Handle, stores[i].Handle, 0, 0) == 0)
         {
             throw new CertificateException("Could not add the store to the collection.");
         }
     }
     m_Stores = new ArrayList();             // used to hold references to the certificate stores so they cannot be finalized
     m_Stores.AddRange(stores);
 }
Пример #19
0
        /// <summary>
        /// Dynamically creates an exponent-of-one key.
        /// </summary>
        /// <returns>The handle of a exponent-of-one key.</returns>
        /// <exception cref="SecurityException">An error occurs while creating the key.</exception>
        private int CreateDynamicExponentOfOneKey()
        {
            int    hPrivateKey = 0;
            int    dwKeyBlob   = 0;
            IntPtr keyblob     = IntPtr.Zero;
            int    dwBitLen;

            try {
                if (SspiProvider.CryptGenKey(m_Provider, new IntPtr(SecurityConstants.AT_KEYEXCHANGE), SecurityConstants.CRYPT_EXPORTABLE, ref hPrivateKey) == 0)
                {
                    throw new SecurityException("Cannot generate key pair.");
                }
                // Export the private key, we'll convert it to a private
                // exponent of one key
                if (SspiProvider.CryptExportKey(hPrivateKey, 0, SecurityConstants.PRIVATEKEYBLOB, 0, IntPtr.Zero, ref dwKeyBlob) == 0)
                {
                    throw new SecurityException("Cannot export generated key.");
                }
                keyblob = Marshal.AllocHGlobal(dwKeyBlob);
                if (SspiProvider.CryptExportKey(hPrivateKey, 0, SecurityConstants.PRIVATEKEYBLOB, 0, keyblob, ref dwKeyBlob) == 0)
                {
                    throw new SecurityException("Cannot export generated key.");
                }
                SspiProvider.CryptDestroyKey(hPrivateKey);
                hPrivateKey = 0;
                // Get the bit length of the key
                dwBitLen = Marshal.ReadInt32(keyblob, 12);
                /* Modify the Exponent in Key BLOB format [Key BLOB format is documented in SDK] */
                // Convert pubexp in rsapubkey to 1
                int offset = 16;
                for (int i = 0; i < 4; i++)
                {
                    if (i == 0)
                    {
                        Marshal.WriteByte(keyblob, offset, 1);
                    }
                    else
                    {
                        Marshal.WriteByte(keyblob, offset + i, 0);
                    }
                }
                // Skip pubexp
                offset += 4;
                // Skip modulus, prime1, prime2
                offset += dwBitLen / 8;
                offset += dwBitLen / 16;
                offset += dwBitLen / 16;
                // Convert exponent1 to 1
                for (int i = 0; i < dwBitLen / 16; i++)
                {
                    if (i == 0)
                    {
                        Marshal.WriteByte(keyblob, offset, 1);
                    }
                    else
                    {
                        Marshal.WriteByte(keyblob, offset + i, 0);
                    }
                }
                // Skip exponent1
                offset += dwBitLen / 16;
                // Convert exponent2 to 1
                for (int i = 0; i < dwBitLen / 16; i++)
                {
                    if (i == 0)
                    {
                        Marshal.WriteByte(keyblob, offset, 1);
                    }
                    else
                    {
                        Marshal.WriteByte(keyblob, offset + i, 0);
                    }
                }
                // Skip exponent2, coefficient
                offset += dwBitLen / 16;
                offset += dwBitLen / 16;
                // Convert privateExponent to 1
                for (int i = 0; i < dwBitLen / 8; i++)
                {
                    if (i == 0)
                    {
                        Marshal.WriteByte(keyblob, offset, 1);
                    }
                    else
                    {
                        Marshal.WriteByte(keyblob, offset + i, 0);
                    }
                }
                // Import the exponent-of-one private key.
                if (SspiProvider.CryptImportKey(m_Provider, keyblob, dwKeyBlob, 0, SecurityConstants.CRYPT_EXPORTABLE, ref hPrivateKey) == 0)
                {
                    throw new SecurityException("Could not import modified key.");
                }
            } catch (Exception e) {
                if (hPrivateKey != 0)
                {
                    SspiProvider.CryptDestroyKey(hPrivateKey);
                }
                throw e;
            } finally {
                if (keyblob != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(keyblob);
                }
            }
            return(hPrivateKey);
        }
        /// <summary>
        /// Decrypts data that has been encrypted with the <see cref="ProtectData"/> method.
        /// </summary>
        /// <param name="data">The data to decrypt.</param>
        /// <param name="offset">The zero-based position in the <i>data</i> parameter at which to begin decrypting.</param>
        /// <param name="size">The number of bytes to decrypt.</param>
        /// <param name="entropy">Additional entropy to use during the decryption process. This parameter can be set to null.</param>
        /// <exception cref="ArgumentNullException"><i>data</i> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
        /// <exception cref="ArgumentException">The specified <i>offset</i> or <i>size</i> exceeds the size of buffer.</exception>
        /// <exception cref="CryptographicException">An error occurs during the encryption process. Under some circumstances, Microsoft cryptographic service providers may not allow encryption when used in France. This may occur on down-level platforms such as Windows 98 and Windows NT 4.0, depending on the system's configuration and the version of the CSPs.</exception>
        /// <returns>The decrypted data.</returns>
        /// <remarks>The entropy used during decryption must be the same as the entropy used during encryption.</remarks>
        public byte[] UnprotectData(byte[] data, int offset, int size, byte[] entropy)
        {
            if (m_Disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (data == null)
            {
                throw new ArgumentNullException();
            }
            if (offset < 0 || offset + size > data.Length)
            {
                throw new ArgumentException();
            }
            DataBlob input  = new DataBlob();
            DataBlob entr   = new DataBlob();
            DataBlob output = new DataBlob();

            try {
                // initialize input structure
                input.cbData = size;
                input.pbData = Marshal.AllocHGlobal(size);
                Marshal.Copy(data, offset, input.pbData, size);
                // initialize entropy structure
                if (entropy == null)
                {
                    entr.cbData = 0;
                    entr.pbData = IntPtr.Zero;
                }
                else
                {
                    entr.cbData = entropy.Length;
                    entr.pbData = Marshal.AllocHGlobal(entr.cbData);
                    Marshal.Copy(entropy, 0, entr.pbData, entr.cbData);
                }
                // initialize output structure
                output.cbData = 0;
                output.pbData = IntPtr.Zero;
                // call the function and check for errors
                int flags = 0;
                if (!Environment.UserInteractive)
                {
                    flags = flags | SecurityConstants.CRYPTPROTECT_UI_FORBIDDEN;
                }
                if (SspiProvider.CryptUnprotectData(ref input, IntPtr.Zero, ref entr, IntPtr.Zero, IntPtr.Zero, flags, ref output) == 0 || output.pbData == IntPtr.Zero)
                {
                    throw new CryptographicException("The data could not be unprotected.");
                }
                byte[] ret = new byte[output.cbData];
                Marshal.Copy(output.pbData, ret, 0, output.cbData);
                return(ret);
            } finally {
                if (input.pbData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(input.pbData);
                }
                if (entr.pbData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(entr.pbData);
                }
                if (output.pbData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(output.pbData);
                }
            }
        }
Пример #21
0
        /// <summary>
        /// Imports a specified key.
        /// </summary>
        /// <param name="provider">The handle of the CSP.</param>
        /// <param name="algorithm">One of the <see cref="CryptoAlgorithm"/> values.</param>
        /// <param name="key">The key to import.</param>
        /// <returns>The handle of the symmetric key.</returns>
        /// <exception cref="SecurityException">An error occurs while importing the specified key.</exception>
        private int KeyFromBytes(int provider, CryptoAlgorithm algorithm, byte[] key)
        {
            int    dwFlags = SecurityConstants.CRYPT_FIRST, dwSize, dwProvSessionKeySize = 0, dwPublicKeySize = 0, dwSessionBlob, offset = 0, hTempKey = 0, hSessionKey = 0;
            IntPtr algo = new IntPtr((int)algorithm), dwPrivKeyAlg = IntPtr.Zero, pbSessionBlob = IntPtr.Zero;
            IntPtr provEnum = IntPtr.Zero;

            try {
                // Double check to see if this provider supports this algorithm
                // and key size
                bool found = false;
                provEnum = Marshal.AllocHGlobal(84 + IntPtr.Size);
                do
                {
                    dwSize = 84 + IntPtr.Size;
                    if (SspiProvider.CryptGetProvParam(provider, SecurityConstants.PP_ENUMALGS_EX, provEnum, ref dwSize, dwFlags) == 0)
                    {
                        break;
                    }
                    dwFlags = 0;
                    if (Marshal.ReadIntPtr(provEnum) == algo)
                    {
                        found = true;
                    }
                } while (!found);
                if (!found)
                {
                    throw new SecurityException("CSP does not support selected algorithm.");
                }
                // We have to get the key size(including padding)
                // from an HCRYPTKEY handle.  PP_ENUMALGS_EX contains
                // the key size without the padding so we can't use it.
                if (SspiProvider.CryptGenKey(provider, algo, 0, ref hTempKey) == 0)
                {
                    throw new SecurityException("Cannot generate temporary key.");
                }
                dwSize = 4;                 // sizeof(int)
                if (SspiProvider.CryptGetKeyParam(hTempKey, SecurityConstants.KP_KEYLEN, ref dwProvSessionKeySize, ref dwSize, 0) == 0)
                {
                    throw new SecurityException("Cannot retrieve key parameters.");
                }
                // Our key is too big, leave
                if ((key.Length * 8) > dwProvSessionKeySize)
                {
                    throw new SecurityException("Key too big.");
                }
                // Get private key's algorithm
                dwSize = IntPtr.Size;                 //sizeof(ALG_ID)
                if (SspiProvider.CryptGetKeyParam(m_ExponentOfOne, SecurityConstants.KP_ALGID, ref dwPrivKeyAlg, ref dwSize, 0) == 0)
                {
                    throw new SecurityException("Unable to get the private key's algorithm.");
                }
                // Get private key's length in bits
                dwSize = 4;                 // sizeof(DWORD)
                if (SspiProvider.CryptGetKeyParam(m_ExponentOfOne, SecurityConstants.KP_KEYLEN, ref dwPublicKeySize, ref dwSize, 0) == 0)
                {
                    throw new SecurityException("Unable to get the key length.");
                }
                // calculate Simple blob's length
                dwSessionBlob = (dwPublicKeySize / 8) + IntPtr.Size /*sizeof(ALG_ID)*/ + 4 + IntPtr.Size /*sizeof(BLOBHEADER)*/;
                // allocate simple blob buffer
                pbSessionBlob = Marshal.AllocHGlobal(dwSessionBlob);
                // SIMPLEBLOB Format is documented in SDK
                // Copy header to buffer
                PUBLICKEYSTRUC pks = new PUBLICKEYSTRUC();
                pks.bType    = SecurityConstants.SIMPLEBLOB;
                pks.bVersion = 2;
                pks.reserved = 0;
                pks.aiKeyAlg = algo;
                Marshal.StructureToPtr(pks, pbSessionBlob, false);
                Marshal.WriteIntPtr(pbSessionBlob, offset = Marshal.SizeOf(pks), dwPrivKeyAlg);
                offset += IntPtr.Size;                 // sizeof(ALG_ID)
                // Place the key material in reverse order
                for (int i = 0; i < key.Length; i++)
                {
                    Marshal.WriteByte(pbSessionBlob, offset + key.Length - i - 1, key[i]);
                }
                // 3 is for the first reserved byte after the key material + the 2 reserved bytes at the end.
                dwSize  = dwSessionBlob - (IntPtr.Size /*sizeof(ALG_ID)*/ + IntPtr.Size + 4 /*sizeof(BLOBHEADER)*/ + key.Length + 3);
                offset += key.Length + 1;
                // Generate random data for the rest of the buffer
                // (except that last two bytes)
                if (SspiProvider.CryptGenRandom(provider, dwSize, new IntPtr(pbSessionBlob.ToInt64() + offset)) == 0)
                {
                    throw new SecurityException("Could not generate random data.");
                }
                for (int i = 0; i < dwSize; i++)
                {
                    if (Marshal.ReadByte(pbSessionBlob, offset) == 0)
                    {
                        Marshal.WriteByte(pbSessionBlob, offset, 1);
                    }
                    offset++;
                }
                Marshal.WriteByte(pbSessionBlob, dwSessionBlob - 2, 2);
                if (SspiProvider.CryptImportKey(provider, pbSessionBlob, dwSessionBlob, m_ExponentOfOne, SecurityConstants.CRYPT_EXPORTABLE, ref hSessionKey) == 0)
                {
                    throw new SecurityException("Cannot import key [key has right size?].");
                }
            } finally {
                if (provEnum != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(provEnum);
                }
                if (hTempKey != 0)
                {
                    SspiProvider.CryptDestroyKey(hTempKey);
                }
                if (pbSessionBlob != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pbSessionBlob);
                }
            }
            return(hSessionKey);
        }