在WinRT中是否有SignedCMS的替代方案?

本文关键字:方案 SignedCMS WinRT 是否 | 更新日期: 2023-09-27 17:53:23

在将。net桌面应用程序移植到Windows Store应用程序时,我又遇到了麻烦……长话短说,我有一个ZIP文件,其中包含加密和签名的XML文件和证书。解密工作(或多或少),但现在我必须"取消签名"的XML,我卡住了。

在。net应用程序中,取消签名是通过System.Security.Cryptography.Pkcs.SignedCms完成的,但这个类在WinRt中不存在(一如往常…)

在WinRT中有其他选择吗?

下面是。net应用程序中使用的一些代码:
public static byte[] CheckAndRemoveSignature(byte[] data,  X509Certificate2Collection certStore, out SignedCms out_signature)
    {
        SignedCms signedMessage = new SignedCms();
        signedMessage.Decode(data);
        if ((certStore != null) && (certStore.Count > 0))
            signedMessage.CheckSignature(certStore, true);
        else
            signedMessage.CheckSignature(true);
        out_signature = signedMessage;
        // return data without signature
        return signedMessage.ContentInfo.Content;
    }

我已经搜索了很多,但我找到的唯一可以帮助我的是这篇文章。不幸的是,标记的答案并没有提供任何有用的信息:(

Windows 8 Metro加密-使用signnedcms Pkcs7

我真的很感激你的帮助:)


编辑

基本问题是从有符号字节数组中获取原始xml数据。或者,更具体地说,我需要WinRT

中这几行代码的功能
SignedCms signedMessage = new SignedCms();
signedMessage.Decode(data);
byte[] result = signedMessage.ContentInfo.Content;

我尝试了从pepo的例子,但我得到一个malformmedcontent异常

private byte[] CheckAndRemoveSignature(byte[] data)
    {
        try
        {
            // load using bouncyCastle
            CmsSignedData sig = new CmsSignedData(data);
            // var allSigsValid = VerifySignatures(sig);
            byte[] content = sig.SignedContent.GetContent() as byte[];
            return content;
        }
        catch (Exception ex)
        {
            cryptOutput.Text += "Error removing Signature: " + ex;
            return data;
        }

我得到了这个异常:

Org.BouncyCastle.Cms.CmsException: Malformed content. ---> System.ArgumentException: unknown object in factory: DerApplicationSpecific
at Org.BouncyCastle.Asn1.Cms.ContentInfo.GetInstance(Object obj)
at Org.BouncyCastle.Cms.CmsUtilities.ReadContentInfo(Asn1InputStream aIn)
   --- End of inner exception stack trace ---
at Org.BouncyCastle.Cms.CmsUtilities.ReadContentInfo(Asn1InputStream aIn)
at Org.BouncyCastle.Cms.CmsUtilities.ReadContentInfo(Stream input)
at Org.BouncyCastle.Cms.CmsSignedData..ctor(Byte[] sigBlock)
at TestApp.MainPage.CheckAndRemoveSignature(Byte[] data)

来自桌面应用程序对xml文件进行签名的代码:

  private byte[] signInternal(byte[] data, X509Certificate2 signatureCert, bool signatureOnly)
    {
        CAPICOM.SignedData signedData = new CAPICOM.SignedDataClass();
        CAPICOM.Utilities u = new CAPICOM.UtilitiesClass();
        signedData.set_Content(u.ByteArrayToBinaryString(data));
        GC.Collect();
        CAPICOM.Signer signer = new CAPICOM.Signer();
        signer.Options = CAPICOM.CAPICOM_CERTIFICATE_INCLUDE_OPTION.CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY;
        CAPICOM.CertificateClass certClass = new CAPICOM.CertificateClass();
        certClass.Import(Convert.ToBase64String(signatureCert.Export(X509ContentType.SerializedCert)));
        signer.Certificate = certClass;
        GC.Collect();
        if (this.validateCert(signatureCert))
            return (byte[])Convert.FromBase64String(signedData.Sign(signer, signatureOnly, CAPICOM.CAPICOM_ENCODING_TYPE.CAPICOM_ENCODE_BASE64));
        else
            return new byte[] { };
    }

解决方案

最后发现编码有一个大问题,我认为不值得注意。来自pepo的答案是有效的,但是我将发布我的版本,以展示它是如何工作的,如果你从zip文件夹中获取文件:

// get bytes from zip
byte[] data = getFileContentAsByteArray(zipBytes, ze.FileName);
var dataString = Encoding.UTF8.GetString(data, 0, data.Length);
// check and remove signature
bool isValid;
byte[] withoutSig = CheckAndRemoveSignature(dataString, out isValid);


    private byte[] CheckAndRemoveSignature(string data, out bool isValid)
    {
        isValid = false;
        // using bouncyCastle
        try
        {
            var bytes = Convert.FromBase64String(data);
            // assign data to CmsSignedData                  
            CmsSignedData sig = new CmsSignedData(bytes);
            // check if signature is valid
            var allSigsValid = VerifySignaturesBC(sig);
            if (allSigsValid.Equals(true)) { isValid = true; }
            // get signature from cms
            byte[] content = sig.SignedContent.GetContent() as byte[];
            return content;
        }
        catch (Exception ex) { cryptOutput.Text += "Error in 'BouncyCastle unsign' " + ex; return null; }
    }

在WinRT中是否有SignedCMS的替代方案?

根据注释,我知道你有一个pkcs# 7结构(SignedCms),该结构的内容是XmlDocument。

因为在WinRT API中没有signedcm,所以你有两个选择。要么使用ASN.1库,手动解析pkcs# 7查找内容,要么使用BouncyCastle,它实现了signnedcms,可以解析该结构。你要我举一个使用bouncyCastle的例子。

using Org.BouncyCastle.Cms;
using Org.BouncyCastle.X509.Store;
using System.Collections;
using System.Security.Cryptography.Pkcs;
namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            // make some pkcs7 signedCms to work on
            SignedCms p7 = new SignedCms(new System.Security.Cryptography.Pkcs.ContentInfo(new byte[] { 0x01, 0x02 }));
            p7.ComputeSignature(new CmsSigner(), false);
            // encode to get signedCms byte[] representation
            var signedCms = p7.Encode();
            // load using bouncyCastle
            CmsSignedData sig = new CmsSignedData(signedCms);
            var allSigsValid = VerifySignatures(sig);
            byte[] content = sig.SignedContent.GetContent() as byte[];
        }
        // taken from bouncy castle SignedDataTest.cs
        private static bool VerifySignatures(
            CmsSignedData sp)
        {
            var signaturesValid = true;
            IX509Store x509Certs = sp.GetCertificates("Collection");
            SignerInformationStore signers = sp.GetSignerInfos();
            foreach (SignerInformation signer in signers.GetSigners())
            {
                ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
                IEnumerator certEnum = certCollection.GetEnumerator();
                certEnum.MoveNext();
                Org.BouncyCastle.X509.X509Certificate cert = (Org.BouncyCastle.X509.X509Certificate)certEnum.Current;
                signaturesValid &= signer.Verify(cert);
            }
            return signaturesValid;
        }
    }
}

至于ASN.1库,我只使用了具有ASN.1解析器或ASN.1编辑器的bouncyCastle,这是一个非常有用的GUI应用程序,用于显示pkcs# 7的结构,证书等。所以我只推荐这两种

你可能正在寻找像windows . security . cryptographic . certificates . cmsattachedsignature . verifysignature()这样的东西,它的'Content'属性看到