2

次の方法でファイルをデコードしています。

string outFileName = zfoFileName.Replace(".zfo", "_tmp.zfo");
FileStream inFile = null;
FileStream outFile = null;
inFile = File.Open(zfoFileName, FileMode.Open);
outFile = File.Create(outFileName);
LargeCMS.CMS cms = new LargeCMS.CMS();
cms.Decode(inFile, outFile);

これは私のWin7開発マシンでは正常に機能していますが、Windows 2003サーバーの実稼働マシンでは、次の例外を除いて失敗します。

例外:System.Exception:CryptMsgUpdateエラー#-2146893816 ---> System.ComponentModel.Win32Exception:無効なアルゴリズムが指定されました---内部例外スタックトレースの終わり--- LargeCMS.CMS.Decode(FileStream inFile、FileStream outFile)で

以下は、デコードを行うために呼び出すクラスです。必要に応じて、デコード用のサンプルファイルをアップロードできます。これは、Win2k3サーバーではなく、Win7で機能するという奇妙なことです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace LargeCMS
{
    class CMS
    {
        // File stream to use in callback function
        private FileStream m_callbackFile;

        // Streaming callback function for encoding
        private Boolean StreamOutputCallback(IntPtr pvArg, IntPtr pbData, int cbData, Boolean fFinal)
        {
            // Write all bytes to encoded file
            Byte[] bytes = new Byte[cbData];
            Marshal.Copy(pbData, bytes, 0, cbData);
            m_callbackFile.Write(bytes, 0, cbData);

            if (fFinal)
            {
                // This is the last piece. Close the file
                m_callbackFile.Flush();
                m_callbackFile.Close();
                m_callbackFile = null;
            }

            return true;
        }



        // Decode CMS with streaming to support large data
        public void Decode(FileStream inFile, FileStream outFile)
        {
            // Variables
            Win32.CMSG_STREAM_INFO StreamInfo;
            Win32.CERT_CONTEXT SignerCertContext;

            BinaryReader stream = null;
            GCHandle gchandle = new GCHandle();

            IntPtr hMsg = IntPtr.Zero;
            IntPtr pSignerCertInfo = IntPtr.Zero;
            IntPtr pSignerCertContext = IntPtr.Zero;
            IntPtr pbPtr = IntPtr.Zero;
            IntPtr hStore = IntPtr.Zero;
            Byte[] pbData;
            Boolean bResult = false;
            int dwFileSize;
            int dwRemaining;
            int dwSize;
            int cbSignerCertInfo;

            try
            {
                // Get data to decode
                dwFileSize = (int)inFile.Length;
                stream = new BinaryReader(inFile);
                pbData = stream.ReadBytes(dwFileSize);

                // Prepare stream for decoded info
                m_callbackFile = outFile;

                // Populate Stream Info struct
                StreamInfo = new Win32.CMSG_STREAM_INFO();
                StreamInfo.cbContent = dwFileSize;
                StreamInfo.pfnStreamOutput = new Win32.StreamOutputCallbackDelegate(StreamOutputCallback);

                // Open message to decode
                hMsg = Win32.CryptMsgOpenToDecode(
                    Win32.X509_ASN_ENCODING | Win32.PKCS_7_ASN_ENCODING,
                    0,
                    0,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref StreamInfo
                );
                if (hMsg.Equals(IntPtr.Zero))
                {
                    throw new Exception("CryptMsgOpenToDecode error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
                }

                // Process the whole message
                gchandle = GCHandle.Alloc(pbData, GCHandleType.Pinned);
                pbPtr = gchandle.AddrOfPinnedObject();
                dwRemaining = dwFileSize;
                dwSize = (dwFileSize < 1024 * 1000 * 100) ? dwFileSize : 1024 * 1000 * 100;
                while (dwRemaining > 0)
                {
                    // Update message piece by piece     
                    bResult = Win32.CryptMsgUpdate(
                        hMsg,
                        pbPtr,
                        dwSize,
                        (dwRemaining <= dwSize) ? true : false
                    );
                    if (!bResult)
                    {
                        throw new Exception("CryptMsgUpdate error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
                    }

                    // Move to the next piece
                    pbPtr = new IntPtr(pbPtr.ToInt64() + dwSize);
                    dwRemaining -= dwSize;
                    if (dwRemaining < dwSize)
                    {
                        dwSize = dwRemaining;
                    }
                }

                // Get signer certificate info
                cbSignerCertInfo = 0;
                bResult = Win32.CryptMsgGetParam(
                    hMsg,
                    Win32.CMSG_SIGNER_CERT_INFO_PARAM,
                    0,
                    IntPtr.Zero,
                    ref cbSignerCertInfo
                );
                if (!bResult)
                {
                    throw new Exception("CryptMsgGetParam error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
                }

                pSignerCertInfo = Marshal.AllocHGlobal(cbSignerCertInfo);

                bResult = Win32.CryptMsgGetParam(
                    hMsg,
                    Win32.CMSG_SIGNER_CERT_INFO_PARAM,
                    0,
                    pSignerCertInfo,
                    ref cbSignerCertInfo
                );
                if (!bResult)
                {
                    throw new Exception("CryptMsgGetParam error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
                }

                // Open a cert store in memory with the certs from the message
                hStore = Win32.CertOpenStore(
                    Win32.CERT_STORE_PROV_MSG,
                    Win32.X509_ASN_ENCODING | Win32.PKCS_7_ASN_ENCODING,
                    IntPtr.Zero,
                    0,
                    hMsg
                );
                if (hStore.Equals(IntPtr.Zero))
                {
                    throw new Exception("CertOpenStore error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
                }

                // Find the signer's cert in the store
                pSignerCertContext = Win32.CertGetSubjectCertificateFromStore(
                    hStore,
                    Win32.X509_ASN_ENCODING | Win32.PKCS_7_ASN_ENCODING,
                    pSignerCertInfo
                );
                if (pSignerCertContext.Equals(IntPtr.Zero))
                {
                    throw new Exception("CertGetSubjectCertificateFromStore error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
                }

                // Set message for verifying
                SignerCertContext = (Win32.CERT_CONTEXT)Marshal.PtrToStructure(pSignerCertContext, typeof(Win32.CERT_CONTEXT));
                bResult = Win32.CryptMsgControl(
                    hMsg,
                    0,
                    Win32.CMSG_CTRL_VERIFY_SIGNATURE,
                    SignerCertContext.pCertInfo
                );
                if (!bResult)
                {
                    throw new Exception("CryptMsgControl error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
                }
            }
            finally
            {
                // Clean up
                if (gchandle.IsAllocated)
                {
                    gchandle.Free();
                }
                if (!pSignerCertContext.Equals(IntPtr.Zero))
                {
                    Win32.CertFreeCertificateContext(pSignerCertContext);
                }
                if (!pSignerCertInfo.Equals(IntPtr.Zero))
                {
                    Marshal.FreeHGlobal(pSignerCertInfo);
                }
                if (!hStore.Equals(IntPtr.Zero))
                {
                    Win32.CertCloseStore(hStore, Win32.CERT_CLOSE_STORE_FORCE_FLAG);
                }
                if (stream != null)
                {
                    stream.Close();
                }
                if (m_callbackFile != null)
                {
                    m_callbackFile.Close();
                }
                if (!hMsg.Equals(IntPtr.Zero))
                {
                    Win32.CryptMsgClose(hMsg);
                }
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.ComponentModel;
using System.Security.Cryptography;

namespace LargeCMS
{
    class Win32
    {
        #region "CONSTS"

        public const int X509_ASN_ENCODING = 0x00000001;
        public const int PKCS_7_ASN_ENCODING = 0x00010000;
        public const int CMSG_SIGNED = 2;
        public const int CMSG_DETACHED_FLAG = 0x00000004;
        public const int AT_KEYEXCHANGE = 1;
        public const int AT_SIGNATURE = 2;
        public const String szOID_OIWSEC_sha1 = "1.3.14.3.2.26";
        public const int CMSG_CTRL_VERIFY_SIGNATURE = 1;
        public const int CMSG_CERT_PARAM = 12;
        public const int CMSG_SIGNER_CERT_INFO_PARAM = 7;
        public const int CERT_STORE_PROV_MSG = 1;
        public const int CERT_CLOSE_STORE_FORCE_FLAG = 1;

        #endregion

        #region "STRUCTS"

        [StructLayout(LayoutKind.Sequential)]
        public struct CRYPT_ALGORITHM_IDENTIFIER
        {
            public String pszObjId;
            BLOB Parameters;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CERT_ID
        {
            public int dwIdChoice;
            public BLOB IssuerSerialNumberOrKeyIdOrHashId;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CMSG_SIGNER_ENCODE_INFO
        {
            public int cbSize;
            public IntPtr pCertInfo;
            public IntPtr hCryptProvOrhNCryptKey;
            public int dwKeySpec;
            public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
            public IntPtr pvHashAuxInfo;
            public int cAuthAttr;
            public IntPtr rgAuthAttr;
            public int cUnauthAttr;
            public IntPtr rgUnauthAttr;
            public CERT_ID SignerId;
            public CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
            public IntPtr pvHashEncryptionAuxInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CERT_CONTEXT
        {
            public int dwCertEncodingType;
            public IntPtr pbCertEncoded;
            public int cbCertEncoded;
            public IntPtr pCertInfo;
            public IntPtr hCertStore;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct BLOB
        {
            public int cbData;
            public IntPtr pbData;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CMSG_SIGNED_ENCODE_INFO
        {
            public int cbSize;
            public int cSigners;
            public IntPtr rgSigners;
            public int cCertEncoded;
            public IntPtr rgCertEncoded;
            public int cCrlEncoded;
            public IntPtr rgCrlEncoded;
            public int cAttrCertEncoded;
            public IntPtr rgAttrCertEncoded;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CMSG_STREAM_INFO
        {
            public int cbContent;
            public StreamOutputCallbackDelegate pfnStreamOutput;
            public IntPtr pvArg;
        }

        #endregion

        #region "DELEGATES"

        public delegate Boolean StreamOutputCallbackDelegate(IntPtr pvArg, IntPtr pbData, int cbData, Boolean fFinal);

        #endregion

        #region "API"

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern Boolean CryptAcquireContext(
          ref IntPtr hProv,
          String pszContainer,
          String pszProvider,
          int dwProvType,
          int dwFlags
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern IntPtr CryptMsgOpenToEncode(
            int dwMsgEncodingType,
            int dwFlags,
            int dwMsgType,
            ref CMSG_SIGNED_ENCODE_INFO pvMsgEncodeInfo,
            String pszInnerContentObjID,
            ref CMSG_STREAM_INFO pStreamInfo
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern IntPtr CryptMsgOpenToDecode(
            int dwMsgEncodingType,
            int dwFlags,
            int dwMsgType,
            IntPtr hCryptProv,
            IntPtr pRecipientInfo,
            ref CMSG_STREAM_INFO pStreamInfo
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern Boolean CryptMsgClose(
            IntPtr hCryptMsg
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern Boolean CryptMsgUpdate(
            IntPtr hCryptMsg,
            Byte[] pbData,
            int cbData,
            Boolean fFinal
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern Boolean CryptMsgUpdate(
            IntPtr hCryptMsg,
            IntPtr pbData,
            int cbData,
            Boolean fFinal
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern Boolean CryptMsgGetParam(
            IntPtr hCryptMsg,
            int dwParamType,
            int dwIndex,
            IntPtr pvData,
            ref int pcbData
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern Boolean CryptMsgControl(
            IntPtr hCryptMsg,
            int dwFlags,
            int dwCtrlType,
            IntPtr pvCtrlPara
        );

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern Boolean CryptReleaseContext(
            IntPtr hProv,
            int dwFlags
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern IntPtr CertCreateCertificateContext(
            int dwCertEncodingType,
            IntPtr pbCertEncoded,
            int cbCertEncoded
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern Boolean CertFreeCertificateContext(
            IntPtr pCertContext
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern IntPtr CertOpenStore(
            int lpszStoreProvider,
            int dwMsgAndCertEncodingType,
            IntPtr hCryptProv,
            int dwFlags,
            IntPtr pvPara
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern IntPtr CertGetSubjectCertificateFromStore(
            IntPtr hCertStore,
            int dwCertEncodingType,
            IntPtr pCertId
        );

        [DllImport("Crypt32.dll", SetLastError = true)]
        public static extern IntPtr CertCloseStore(
            IntPtr hCertStore,
            int dwFlags
        );

        #endregion
    }
}
4

3 に答える 3

3

あなたの環境について詳しく教えてください。まず、どのサービス パックに Windows 2003 Server が含まれているかを調べます。たとえば、SP3 http://support.microsoft.com/kb/324953/enで修正されたバグ「Web 登録ページでのデフォルトの Diffie-Hellman SChannel 証明書の選択により、エラー: 0x80090008 - NTE_BAD_ALGID」が発生します。問題がない場合は、証明書とテスト メッセージを含むバイナリ ファイルを Web 上のどこかに配置し、ここに URL を投稿する必要があります。その後、問題を再現してテストすることができます。

問題を解決するには (最後の Service Pack が Windows Server 2003 にインストールされている場合)、メッセージが署名されている証明書のいくつかのプロパティを変更する必要があると思います。

ちなみに、証明書でSHA-2アルゴリズム(SHA-256、SHA-384、およびSHA-512)を使用しているとは思いません。これを使用し、最後のサービス パックがインストールされている場合は、"Microsoft Enhanced RSA and AES Cryptographic Provider" (または Windows で呼び出される "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)") を明示的に使用する必要があります。 XP SP3) または PROV_RSA_AES または MS_ENH_RSA_AES_PROV をデフォルトの PROV_RSA_FULL プロバイダーの代わりに使用します。(例: http://blogs.msdn.com/alejacma/archive/2009/01/23/sha-2-support-on-windows-xp.aspxを参照)

更新 1: テスト ファイルを受け取った後、問題はより明確になります。まずは朗報です。あなたのプログラムは正しく動作します! SP2 を適用したテスト用の Windows 2003 サーバーでは問題なく動作します。したがって、ソフトウェア開発ではなく、管理上の問題があります。別の Windows 2003 Server でプログラムをテストすることをお勧めします。このサーバーでは、SP2 を再インストールしてから、Microsoft Updates に移動して、すべての更新プログラムをインストールできます。

ちなみに、SHA256 やその他の SHA-2 アルゴリズムでは問題ありません。あなたの例では、標準の 1.2.840.113549.1.1.5 sha1RSA アルゴリズムを使用しています。

今あなたのプログラムについて。私はあなたのコードの詳細を読み、あなたが何をしているかを正確に理解しています。内部にテキスト タイル (XML ファイル) を含む PKCS#7 署名付きメッセージを受け取ります。あなたの例がhttp://blogs.msdn.com/alejacma/archive/2010/04/09/how-to-call-cryptmsg-api-in-streaming-mode-c.aspxの問題を説明していることを理解する方法100MB もの大きなファイルの復号化 ( http://blogs.msdn.com/alejacma/archive/2010/03/17/asn1-value-too-large-error-when-calling-signedcms-computesignature.aspxも参照)。このようなケースがない場合は、System.Security.Cryptography.Pkcs 名前空間の .NET 暗号化関数を使用することをお勧めします。大きなデータがある場合は、現在のコードで問題ありません。疑わしい唯一の場所は、入力ファイルの読み取りです。stream.ReadBytes()を読みません電話。巨大なファイルをメモリにロードする代わりに、より適切なメモリマップファイルを使用します。ネイティブ コードでこれを行うには、次のようなコードを使用できます。

DWORD MapFileInMemory (IN LPCWSTR pszFileName,
                       OUT PBYTE *ppbyFile, OUT PDWORD pdwFileSizeLow, OUT PDWORD pdwFileSizeHigh)
{
    HANDLE hFile = INVALID_HANDLE_VALUE, hFileMapping = NULL;
    DWORD  dwStatus = (DWORD)E_UNEXPECTED;

    __try {
        // Open the input file to be encrypted or decrypted
        hFile = CreateFileW (pszFileName, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING,
                             FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
        if (hFile == INVALID_HANDLE_VALUE) {
            dwStatus = GetLastError();
            __leave;
        }

        *pdwFileSizeLow = GetFileSize (hFile, pdwFileSizeHigh);
        if (*pdwFileSizeLow == INVALID_FILE_SIZE){
            dwStatus = GetLastError();
            __leave;
        }

        hFileMapping = CreateFileMapping (hFile, NULL, PAGE_READONLY, 0, 0, NULL);
        if (!hFileMapping){
            dwStatus = GetLastError();
            __leave;
        }

        *ppbyFile = (PBYTE) MapViewOfFile (hFileMapping, FILE_MAP_READ, 0, 0, 0);
        if (*ppbyFile == NULL) {
            dwStatus = GetLastError();
            __leave;
        }

        dwStatus = NO_ERROR;
    }
    __finally {
        if (hFileMapping)
            CloseHandle (hFileMapping);

        if (hFile != INVALID_HANDLE_VALUE)
            CloseHandle (hFile);
    }

    return dwStatus;
}

BOOL UnmapFileFromMemory (LPCVOID lpBaseAddress)
{
    return UnmapViewOfFile (lpBaseAddress);
}

対応する .NET コードの記述は問題になりません。Memory Mapped Files を使用すると、ファイルへの仮想アドレス マッピングのみが作成され、データの対応する部分にアクセスした場合、データは読み取り専用になります。

もう1つの発言。メッセージがいっぱいでないことを確認するコードの部分。あなたがしなければならないことは、メッセージが署名された証明書の検証です。ネイティブのCryptoAPIを使用する場合は、CertGetCertificateChain(). そうして初めて、証明書とそのすべての親が有効であることを確認できます。CertVerifyCertificateChainPolicy()また、証明書チェーンがメッセージの署名に証明書を使用できることを確認する必要があります。

ところで、現在のコードはエラー メッセージなしで動作しますが、メッセージが署名されている証明書の発行者は "CN=PostSignum Qualified CA, O="Ceská pošta, sp [IC 47114983]", C=CZ" であり、証明書が存在しないというメッセージ。たとえばcertutil.exe -dump 31602.zfo、詳細を表示するために使用できます。

Missing Issuer: CN=PostSignum Qualified CA, O="Ceská pošta, s.p. [IC 47114983]", C=CZ
  Issuer: CN=PostSignum Qualified CA, O="Ceská pošta, s.p. [IC 47114983]", C=CZ
  NotBefore: 03.12.2009 11:23
  NotAfter: 03.12.2010 10:33
  Subject: SERIALNUMBER=S7464, CN=Informacní systém datových schránek - zkušební prostredí, O="Ceská pošta, s.p. [IC 47114983]", C=CZ
  Serial: 04d3c5
  SubjectAltName: RFC822 Name=postsignum@cpost.cz, Other Name:Description=13 00
  59 c7 20 ba 70 b1 e6 93 ea c4 83 4b 3c 1e 35 dc b9 15 f5 ff
A certificate chain could not be built to a trusted root authority. 0x800b010a (-2146762486)

おそらく、署名されたメッセージを有効であると解釈したくないでしょう。証明書の検証は必須です。さらに、多くのシナリオでは、署名付きメッセージを入力として許可する発行元の範囲を定義することをお勧めします。これについて考えます。

更新 2:新しい 331879.zfo ファイルでは、実際に署名に sha256RSA (1.2.840.113549.1.1.11) を使用しています。http://thehotfixshare.net/board/index.php?showtopic=12629&hl=968730で好きなhttp://support.microsoft.com/kb/968730/enをインストールしてみてください。デジタル署名されたファイルです。だから私はそれが安全でなければなりません。Microsoft からこの修正プログラムを確実に受け取ることができるようにします。この修正で問題が解決することを願っています。

更新 3 : コード例についてもう少し考えました。私には、最良の実装を受け取るには、メッセージ デコードのコード全体をアンマネージ (ネイティブ) コードとして実装する必要があるように思えます。そのため、大きなデータのデコード中に、ネイティブ コードとマネージド コードの間のマーシャリングに余分な時間を費やすことはありません。このネイティブ コードを DLL 内に配置し、メイン マネージ コード内で使用できる関数をエクスポートする必要があります。

メモリ マップド フィールドの使用に関するもう 1 つの注意事項。メモリ マップド フィールドの使用は、ほとんどの場合、読み書きの両方で Windows の任意のファイルにアクセスする方法として最適化されています。知っておかなければならないことの 1 つは、メモリ使用量です。タスク マネージャで使用メモリを確認すると、メモリ マップ ファイル手法を使用するプログラムが非常に大きなメモリを使用する可能性があることがわかります。まったく問題ありません。このメモリは物理メモリではなく、ページング ファイルからのページ メモリでもありません。仮想アドレスは、メモリにマップしたファイルに直接マップされます。したがって、データのページングは​​、ファイル データ自体に関して行われます。オペレーティング システムのページング ファイルの追加部分は必要ありません。ファイルからのこの I/O は、対応する組み込みプロセッサ機能に関して最適化され、実装されています。

最終的な解決策: この問題について考えるのをやめられなかったので、解決しなければなりませんでした。これは、私が以前に書いたことに基づいた完全なソリューションです。

public const int PROV_RSA_AES = 24;
public const String MS_ENH_RSA_AES_PROV =
    "Microsoft Enhanced RSA and AES Cryptographic Provider";
public const String MS_ENH_RSA_AES_PROV_XP =
    "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)";
public const int CRYPT_VERIFYCONTEXT = unchecked((int)0xF0000000U);
[StructLayout (LayoutKind.Sequential)]
    public struct OSVERSIONINFOEX {
        public int dwOSVersionInfoSize;
        public int dwMajorVersion;
        public int dwMinorVersion;
        public int dwBuildNumber;
        public int dwPlatformId;
        [MarshalAs (UnmanagedType.ByValTStr, SizeConst = 128)]
        public string szCSDVersion;
        public short wServicePackMajor;
        public short wServicePackMinor;
        public short wSuiteMask;
        public byte wProductType;
        public byte wReserved;
    }
[DllImport ("kernel32.dll")]
public static extern bool GetVersionEx (ref OSVERSIONINFOEX osVersionInfo);
  • public void Decode(FileStream inFile, FileStream outFile)Windows Server 2003 または XP で RSA および AES 暗号化プロバイダーを明示的に使用するように変更します。
// insert next line before of try block like after this line
IntPtr hStore = IntPtr.Zero;
IntPtr hProv = IntPtr.Zero;

//...
// insert Windows versions test before CryptMsgOpenToDecode like after this line
StreamInfo.pfnStreamOutput = new Win32.StreamOutputCallbackDelegate(StreamOutputCallback);

Win32.OSVERSIONINFOEX osVersionInfo = new Win32.OSVERSIONINFOEX ();
osVersionInfo.dwOSVersionInfoSize = Marshal.SizeOf (typeof (Win32.OSVERSIONINFOEX));
if (Win32.GetVersionEx (ref osVersionInfo)) {
    Console.WriteLine ("dwMajorVersion={0}, dwMinorVersion={1}, wProductType={2}",
        osVersionInfo.dwMajorVersion, osVersionInfo.dwMinorVersion, osVersionInfo.wProductType);
    if (osVersionInfo.dwMajorVersion == 5 &&
        (osVersionInfo.dwMinorVersion == 2 || osVersionInfo.dwMinorVersion == 1)) {
        // Windows 2003 or XP
        string provider = Win32.MS_ENH_RSA_AES_PROV;
        if (osVersionInfo.dwMajorVersion == 5 && osVersionInfo.dwMinorVersion == 1)
            provider = Win32.MS_ENH_RSA_AES_PROV_XP;
        Win32.CryptAcquireContext (ref hProv, null, provider,
            Win32.PROV_RSA_AES, Win32.CRYPT_VERIFYCONTEXT);
    }
}

// Open message to decode
hMsg = Win32.CryptMsgOpenToDecode(
    Win32.X509_ASN_ENCODING | Win32.PKCS_7_ASN_ENCODING,
    0,
    0,
    hProv,
    IntPtr.Zero,
    ref StreamInfo
);
  • CryptReleaseContext 関数に関してクローズ ハンドルをデコードした後
    //...
    // insert CryptReleaseContext somewhere inside of finally block like after this line
    if (!hMsg.Equals(IntPtr.Zero))
    {
    Win32.CryptMsgClose(hMsg);
    }
    if (hProv != IntPtr.Zero)
    Win32.CryptReleaseContext (hProv, 0);

現在、プログラムは SHA-2 アルゴリズムで署名されたデータ (1.2.840.113549.1.1.11 sha256RSA で署名された 331879.zfo など) で動作します。

メモリ マップド ファイルを忘れないことをお勧めします。.NET 4.0 を使用している場合は、新しい .NET フレームワーク クラスを使用できます ( http://msdn.microsoft.com/en-us/library/dd997372%28v=VS.100%29.aspxを参照)。

于 2010-04-26T15:21:14.480 に答える
3

使用している CSP が Win2003 にインストールされていない可能性がありますか? SP3 より前の XP には SHA-2 か何かの問題があり、XP と Win2003 はほぼ同じ基本的な OS であると読んだことを覚えています。


次のレジストリ キーHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaultsに何がインストールされているかを確認できると思います

たぶん、あなたのマシンを比較することができます。

于 2010-04-21T20:11:47.297 に答える
1

MD5 およびその他のレガシー/壊れた暗号化アルゴリズムは、グループ ポリシーで無効にすることができます (米国政府での使用に必要)。

于 2010-04-26T15:57:00.660 に答える