我已經看到幾個類似的問題,但沒有一個解決我所問的問題。SignedXml.CheckSignature只有在使用私鑰進行驗證時纔會返回true
我想簽署一個XML,然後使用C#驗證它的公鑰。
我用密鑰對XML進行簽名,然後將密鑰導出到XML。然後將密鑰和簽名的XML帶到另一臺計算機,使用rsa.FromXmlString(doc.InnerXml)
導入密鑰,並驗證XML簽名。
如果我使用rsa.ToXmlString(True)
將公鑰和私鑰導出到XML,這將起作用。但是,我只想使用rsa.ToXmlString(False)
導出我的公鑰。如果我只導出公鑰並將其導入第二臺計算機,並嘗試驗證XML簽名,則表示簽名無效。
首先,我是否應該能夠使用公鑰驗證簽名的XML?第二,如果這是真的,那麼爲什麼我的驗證XML函數只能與pub/priv密鑰對一起使用,而不能與只使用公鑰?
你有什麼關於如何調試這個問題的智慧?我不知道還有什麼要做,因爲signedXml.CheckSignature(Key);
沒有提供任何有關它失敗原因的信息。
下面是我的導入密鑰,導出密鑰,簽名XML和驗證XML函數。如果您需要更多信息,請與我們聯繫。
public static void ImportKeyFromFile(string ContainerName, string inputFile)
{
try
{
// Create new XmlDocument.
XmlDocument doc = new XmlDocument();
// Load XML Document.
doc.Load(inputFile);
// Create the CspParameters object and set the key container
// name used to store the RSA key pair.
CspParameters cp = new CspParameters();
cp.KeyContainerName = ContainerName;
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container MyKeyContainerName.
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
// Get RSA Parameters from xml document.
rsa.FromXmlString(doc.InnerXml);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public static void ExportKeyToFile(string ContainerName, string outputPath, bool private_key)
{
try
{
// Create the CspParameters object and set the key container
// name used to store the RSA key pair.
CspParameters cp = new CspParameters();
cp.KeyContainerName = ContainerName;
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container MyKeyContainerName.
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
// Create new XmlDocument.
XmlDocument doc = new XmlDocument();
// Store rsa key.
doc.InnerXml = rsa.ToXmlString(private_key);
// Save Document.
doc.Save(outputPath);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public static Boolean VerifyXml(XmlDocument Doc, RSA Key)
{
// Check arguments.
if (Doc == null)
throw new ArgumentException("Doc");
if (Key == null)
throw new ArgumentException("Key");
// Create a new SignedXml object and pass it
// the XML document class.
SignedXml signedXml = new SignedXml(Doc);
// Find the "Signature" node and create a new
// XmlNodeList object.
XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");
// Throw an exception if no signature was found.
if (nodeList.Count <= 0)
{
throw new CryptographicException("Verification failed: No Signature was found in the document.");
}
// Load the first <signature> node.
signedXml.LoadXml((XmlElement)nodeList[0]);
// Check the signature and return the result.
return signedXml.CheckSignature(Key);
}
public static void SignXml(XmlDocument xmlDoc, RSA Key)
{
// Check arguments.
if (xmlDoc == null)
throw new ArgumentException("xmlDoc");
if (Key == null)
throw new ArgumentException("Key");
// Create a SignedXml object.
SignedXml signedXml = new SignedXml(xmlDoc);
// Add the key to the SignedXml document.
signedXml.SigningKey = Key;
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = "";
// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
// Compute the signature.
signedXml.ComputeSignature();
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Append the element to the XML document.
xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
}
另一種選擇將是包括簽署文檔中鍵(或者甚至是證書)。這並不佔用太多空間,但可以減輕消費者從單獨渠道獲取鑰匙的難度。 –
消費者仍然需要一些如何檢查公鑰是否屬於她認爲是的。就我而言,當xml被接收時,消費者已經擁有了公鑰。 – user985637
確實如此,但它們只需要一個密鑰指紋(密鑰的散列)與接收的指紋進行比較。 –