Esempio n. 1
0
 private static extern bool CreateDeltaB(
     DeltaFileType fileTypeSet,       // File type set.
     DeltaFlag setFlags,              // Set these flags.
     DeltaFlag resetFlags,            // Reset (suppress) these flags.
     DeltaInput source,               // Source memory block.
     DeltaInput target,               // Target memory block.
     DeltaInput sourceOptions,        // Memory block with source-specific options.
     DeltaInput targetOptions,        // Memory block with target-specific options.
     DeltaInput globalOptions,        // Memory block with global options.
     IntPtr targetFileTime,           // Target file time to use, null to use current time. (need this overload because the compiler can't convert from "null" to "ref FILETIME")
     AlgId hashAlgId,
     out DeltaOutput delta);
Esempio n. 2
0
 private static extern bool CreateDeltaB(
     DeltaFileType fileTypeSet,                                           // File type set.
     DeltaFlag setFlags,                                                  // Set these flags.
     DeltaFlag resetFlags,                                                // Reset (suppress) these flags.
     DeltaInput source,                                                   // Source memory block.
     DeltaInput target,                                                   // Target memory block.
     DeltaInput sourceOptions,                                            // Memory block with source-specific options.
     DeltaInput targetOptions,                                            // Memory block with target-specific options.
     DeltaInput globalOptions,                                            // Memory block with global options.
     ref System.Runtime.InteropServices.ComTypes.FILETIME targetFileTime, // Target file time to use, null to use current time.
     AlgId hashAlgId,
     out DeltaOutput delta);
Esempio n. 3
0
            //
            // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb".
            //
            private static CMSG_RECIPIENT_ENCODE_INFO EncodeRecipientInfo(CmsRecipient recipient, AlgorithmIdentifier contentEncryptionAlgorithm, HeapBlockRetainer hb)
            {
                CMsgCmsRecipientChoice recipientChoice;
                string keyAlgorithmOid = recipient.Certificate.GetKeyAlgorithm();
                AlgId  algId           = keyAlgorithmOid.ToAlgId();

                switch (algId)
                {
                case AlgId.CALG_RSA_KEYX:
                    recipientChoice = CMsgCmsRecipientChoice.CMSG_KEY_TRANS_RECIPIENT;
                    break;

                case AlgId.CALG_DH_SF:
                case AlgId.CALG_DH_EPHEM:
                    recipientChoice = CMsgCmsRecipientChoice.CMSG_KEY_AGREE_RECIPIENT;
                    break;

                default:
                    throw ErrorCode.CRYPT_E_UNKNOWN_ALGO.ToCryptographicException();
                }

                CMSG_RECIPIENT_ENCODE_INFO recipientEncodeInfo;

                recipientEncodeInfo.dwRecipientChoice = recipientChoice;

                unsafe
                {
                    switch (recipientChoice)
                    {
                    case CMsgCmsRecipientChoice.CMSG_KEY_TRANS_RECIPIENT:
                        recipientEncodeInfo.pCmsRecipientEncodeInfo = (IntPtr)EncodeKeyTransRecipientInfo(recipient, hb);
                        break;

                    case CMsgCmsRecipientChoice.CMSG_KEY_AGREE_RECIPIENT:
                        recipientEncodeInfo.pCmsRecipientEncodeInfo = (IntPtr)EncodeKeyAgreeRecipientInfo(recipient, contentEncryptionAlgorithm, hb);
                        break;

                    default:
                        throw ErrorCode.CRYPT_E_UNKNOWN_ALGO.ToCryptographicException();
                    }
                }
                return(recipientEncodeInfo);
            }
Esempio n. 4
0
        static string AlgIdToJwsAlgId(AlgId algId)
        {
            if (algId == AlgId.CALG_SHA_256)
            {
                return("RS256");
            }

            if (algId == AlgId.CALG_SHA_384)
            {
                return("RS384");
            }

            if (algId == AlgId.CALG_SHA_512)
            {
                return("RS512");
            }

            Console.Error.WriteLine("Only sha256, sha384, and sha512 is supported by Azure Key Vault signing");
            return(null);
        }
Esempio n. 5
0
        public static int AuthenticodeDigestSign([In] IntPtr pSignerCert,
                                                 [In] ref CRYPT_ATTR_BLOB pMetadataBlob,
                                                 [In] AlgId digestAlgID,
                                                 [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] pbToBeSignedDigest,
                                                 [In] int cbToBeSignedDigest,
                                                 [Out] out CRYPT_ATTR_BLOB pSignedDigest
                                                 )
        {
            pSignedDigest = default;

            try
            {
                //  var signerCert = new X509Certificate2(pSignerCert);
                var accessToken   = Environment.GetEnvironmentVariable("KEYVAULT_ACCESSTOKEN");
                var keyIdentifier = Environment.GetEnvironmentVariable("KEYVAULT_KEY_IDENTIFIER");

                HookAssemblyLoad();

                var kvalg = AlgIdToJwsAlgId(digestAlgID);
                if (kvalg == null)
                {
                    return(-1);
                }

                var signed = SignWithKeyVault(keyIdentifier, accessToken, pbToBeSignedDigest, kvalg).Result;

                var buffer = Marshal.AllocHGlobal(signed.Length);
                Marshal.Copy(signed, 0, buffer, signed.Length);
                pSignedDigest = new CRYPT_ATTR_BLOB
                {
                    pbData = buffer,
                    cbData = signed.Length
                };
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e.Message);
                return(Marshal.GetHRForException(e));
            }
            return(0);
        }
Esempio n. 6
0
            //
            // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb".
            //
            private static IntPtr GenerateEncryptionAuxInfoIfNeeded(AlgorithmIdentifier contentEncryptionAlgorithm, HeapBlockRetainer hb)
            {
                string algorithmOidValue = contentEncryptionAlgorithm.Oid.Value;
                AlgId  algId             = algorithmOidValue.ToAlgId();

                if (!(algId == AlgId.CALG_RC2 || algId == AlgId.CALG_RC4))
                {
                    return(IntPtr.Zero);
                }

                unsafe
                {
                    CMSG_RC2_AUX_INFO *pRc2AuxInfo = (CMSG_RC2_AUX_INFO *)(hb.Alloc(sizeof(CMSG_RC2_AUX_INFO)));
                    pRc2AuxInfo->cbSize   = sizeof(CMSG_RC2_AUX_INFO);
                    pRc2AuxInfo->dwBitLen = contentEncryptionAlgorithm.KeyLength;
                    if (pRc2AuxInfo->dwBitLen == 0)
                    {
                        // Desktop compat: If the caller didn't set the KeyLength property, set dwBitLength to the maxmium key length supported by RC2/RC4. The desktop queries CAPI for this but
                        // since that requires us to use a prohibited api (CryptAcquireContext), we'll just hardcode what CAPI returns for RC2 and RC4.
                        pRc2AuxInfo->dwBitLen = KeyLengths.DefaultKeyLengthForRc2AndRc4;
                    }
                    return((IntPtr)pRc2AuxInfo);
                }
            }
Esempio n. 7
0
        public static AlgorithmIdentifier ToAlgorithmIdentifier(this CRYPT_ALGORITHM_IDENTIFIER cryptAlgorithmIdentifer)
        {
            string oidValue = cryptAlgorithmIdentifer.pszObjId.ToStringAnsi();
            AlgId  algId    = oidValue.ToAlgId();

            int keyLength;

            switch (algId)
            {
            case AlgId.CALG_RC2:
            {
                if (cryptAlgorithmIdentifer.Parameters.cbData == 0)
                {
                    keyLength = 0;
                }
                else
                {
                    CRYPT_RC2_CBC_PARAMETERS rc2Parameters;
                    unsafe
                    {
                        int cbSize = sizeof(CRYPT_RC2_CBC_PARAMETERS);
                        if (!Interop.Crypt32.CryptDecodeObject(CryptDecodeObjectStructType.PKCS_RC2_CBC_PARAMETERS, cryptAlgorithmIdentifer.Parameters.pbData, (int)(cryptAlgorithmIdentifer.Parameters.cbData), &rc2Parameters, ref cbSize))
                        {
                            throw Interop.CPError.GetLastWin32Error().ToCryptographicException();
                        }
                    }

                    switch (rc2Parameters.dwVersion)
                    {
                    case CryptRc2Version.CRYPT_RC2_40BIT_VERSION:
                        keyLength = KeyLengths.Rc2_40Bit;
                        break;

                    case CryptRc2Version.CRYPT_RC2_56BIT_VERSION:
                        keyLength = KeyLengths.Rc2_56Bit;
                        break;

                    case CryptRc2Version.CRYPT_RC2_64BIT_VERSION:
                        keyLength = KeyLengths.Rc2_64Bit;
                        break;

                    case CryptRc2Version.CRYPT_RC2_128BIT_VERSION:
                        keyLength = KeyLengths.Rc2_128Bit;
                        break;

                    default:
                        keyLength = 0;
                        break;
                    }
                }
                break;
            }

            case AlgId.CALG_RC4:
            {
                int saltLength = 0;
                if (cryptAlgorithmIdentifer.Parameters.cbData != 0)
                {
                    using (SafeHandle sh = Interop.Crypt32.CryptDecodeObjectToMemory(CryptDecodeObjectStructType.X509_OCTET_STRING, cryptAlgorithmIdentifer.Parameters.pbData, (int)cryptAlgorithmIdentifer.Parameters.cbData))
                    {
                        unsafe
                        {
                            DATA_BLOB *pDataBlob = (DATA_BLOB *)(sh.DangerousGetHandle());
                            saltLength = (int)(pDataBlob->cbData);
                        }
                    }
                }

                // For RC4, keyLength = 128 - (salt length * 8).
                keyLength = KeyLengths.Rc4Max_128Bit - saltLength * 8;
                break;
            }

            case AlgId.CALG_DES:
                // DES key length is fixed at 64 (or 56 without the parity bits).
                keyLength = KeyLengths.Des_64Bit;
                break;

            case AlgId.CALG_3DES:
                // 3DES key length is fixed at 192 (or 168 without the parity bits).
                keyLength = KeyLengths.TripleDes_192Bit;
                break;

            default:
                // We've exhausted all the algorithm types that the desktop used to set the KeyLength for. Key lengths are not a viable way of
                // identifying algorithms in the long run so we will not extend this list any further.
                keyLength = 0;
                break;
            }

            AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Oid.FromOidValue(oidValue, OidGroup.All), keyLength);

            switch (oidValue)
            {
            case Oids.RsaOaep:
                algorithmIdentifier.Parameters = cryptAlgorithmIdentifer.Parameters.ToByteArray();
                break;
            }
            return(algorithmIdentifier);
        }
 internal static extern bool CryptGenKey(IntPtr hProv, AlgId Algid, int dwFlags, ref IntPtr phKey);
 internal static extern bool CryptCreateHash(IntPtr hProv, AlgId algId, IntPtr hKey, 
     uint dwFlags, ref IntPtr phHash);
Esempio n. 10
0
            //
            // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb".
            //
            private static unsafe CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO *EncodeKeyAgreeRecipientInfo(CmsRecipient recipient, AlgorithmIdentifier contentEncryptionAlgorithm, HeapBlockRetainer hb)
            {
                // "recipient" is a deep-cloned CmsRecipient object whose lifetime this class controls. Because of this, we can pull out the CERT_CONTEXT* and CERT_INFO* pointers without
                // bringing in all the SafeCertContextHandle machinery, and embed pointers to them in the memory block we return. Yes, this code is scary.
                using (SafeCertContextHandle hCertContext = recipient.Certificate.CreateCertContextHandle())
                {
                    CERT_CONTEXT *pCertContext = hCertContext.DangerousGetCertContext();
                    CERT_INFO *   pCertInfo    = pCertContext->pCertInfo;

                    CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO *pEncodeInfo = (CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO)));

                    pEncodeInfo->cbSize = sizeof(CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO);

                    pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.Esdh);
                    pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = 0;
                    pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = IntPtr.Zero;

                    pEncodeInfo->pvKeyEncryptionAuxInfo = null;

                    string oidValue;
                    AlgId  algId = contentEncryptionAlgorithm.Oid.Value.ToAlgId();
                    if (algId == AlgId.CALG_RC2)
                    {
                        oidValue = Oids.CmsRc2Wrap;
                    }
                    else
                    {
                        oidValue = Oids.Cms3DesWrap;
                    }

                    pEncodeInfo->KeyWrapAlgorithm.pszObjId          = hb.AllocAsciiString(oidValue);
                    pEncodeInfo->KeyWrapAlgorithm.Parameters.cbData = 0;
                    pEncodeInfo->KeyWrapAlgorithm.Parameters.pbData = IntPtr.Zero;

                    pEncodeInfo->pvKeyWrapAuxInfo = GenerateEncryptionAuxInfoIfNeeded(contentEncryptionAlgorithm, hb);

                    pEncodeInfo->hCryptProv             = IntPtr.Zero;
                    pEncodeInfo->dwKeySpec              = 0;
                    pEncodeInfo->dwKeyChoice            = CmsKeyAgreeKeyChoice.CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE;
                    pEncodeInfo->pEphemeralAlgorithm    = (CRYPT_ALGORITHM_IDENTIFIER *)(hb.Alloc(sizeof(CRYPT_ALGORITHM_IDENTIFIER)));
                    *(pEncodeInfo->pEphemeralAlgorithm) = pCertInfo->SubjectPublicKeyInfo.Algorithm;

                    pEncodeInfo->UserKeyingMaterial.cbData = 0;
                    pEncodeInfo->UserKeyingMaterial.pbData = IntPtr.Zero;

                    CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *pEncryptedKey = (CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO)));

                    pEncryptedKey->cbSize             = sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO);
                    pEncryptedKey->RecipientPublicKey = pCertInfo->SubjectPublicKeyInfo.PublicKey;

                    pEncryptedKey->RecipientId = EncodeRecipientId(recipient, hCertContext, pCertContext, pCertInfo, hb);
                    pEncryptedKey->Date        = default(FILETIME);
                    pEncryptedKey->pOtherAttr  = null;

                    CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO **ppEncryptedKey = (CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO **)(hb.Alloc(sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *)));
                    ppEncryptedKey[0] = pEncryptedKey;
                    pEncodeInfo->cRecipientEncryptedKeys   = 1;
                    pEncodeInfo->rgpRecipientEncryptedKeys = ppEncryptedKey;

                    return(pEncodeInfo);
                }
            }
Esempio n. 11
0
        internal byte[] DecryptInternal(string password, byte[] encryptionInfo, byte[] encryptedPackage)
        {
            #region Parse the encryption info data

            using (System.IO.MemoryStream ms = new System.IO.MemoryStream(encryptionInfo))
            {
                System.IO.BinaryReader reader = new System.IO.BinaryReader(ms);

                versionMajor = reader.ReadUInt16();
                versionMinor = reader.ReadUInt16();

                encryptionFlags = (EncryptionFlags)reader.ReadUInt32();
                if (encryptionFlags == EncryptionFlags.fExternal)
                    throw new Exception("An external cryptographic provider is not supported");

                // Encryption header
                uint headerLength		= reader.ReadUInt32();
                int skipFlags			= reader.ReadInt32(); headerLength -= 4;
                sizeExtra				= reader.ReadUInt32(); headerLength -= 4;
                algId					= (AlgId)reader.ReadUInt32(); headerLength -= 4;
                algHashId				= (AlgHashId)reader.ReadUInt32(); headerLength -= 4;
                keySize					= reader.ReadInt32(); headerLength -= 4;
                providerType			= (ProviderType)reader.ReadUInt32(); headerLength -= 4;
                                          reader.ReadUInt32(); headerLength -= 4; // Reserved 1
                                          reader.ReadUInt32(); headerLength -= 4; // Reserved 2
                CSPName					= System.Text.UnicodeEncoding.Unicode.GetString(reader.ReadBytes((int)headerLength));

                // Encryption verifier
                saltSize				= reader.ReadInt32();
                salt					= reader.ReadBytes(saltSize);
                encryptedVerifier		= reader.ReadBytes(0x10);
                verifierHashSize		= reader.ReadInt32();
                encryptedVerifierHash	= reader.ReadBytes(providerType == ProviderType.RC4 ? 0x14 : 0x20);
            }

            #endregion

            #region Encryption key generation

            Console.WriteLine("Encryption key generation");
            byte[] encryptionKey = GeneratePasswordHashUsingSHA1(password);
            if (encryptionKey == null) return null;

            #endregion

            #region Password verification

            Console.WriteLine("Password verification");
            if (PasswordVerifier(encryptionKey))
            {
                Console.WriteLine("Password verification succeeded");
            }
            else
            {
                Console.WriteLine("Password verification failed");
                throw new InvalidPasswordException("The password is not valid");
            }

            #endregion

            #region Decrypt

            // First 8 bytes hold the size of the stream
            long length = BitConverter.ToInt64(encryptedPackage, 0);

            // Decrypt the stream using the generated and validated key
            Console.WriteLine("Decrypt the stream using the generated and validated key");
            encryptedPackage = AESDecrypt(encryptedPackage, 8, encryptedPackage.Length-8, encryptionKey);

            // !! IMPORTANT !! Make sure the final array is the correct size
            // Failure to do this will cause an error when the decrypted stream
            // is opened by the System.IO.Packaging.Package.Open() method.

            byte[] result = encryptedPackage;

            if (encryptedPackage.Length > length)
            {
                result = new byte[length];
                Array.Copy(encryptedPackage, result, result.Length);
            }

            //using (System.IO.FileStream fs = new System.IO.FileStream(@"c:\x.zip", System.IO.FileMode.Create))
            //{
            //    fs.Write(result, 0, result.Length);
            //}

            return result;

            #endregion
        }
        public byte[] SignHash(byte[] rgbHash, AlgId hashType)
        {
            if (rgbHash == null)
            {
                throw new ArgumentNullException("rgbHash");
            }

            if (this.rsaCertificate == null)
            {
                throw new NullReferenceException("Certificate can't be null.");
            }

            IntPtr pCertContext = rsaCertificate.Handle;
            IntPtr hCryptProv   = IntPtr.Zero;
            uint   keySpec      = 0;
            bool   freeProv     = false;

            bool result = NativeMethods.CryptAcquireCertificatePrivateKey(
                pCertContext,
                (uint)CryptAcquireContextTypes.CRYPT_SILENT,
                IntPtr.Zero,
                out hCryptProv,
                out keySpec,
                out freeProv);

            if (!result)
            {
                throw new SEHException("Fail to invoke CryptAcquireCertificatePrivateKey failed.");
            }

            IntPtr hHashSend = IntPtr.Zero;
            IntPtr hHash     = IntPtr.Zero;

            result = NativeMethods.CryptCreateHash(hCryptProv, hashType, IntPtr.Zero, 0, ref hHash);
            if (!result)
            {
                NativeMethods.CryptReleaseContext(hCryptProv, 0);
                throw new SEHException("Fail to invoke CryptCreateHash failed.");
            }
            hHashSend = Marshal.AllocHGlobal(rgbHash.Length);
            Marshal.Copy(rgbHash, 0, hHashSend, rgbHash.Length);

            result = NativeMethods.CryptSetHashParam(hHash, HashParameters.HP_HASHVAL, hHashSend, 0);
            if (!result)
            {
                NativeMethods.CryptReleaseContext(hCryptProv, 0);
                Marshal.FreeHGlobal(hHashSend);
                NativeMethods.CryptDestroyHash(hHash);
                throw new SEHException("Fail to invoke CryptSetHashParam failed.");
            }

            IntPtr pbSignature   = IntPtr.Zero;
            uint   signatureSize = 0;

            result = NativeMethods.CryptSignHash(hHash, NativeMethods.AT_SIGNATURE, IntPtr.Zero, this.flags, IntPtr.Zero, ref signatureSize);
            if (!result)
            {
                NativeMethods.CryptReleaseContext(hCryptProv, 0);
                Marshal.FreeHGlobal(hHashSend);
                NativeMethods.CryptDestroyHash(hHash);
                throw new SEHException("Fail to invoke CryptSignHash failed.");
            }

            pbSignature = Marshal.AllocHGlobal((int)signatureSize);
            result      = NativeMethods.CryptSignHash(hHash, NativeMethods.AT_SIGNATURE, IntPtr.Zero, this.flags, pbSignature, ref signatureSize);
            if (!result)
            {
                Marshal.FreeHGlobal(pbSignature);
                NativeMethods.CryptReleaseContext(hCryptProv, 0);
                Marshal.FreeHGlobal(hHashSend);
                NativeMethods.CryptDestroyHash(hHash);
                throw new SEHException("Fail to invoke CryptSignHash failed.");
            }

            byte[] signature = new byte[signatureSize];
            Marshal.Copy(pbSignature, signature, 0, signature.Length);
            //The byte order of signature should be reversed, don't know the reason.
            Array.Reverse(signature);
            Marshal.FreeHGlobal(pbSignature);
            Marshal.FreeHGlobal(hHashSend);
            NativeMethods.CryptReleaseContext(hCryptProv, 0);
            NativeMethods.CryptDestroyHash(hHash);
            return(signature);
        }
Esempio n. 13
0
 internal static extern bool CryptGenKey(IntPtr hProv, AlgId Algid, int dwFlags, ref IntPtr phKey);
Esempio n. 14
0
 internal static extern bool CryptCreateHash(IntPtr hProv, AlgId algId, IntPtr hKey,
                                             uint dwFlags, ref IntPtr phHash);
Esempio n. 15
0
        internal byte[] DecryptInternal(string password, byte[] encryptionInfo, byte[] encryptedPackage)
        {
            #region Parse the encryption info data

            using (System.IO.MemoryStream ms = new System.IO.MemoryStream(encryptionInfo))
            {
                System.IO.BinaryReader reader = new System.IO.BinaryReader(ms);

                versionMajor = reader.ReadUInt16();
                versionMinor = reader.ReadUInt16();

                encryptionFlags = (EncryptionFlags)reader.ReadUInt32();
                if (encryptionFlags == EncryptionFlags.fExternal)
                {
                    throw new Exception("An external cryptographic provider is not supported");
                }

                // Encryption header
                uint headerLength = reader.ReadUInt32();
                int  skipFlags    = reader.ReadInt32(); headerLength -= 4;
                sizeExtra    = reader.ReadUInt32(); headerLength -= 4;
                algId        = (AlgId)reader.ReadUInt32(); headerLength -= 4;
                algHashId    = (AlgHashId)reader.ReadUInt32(); headerLength -= 4;
                keySize      = reader.ReadInt32(); headerLength -= 4;
                providerType = (ProviderType)reader.ReadUInt32(); headerLength -= 4;
                reader.ReadUInt32(); headerLength -= 4;                                                                   // Reserved 1
                reader.ReadUInt32(); headerLength -= 4;                                                                   // Reserved 2
                CSPName = System.Text.UnicodeEncoding.Unicode.GetString(reader.ReadBytes((int)headerLength));

                // Encryption verifier
                saltSize              = reader.ReadInt32();
                salt                  = reader.ReadBytes(saltSize);
                encryptedVerifier     = reader.ReadBytes(0x10);
                verifierHashSize      = reader.ReadInt32();
                encryptedVerifierHash = reader.ReadBytes(providerType == ProviderType.RC4 ? 0x14 : 0x20);
            }

            #endregion

            #region Encryption key generation

            Console.WriteLine("Encryption key generation");
            byte[] encryptionKey = GeneratePasswordHashUsingSHA1(password);
            if (encryptionKey == null)
            {
                return(null);
            }

            #endregion

            #region Password verification

            Console.WriteLine("Password verification");
            if (PasswordVerifier(encryptionKey))
            {
                Console.WriteLine("Password verification succeeded");
            }
            else
            {
                Console.WriteLine("Password verification failed");
                throw new InvalidPasswordException("The password is not valid");
            }

            #endregion

            #region Decrypt

            // First 8 bytes hold the size of the stream
            long length = BitConverter.ToInt64(encryptedPackage, 0);

            // Decrypt the stream using the generated and validated key
            Console.WriteLine("Decrypt the stream using the generated and validated key");
            encryptedPackage = AESDecrypt(encryptedPackage, 8, encryptedPackage.Length - 8, encryptionKey);

            // !! IMPORTANT !! Make sure the final array is the correct size
            // Failure to do this will cause an error when the decrypted stream
            // is opened by the System.IO.Packaging.Package.Open() method.

            byte[] result = encryptedPackage;

            if (encryptedPackage.Length > length)
            {
                result = new byte[length];
                Array.Copy(encryptedPackage, result, result.Length);
            }

            //using (System.IO.FileStream fs = new System.IO.FileStream(@"c:\x.zip", System.IO.FileMode.Create))
            //{
            //    fs.Write(result, 0, result.Length);
            //}

            return(result);

            #endregion
        }
        public byte[] SignHash(byte[] rgbHash, AlgId hashType)
        {
            if (rgbHash == null)
            {
                throw new ArgumentNullException("rgbHash");
            }

            if (this.rsaCertificate == null)
            {
                throw new NullReferenceException("Certificate can't be null.");
            }

            IntPtr pCertContext = rsaCertificate.Handle;
            IntPtr hCryptProv = IntPtr.Zero;
            uint keySpec = 0;
            bool freeProv = false;

            bool result = NativeMethods.CryptAcquireCertificatePrivateKey(
                pCertContext,
                (uint)CryptAcquireContextTypes.CRYPT_SILENT,
                IntPtr.Zero,
                out hCryptProv,
                out keySpec,
                out freeProv);
            if (!result)
            {
                throw new SEHException("Fail to invoke CryptAcquireCertificatePrivateKey failed.");
            }

            IntPtr hHashSend = IntPtr.Zero;
            IntPtr hHash = IntPtr.Zero;

            result = NativeMethods.CryptCreateHash(hCryptProv, hashType, IntPtr.Zero, 0, ref hHash);
            if (!result)
            {
                NativeMethods.CryptReleaseContext(hCryptProv, 0);
                throw new SEHException("Fail to invoke CryptCreateHash failed.");
            }
            hHashSend = Marshal.AllocHGlobal(rgbHash.Length);
            Marshal.Copy(rgbHash, 0, hHashSend, rgbHash.Length);

            result = NativeMethods.CryptSetHashParam(hHash, HashParameters.HP_HASHVAL, hHashSend, 0);
            if (!result)
            {
                NativeMethods.CryptReleaseContext(hCryptProv, 0);
                Marshal.FreeHGlobal(hHashSend);
                NativeMethods.CryptDestroyHash(hHash);
                throw new SEHException("Fail to invoke CryptSetHashParam failed.");
            }

            IntPtr pbSignature = IntPtr.Zero;
            uint signatureSize = 0;

            result = NativeMethods.CryptSignHash(hHash, NativeMethods.AT_SIGNATURE, IntPtr.Zero, this.flags, IntPtr.Zero, ref signatureSize);
            if (!result)
            {
                NativeMethods.CryptReleaseContext(hCryptProv, 0);
                Marshal.FreeHGlobal(hHashSend);
                NativeMethods.CryptDestroyHash(hHash);
                throw new SEHException("Fail to invoke CryptSignHash failed.");
            }

            pbSignature = Marshal.AllocHGlobal((int)signatureSize);
            result = NativeMethods.CryptSignHash(hHash, NativeMethods.AT_SIGNATURE, IntPtr.Zero, this.flags, pbSignature, ref signatureSize);
            if (!result)
            {
                Marshal.FreeHGlobal(pbSignature);
                NativeMethods.CryptReleaseContext(hCryptProv, 0);
                Marshal.FreeHGlobal(hHashSend);
                NativeMethods.CryptDestroyHash(hHash);
                throw new SEHException("Fail to invoke CryptSignHash failed.");
            }

            byte[] signature = new byte[signatureSize];
            Marshal.Copy(pbSignature, signature, 0, signature.Length);
            //The byte order of signature should be reversed, don't know the reason.
            Array.Reverse(signature);
            Marshal.FreeHGlobal(pbSignature);
            Marshal.FreeHGlobal(hHashSend);
            NativeMethods.CryptReleaseContext(hCryptProv, 0);
            NativeMethods.CryptDestroyHash(hHash);
            return signature;
        }