internal static bool?VerifyAllSign(XmlDocument xmlDocument) { if (!CheckIfDocumentPreviouslySigned(xmlDocument)) { return(null); //File has no sign } while (CheckIfDocumentPreviouslySigned(xmlDocument)) { bool?lastSignVerificationStatus = VerifyLastSign(xmlDocument); if (lastSignVerificationStatus == false) { return(false); //Not counting all sign, find first invalid sign and tell that file is invalid } string id = GetLastSignatureId(xmlDocument); //Update xmlDocument by removing last sign tag xmlDocument = RemoveLastSign(xmlDocument); if (Tsa.ValidateTimestamp(xmlDocument, id) == false) { return(false); //The TSA signature is invalid } } return(true); }
//tutorial - https://www.asptricks.net/2015/09/sign-xmldocument-with-x509certificate2.html internal static XmlDocument GetSignedXMLDocument(XmlDocument xmlDocument, X509Certificate2 certificate, long procedureSerial = -1, string reason = "") { //Before signing, should check if current document sign is valid or not, if current document is invalid, then new sign should not be added - not implemented yet, but should be if (CheckIfDocumentPreviouslySigned(xmlDocument)) { bool?isLastSignVerified = VerifyLastSign(xmlDocument); if (isLastSignVerified == false) { MessageBox.Show("The file was TEMPERED after last sign !!"); return(null); //Last Sign Not Verified } } //Then sign the xml try { //MessageBox.Show(certificate.Subject); SignedXml signedXml = new SignedXml(xmlDocument); signedXml.SigningKey = certificate.PrivateKey; // Create a reference to be signed Reference reference = new Reference(); ///////////////////// reference.Uri = ""; //"#" + procedureSerial; //reference.Type = reason; //reference.Id = DateTime.UtcNow.Ticks.ToString(); Tsa tsa = new Tsa(); string signedTsaString = tsa.GetSignedHashFromTsa(xmlDocument); DateTime?tsaTime = Tsa.GetTsaTimeFromSignedHash(signedTsaString); //reference.Id = Base64EncodedCurrentTime(tsaTime); reference.Id = signedTsaString; //bool status = Tsa.ValidateTimestamp(xmlDocument, reference.Id); //reference.TransformChain = ; ///////////////////// // Add an enveloped transformation to the reference. XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(true); reference.AddTransform(env); // Add the reference to the SignedXml object. signedXml.AddReference(reference); //canonicalize XmlDsigC14NTransform c14t = new XmlDsigC14NTransform(); reference.AddTransform(c14t); KeyInfo keyInfo = new KeyInfo(); KeyInfoX509Data keyInfoData = new KeyInfoX509Data(certificate); KeyInfoName kin = new KeyInfoName(); //kin.Value = "Public key of certificate"; kin.Value = certificate.FriendlyName; RSA rsa = (RSA)certificate.PublicKey.Key; RSAKeyValue rkv = new RSAKeyValue(rsa); keyInfo.AddClause(rkv); keyInfo.AddClause(kin); keyInfo.AddClause(keyInfoData); signedXml.KeyInfo = keyInfo; //////////////////////////////////////////Add Other Data as we need//// // Add the data object to the signature. //CreateMetaDataObject("Name", GetNetworkTime()); signedXml.AddObject(CreateMetaDataObject(procedureSerial, reason)); /////////////////////////////////////////////////////////////////////// // Compute the signature. signedXml.ComputeSignature(); // Get the XML representation of the signature and save // it to an XmlElement object. XmlElement xmlDigitalSignature = signedXml.GetXml(); xmlDocument.DocumentElement.AppendChild( xmlDocument.ImportNode(xmlDigitalSignature, true) ); ///////////////////// } catch (Exception exception) { MessageBox.Show("Internal System Error during sign"); throw exception; } return(xmlDocument); }