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);
                }
            }
        }
Esempio n. 2
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 {}
        }
Esempio n. 3
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);
        }
Esempio n. 4
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);
        }