在将.NET桌面应用程序移植到Windows应用商店应用程序时,我遇到了麻烦...... 简而言之,我有一个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 cryptography - using SignedCms Pkcs7
我真的很感激一些帮助:)
基本问题是从签名字节数组中获取原始xml数据。 或者,更具体地说,我需要WinRT中这几行代码的功能
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; }
}
答案 0 :(得分:1)
根据评论,我了解到你有一个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 editor,这是一个非常有用的GUI应用程序,用于显示PKCS#7的结构,证书等。所以我可以只推荐那两个。
答案 1 :(得分:1)
您可能正在寻找类似Windows.Security.Cryptography.Certificates.CmsAttachedSignature.VerifySignature()以及它的内容'属性 见here