【发布时间】:2014-03-26 10:43:29
【问题描述】:
在将 .NET 桌面应用程序移植到 Windows 应用商店应用程序时,我又遇到了麻烦...... 长话短说,我有一个 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 cryptography - using SignedCms Pkcs7
我真的很感激这里的一些帮助:)
编辑
本质问题是从有符号字节数组中取出原始xml数据。 或者,更具体地说,我需要 WinRT 中这几行代码的功能
SignedCms signedMessage = new SignedCms();
signedMessage.Decode(data);
byte[] result = signedMessage.ContentInfo.Content;
我尝试了 pepo 中的示例,但出现 MalformedContent 异常
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; }
}
【问题讨论】:
-
为什么需要 SignedCMS?你有 xmldsig 或 CMS (PKCS#7) 吗?
-
正如我所说,我正在移植一个现有的应用程序,在那里,SignedCMS.ContentInfo.Content 用于从 ZIP 文件中获取 .xml - 我认为我在 WinRT 中也需要它,因为当我只解密,不行。
-
那么你有两个选择。使用 c# 版本的 bouncycastle 或使用一些 ASN.1 库手动解析 xml。
-
有没有办法用标准的 WinRT API 做到这一点?干得好微软...不过还是谢谢你的回复:)
-
好吧,您可以使用 LINQ to XML 让解析 XML 变得异常简单。
标签: c# .net windows-runtime windows-store-apps asn.1