使用X509Certificate2验证证书密码

时间:2015-02-11 16:11:51

标签: .net exception-handling certificate x509certificate2

我想验证证书密码。此时我有基于处理CryptographicException和检查异常消息的代码。但这种方法取决于英国文化信息。

    public bool VerifyPassword(byte[] fileContent, string password)
    {
        try
        {
            var certificate = new X509Certificate2(fileContent, password);
        }
        catch (CryptographicException ex)
        {
            if (ex.Message.StartsWith("The specified network password is not correct."))
            {
                return false;
            }

            throw;
        }

        return true;
    }

我一直在寻找其他解决方案如何验证证书密码,但没有成功。

如何验证证书密码的正确方法是什么?

我很感激任何想法...

3 个答案:

答案 0 :(得分:3)

几个月后,我找到了更好的解决方案(也许是最好的)。它基于CryptograhpicExcaption的HResult值。

static bool VerifyPassword(byte[] fileContent, string password)
{
    try
    {
        // ReSharper disable once UnusedVariable
        var certificate = new X509Certificate2(fileContent, password);
    }
    catch (CryptographicException ex)
    {
        if ((ex.HResult & 0xFFFF) == 0x56) 
        { 
            return false;
        };

        throw;
    }

    return true;
}

所有HResults(系统错误代码)文档均可在https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382.aspx

上找到

答案 1 :(得分:1)

由于我工作的公司不允许使用原生Windows API,我有一个解决方案 - >使用InvariantCulture在新线程上运行验证。它将适用于所有.Net语言的突变。

以下是代码示例:

    public bool VerifyPassword(byte[] fileContent, string password)
    {
        CheckParameters(fileContent, password);
        var isPasswordVerified = false;

        var verificationThread = new Thread(() => isPasswordVerified = VerifyPasswordWithUsCulture(fileContent, password))
        {
            CurrentUICulture =  CultureInfo.InvariantCulture
        };

        verificationThread.Start();
        verificationThread.Join();

        return isPasswordVerified;
    }

    static bool VerifyPasswordWithUsCulture(byte[] fileContent, string password)
    {
        try
        {
            // ReSharper disable once UnusedVariable
            var certificate = new X509Certificate2(fileContent, password);
        }
        catch (CryptographicException ex)
        {
            if (ex.Message.StartsWith("The specified network password is not correct."))
            {
                return false;
            }

            throw;
        }

        return true;
    }

答案 2 :(得分:0)

我会使用PFXVerifyPasswordPFXIsPFXBlob原生函数。虽然,它需要一个p / invoke,但这是一个真正的交易。

C#签名和示例代码:

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace ClassLibrary1 {
    class CryptoAPI {
        [DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern Boolean PFXIsPFXBlob(
            [In]CRYPTOAPI_BLOB pPFX
        );
        [DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern Boolean PFXVerifyPassword(
            [In] CRYPTOAPI_BLOB pPFX,
            [MarshalAs(UnmanagedType.LPWStr)]
            [In] String szPassword,
            [In] UInt32 dwFlags
        );
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct CRYPTOAPI_BLOB {
            public UInt32 cbData;
            public IntPtr pbData;
        }
    }

    public class Program {
        public static Boolean TestPfxPwd(Byte[] rawData, String password) {
            // check for input data
            if (rawData == null) { throw new ArgumentNullException("rawData"); }
            // allocate a buffer in an unmanaged memory to store PFX content
            IntPtr pbData = Marshal.AllocHGlobal(rawData.Length);
            // copy PFX content to allocated buffer
            Marshal.Copy(rawData, 0, pbData, rawData.Length);
            // instantiate CRYPTOAPI_BLOB structure as it will be used
            // to call both functions
            CryptoAPI.CRYPTOAPI_BLOB blob = new CryptoAPI.CRYPTOAPI_BLOB {
                cbData = (UInt32)rawData.Length,
                pbData = pbData
            };
            // determine if input byte array represents a PFX blob:
            if (!CryptoAPI.PFXIsPFXBlob(blob)) {
                // release unmanaged resources before leaving method
                Marshal.FreeHGlobal(pbData);
                throw new InvalidDataException("Input data is not valid PFX message.");
            }
            // call the PFXVerifyPassword function and store results in a temporary variable
            Boolean retValue = CryptoAPI.PFXVerifyPassword(blob, password, 0);
            // release unmanaged resources before leaving method
            Marshal.FreeHGlobal(pbData);
            // return pfx match status
            return retValue;
        }
    }
}