WinRT中是否有SignedCMS的替代品?

在将.NET桌面应用程序移植到Windowsapp store应用程序时,我再次陷入困境……简而言之,我有一个ZIP文件,其中包含加密和签名的XML文件以及证书。 解密工作(或多或少),但现在我必须“取消签名”XML并且我被卡住了。

在.NET App中,使用System.Security.Cryptography.Pkcs.SignedCms完成取消签名,但WinRt中不存在该类(一如既往……)

WinRT还有其他选择吗?

这是.NET App中使用的一些代码:

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加密 – 使用SignedCms Pkcs7

我真的很感激这里的一些帮助:)


编辑

基本问题是从签名字节数组中获取原始xml数据。 或者,更具体地说,我需要在WinRT中使用这几行代码的function

 SignedCms signedMessage = new SignedCms(); signedMessage.Decode(data); byte[] result = signedMessage.ContentInfo.Content; 

我尝试了pepo的例子,但是我得到了一个MalformedContent Exception

 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; } } 

根据评论,我了解到你有一个PKCS#7结构(SignedCms),该结构的内容是XmlDocument。

因为WinRT API中没有SignedCms,所以有两种选择。 使用一些ASN.1库并手动解析PKCS#7寻找内容或使用即已实现SignedCms的BouncyCastle并且可以解析该strusture。 你问了一个使用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库,我只使用了bouncyCastle,它有ASN.1解析器或ASN.1编辑器 ,这是一个非常有用的GUI应用程序,用于显示PKCS#7的结构,证书等。所以我只推荐那两个。

你可能正在寻找像Windows.Security.Cryptography.Certificates.CmsAttachedSignature.VerifySignature()这样的东西,它的’内容’属性请看这里