C#-NET 4.0-密码学:使用SHA256和PKCS#10

时间:2018-09-06 14:12:32

标签: c# cryptography .net-4.0 sha256 pkcs#10

我正面临一种新情况,涉及一个用.NET Framework 4.0 / C#编写的程序,该程序必须对要在特定种类的WAN中发送/接收的消息进行编码/解码和签名。 这是当前方案,可以正常工作。 我们有一个.p12文件(包含发送者证书)和一个.cer文件(包含接收者证书),它们都安装在pc中。 该方案正在使用1024位SHA1和PKCS#7,因此下面的代码可以工作

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography;
using System.Windows;
using System.Windows.Controls;
using System.Collections;
private static string senderCert = "sendername"; //the name registered in .p12 file
private static string receiverCert = "receivername"; //the name registered in .cer file
    /// <summary>
    ///verify that the receiving message is signed
    ///and returns the data without sign
    /// </summary>
    /// <param name="signedData">dataflow with sign</param>
    /// <returns></returns>
    public static byte[] Verify(this byte[] signedData)
    {
        X509Certificate2 certPub = GetReceiverCert(); 
        if (certPub == null) return null;

        ContentInfo decodeContentInfo = new ContentInfo(signedData);
        SignedCms decodeCMS = new SignedCms(decodeContentInfo, false);

        try
        {
            //decode the message, if it isn't signed, raise an exception
            decodeCMS.Decode(signedData);
            SignerInfo signerInfo = decodeCMS.SignerInfos[0];

            X509Certificate2Collection certCollection = new 
                        X509Certificate2Collection(certPub);                
            return decodeCMS.ContentInfo.Content;
        }
        catch (CryptographicException err)
        {
            Logger.Log(err);
            return null;
        }
    }

    /// <summary>
    /// Returns the certificate used to sign the sending messages
    /// </summary>
    /// <returns></returns>
    private static X509Certificate2 GetSenderCert()
    {
        //Open the personal certificates folder
        X509Store storeMy = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        storeMy.Open(OpenFlags.ReadOnly);

        //find the proper certificate
        X509Certificate2Collection certColl = storeMy.Certificates.Find 
        (X509FindType.FindBySubjectName, senderCert, false);

        //Check if certificate exists in the collection, otherwise returns null             
            if (certColl.Count == 0)
            return null;
        storeMy.Close();
        return certColl[0];
    }

    /// <summary>
    /// Returns the certificate used to control the sign of the receiving messages
    /// </summary>
    /// <returns></returns>
    private static X509Certificate2 GetReceiverCert()
    {
        //Open personal certificates' folder
        X509Store storeMy = new X509Store(StoreName.My,
            StoreLocation.CurrentUser);
        storeMy.Open(OpenFlags.ReadOnly);

        //find the certificate use for this kind of messages
        X509Certificate2Collection certColl = storeMy.Certificates.Find 
                 (X509FindType.FindBySubjectName, receiverCert, false);

        //Check if certificate exists in the collection, otherwise returns null
        if (certColl.Count == 0)
            return null;
        storeMy.Close();
        return certColl[0];
    }

    /// <summary>
    /// Add a sign to the message
    /// </summary>
    /// <param name="data">message data flow</param>
    /// <returns></returns>
    public static byte[] Sign(this byte[] data)
    {
        X509Certificate2 certificate = GetSenderCert();
        if (certificate == null) return null;            
        if (data == null)
            throw new ArgumentNullException("data");
        if (certificate == null)
            throw new ArgumentNullException("certificate");

        //Set the message to sign
        ContentInfo content = new ContentInfo(data);
        signedCms = new SignedCms(content, false);
        CmsSigner signer = new CmsSigner(certificate);            
        signer.IncludeOption = X509IncludeOption.EndCertOnly; 

        //Create the sign
        signedCms.ComputeSignature(signer);
        return signedCms.Encode();
    }

正如我之前所说,此代码在给定的情况下(1024位SHA1 + PKCS#7)可以正常工作。 现在,客户端要求更新密码,特别是使用 SHA256 代替SHA1和 PKCS#10 代替PKCS#7,密钥长度为2048位而不是1024。 / p>

根据您的经验,我应该怎么做才能获得新要求?

我唯一能确定的是,我不能使用大于此版本的NET Framework,因为这些设备是旧的XP,并且不能因公司问题而更改。因此,我不能使用为.NET 4.7.1发布的新库来解决我的问题。

我想新证书将作为以前的方法发布,即要安装在计算机中的发件人文件和发件人的文件。

老实说,我对加密没有太多的经验,我想找到一条可以遵循当前方法逻辑的简单方法,因为事实上它们的范围不会改变,而只是签名方法。

如果确实有帮助,我在使用其他库,pinvoke和其他东西方面没有其他限制。

感谢大家的支持 任何建议表示赞赏。 问候

重要更新

我想知道国家机构的要求。 首先,它阐明了2048位的#PKCS10是指请求新证书的方式。需要两个opensl请求(具有特定的范式),并生成两个文件:.p12文件(用于发件人,用于对消息进行签名),以PKCS#10请求以2048位发布,另一个文件(我假设是.cer)文件)以供接收器解码文件。

其余部分,他们确认从SHA1切换到SHA2。 我将继续与他们联系以获取更多信息,但是基于他们的解释,考虑到我仍然必须在计算机上安装新证书并将其用于常规操作,是否足以更改从SHA1(默认)到SHA2的算法,还是我应该做其他事情? 谢谢,问候

0 个答案:

没有答案