Example #1
0
        /// <summary>
        /// Open an existing RSA CSP
        /// </summary>
        /// <param name="providerName">Name of the provider</param>
        /// <param name="containerName">Name of container</param>
        /// <exception cref="Win32Exception"/>
        /// <returns>Handle to the crypt provider</returns>
        private CryptoApiMethods.SafeCryptProviderHandle OpenRSAProvider(string providerName, string containerName)
        {
            CryptoApiMethods.SafeCryptProviderHandle hCryptProv;

            if (!CryptoApiMethods.CryptAcquireContext(out hCryptProv, containerName, providerName, CryptoApiMethods.Providers.PROV_RSA_FULL, 0))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            if (hCryptProv == null)
            {
                throw new CryptographicException();
            }

            return(hCryptProv);
        }
Example #2
0
        /// <summary>
        /// Encode an arbitary crypto object
        /// </summary>
        /// <param name="objName">OID for the encoding</param>
        /// <param name="obj">The object to encode</param>
        /// <exception cref="Win32Exception"/>
        /// <returns>The encoded object</returns>
        private byte[] EncodeObject(string objName, object obj)
        {
            byte[] ret            = new byte[0];
            uint   cbEncoded      = 0;
            IntPtr pStruct        = Marshal.AllocHGlobal(Marshal.SizeOf(obj));
            bool   bCreatedStruct = false;

            try
            {
                Marshal.StructureToPtr(obj, pStruct, false);
                bCreatedStruct = true;

                if (!CryptoApiMethods.CryptEncodeObject(CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                                                        objName, pStruct, null, ref cbEncoded))
                {
                    int err = Marshal.GetLastWin32Error();

                    // If not the error for needing more data
                    if (err != 234)
                    {
                        throw new Win32Exception(err);
                    }
                }

                ret = new byte[cbEncoded];

                if (!CryptoApiMethods.CryptEncodeObject(CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                                                        objName, pStruct, ret, ref cbEncoded))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                if (bCreatedStruct)
                {
                    Marshal.DestroyStructure(pStruct, obj.GetType());
                }

                if (pStruct != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pStruct);
                }
            }

            return(ret);
        }
Example #3
0
        /// <summary>
        /// Hash public key info of a specified RSA key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private byte[] HashPublicKeyInfo(RSACryptoServiceProvider key)
        {
            CryptoApiMethods.SafeCryptProviderHandle hProv = new CryptoApiMethods.SafeCryptProviderHandle();
            IntPtr publicKeyInfoPtr = IntPtr.Zero;

            byte[] ret = null;
            uint   len = 0;

            try
            {
                publicKeyInfoPtr = ExportPublicKeyInfo(key);
                CryptoApiMethods.CERT_PUBLIC_KEY_INFO publicKeyInfo = (CryptoApiMethods.CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(publicKeyInfoPtr, typeof(CryptoApiMethods.CERT_PUBLIC_KEY_INFO));

                hProv = OpenRSAProvider(key.CspKeyContainerInfo.ProviderName, key.CspKeyContainerInfo.KeyContainerName);

                if (!CryptoApiMethods.CryptHashPublicKeyInfo(hProv, 0, 0, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                                                             publicKeyInfo, null, out len))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                ret = new byte[len];

                if (!CryptoApiMethods.CryptHashPublicKeyInfo(hProv, 0, 0, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                                                             publicKeyInfo, ret, out len))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                if (!hProv.IsInvalid)
                {
                    hProv.Close();
                }

                if (publicKeyInfoPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(publicKeyInfoPtr);
                }
            }

            return(ret);
        }
Example #4
0
        /// <summary>
        /// Encode and sign a CERT_INFO structure
        /// </summary>
        /// <param name="hProv"></param>
        /// <param name="certInfo"></param>
        /// <param name="signature">True encodes with a AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="hashAlgorithm"></param>
        /// <returns></returns>
        private byte[] EncodeAndSignCertInfo(CryptoApiMethods.SafeCryptProviderHandle hProv, CryptoApiMethods.CERT_INFO certInfo, bool signature, CertificateHashAlgorithm hashAlgorithm)
        {
            CryptoApiMethods.CALG keyType = signature ? CryptoApiMethods.CALG.AT_SIGNATURE : CryptoApiMethods.CALG.AT_KEYEXCHANGE;
            byte[] ret         = null;
            uint   certLen     = 0;
            IntPtr certInfoPtr = IntPtr.Zero;

            CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm = new CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER();
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_OIWSEC_sha1RSASign;
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA1RSA;
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA512RSA;
            SignatureAlgorithm.pszObjId = HashAlgorithmToOID(hashAlgorithm);

            try
            {
                certInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(certInfo));
                Marshal.StructureToPtr(certInfo, certInfoPtr, false);

                if (!CryptoApiMethods.CryptSignAndEncodeCertificate(hProv, keyType, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                                                                    new IntPtr((int)CryptoApiMethods.StructType.X509_CERT_TO_BE_SIGNED), certInfoPtr, SignatureAlgorithm, IntPtr.Zero, null, ref certLen))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                ret = new byte[certLen];

                if (!CryptoApiMethods.CryptSignAndEncodeCertificate(hProv, keyType, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                                                                    new IntPtr((int)CryptoApiMethods.StructType.X509_CERT_TO_BE_SIGNED), certInfoPtr, SignatureAlgorithm, IntPtr.Zero, ret, ref certLen))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                Marshal.DestroyStructure(certInfoPtr, certInfo.GetType());
                Marshal.FreeHGlobal(certInfoPtr);
            }

            return(ret);
        }
Example #5
0
        /// <summary>
        /// Export the public RSA keyinfo from the current crypto provider
        /// </summary>
        /// <param name="hProv">Handle to the crypto provider</param>
        /// <param name="signature">Set to true for AT_SIGNATURE, false for AT_KEYEXCHANGE</param>
        /// <returns>An IntPtr pointing to the public key info structure</returns>
        private IntPtr ExportPublicKeyInfo(CryptoApiMethods.SafeCryptProviderHandle hProv, bool signature)
        {
            CryptoApiMethods.CALG type = signature ? CryptoApiMethods.CALG.AT_SIGNATURE : CryptoApiMethods.CALG.AT_KEYEXCHANGE;
            IntPtr ret     = IntPtr.Zero;
            uint   infoLen = 0;

            if (!CryptoApiMethods.CryptExportPublicKeyInfoEx(hProv, type, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                                                             CryptoApiMethods.szOID_RSA_RSA, 0, IntPtr.Zero, ret, ref infoLen))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            ret = Marshal.AllocHGlobal((int)infoLen);

            if (!CryptoApiMethods.CryptExportPublicKeyInfoEx(hProv, type, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                                                             CryptoApiMethods.szOID_RSA_RSA, 0, IntPtr.Zero, ret, ref infoLen))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            return(ret);
        }
Example #6
0
 protected override bool ReleaseHandle()
 {
     return(CryptoApiMethods.CryptDestroyKey(handle));
 }
Example #7
0
 protected override bool ReleaseHandle()
 {
     return(CryptoApiMethods.CryptReleaseContext(handle, 0));
 }
        /// <summary>
        /// Export the public RSA keyinfo from the current crypto provider
        /// </summary>
        /// <param name="hProv">Handle to the crypto provider</param>
        /// <param name="signature">Set to true for AT_SIGNATURE, false for AT_KEYEXCHANGE</param>
        /// <returns>An IntPtr pointing to the public key info structure</returns>
        private IntPtr ExportPublicKeyInfo(CryptoApiMethods.SafeCryptProviderHandle hProv, bool signature)
        {
            CryptoApiMethods.CALG type = signature ? CryptoApiMethods.CALG.AT_SIGNATURE : CryptoApiMethods.CALG.AT_KEYEXCHANGE;
            IntPtr ret = IntPtr.Zero;
            uint infoLen = 0;

            if (!CryptoApiMethods.CryptExportPublicKeyInfoEx(hProv, type, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                CryptoApiMethods.szOID_RSA_RSA, 0, IntPtr.Zero, ret, ref infoLen))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            ret = Marshal.AllocHGlobal((int)infoLen);

            if (!CryptoApiMethods.CryptExportPublicKeyInfoEx(hProv, type, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                CryptoApiMethods.szOID_RSA_RSA, 0, IntPtr.Zero, ret, ref infoLen))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            return ret;
        }
        /// <summary>
        /// Encode and sign a CERT_INFO structure
        /// </summary>
        /// <param name="hProv"></param>
        /// <param name="certInfo"></param>
        /// <param name="signature">True encodes with a AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="hashAlgorithm"></param>
        /// <returns></returns>
        private byte[] EncodeAndSignCertInfo(CryptoApiMethods.SafeCryptProviderHandle hProv, CryptoApiMethods.CERT_INFO certInfo, bool signature, CertificateHashAlgorithm hashAlgorithm)
        {
            CryptoApiMethods.CALG keyType = signature ? CryptoApiMethods.CALG.AT_SIGNATURE : CryptoApiMethods.CALG.AT_KEYEXCHANGE;
            byte[] ret = null;
            uint certLen = 0;
            IntPtr certInfoPtr = IntPtr.Zero;
            CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm = new CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER();
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_OIWSEC_sha1RSASign;
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA1RSA;
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA512RSA;
            SignatureAlgorithm.pszObjId = HashAlgorithmToOID(hashAlgorithm);

            try
            {
                certInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(certInfo));
                Marshal.StructureToPtr(certInfo, certInfoPtr, false);

                if (!CryptoApiMethods.CryptSignAndEncodeCertificate(hProv, keyType, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                    new IntPtr((int)CryptoApiMethods.StructType.X509_CERT_TO_BE_SIGNED), certInfoPtr, SignatureAlgorithm, IntPtr.Zero, null, ref certLen))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                ret = new byte[certLen];

                if (!CryptoApiMethods.CryptSignAndEncodeCertificate(hProv, keyType, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                    new IntPtr((int)CryptoApiMethods.StructType.X509_CERT_TO_BE_SIGNED), certInfoPtr, SignatureAlgorithm, IntPtr.Zero, ret, ref certLen))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                Marshal.DestroyStructure(certInfoPtr, certInfo.GetType());
                Marshal.FreeHGlobal(certInfoPtr);
            }

            return ret;
        }
        /// <summary>
        /// Encode and sign a CERT_INFO structure
        /// </summary>
        /// <param name="key">Key to sign the certificate with</param>
        /// <param name="certInfo">The CERT_INFO structure to sign</param>
        /// <param name="hashAlgorithm"></param>
        /// <returns></returns>
        private byte[] EncodeAndSignCertInfo(RSACryptoServiceProvider key, CryptoApiMethods.CERT_INFO certInfo, CertificateHashAlgorithm hashAlgorithm)
        {
            byte[] ret = null;
            CryptoApiMethods.SafeCryptProviderHandle hProv = new CryptoApiMethods.SafeCryptProviderHandle();

            try
            {
                hProv = OpenRSAProvider(key.CspKeyContainerInfo.ProviderName, key.CspKeyContainerInfo.KeyContainerName);

                ret = EncodeAndSignCertInfo(hProv, certInfo, key.CspKeyContainerInfo.KeyNumber == KeyNumber.Signature ? true : false, hashAlgorithm);
            }
            finally
            {
                if (!hProv.IsInvalid)
                {
                    hProv.Close();
                }
            }

            return ret;
        }