/// <summary> /// Load state from an XML element /// </summary> /// <param name="xmlElement">XML element containing new state</param> /// <param name="counterSignedXmlElement">Element containing parent signature (needed if there are counter signatures)</param> public void LoadXml(XmlElement xmlElement, XmlElement counterSignedXmlElement) { XmlNamespaceManager xmlNamespaceManager; XmlNodeList xmlNodeList; if (xmlElement == null) { throw new ArgumentNullException("xmlElement"); } if (xmlElement.HasAttribute("Id")) { this.id = xmlElement.GetAttribute("Id"); } else { this.id = ""; } if (xmlElement.HasAttribute("Target")) { this.target = xmlElement.GetAttribute("Target"); } else { this.target = ""; throw new CryptographicException("Target attribute missing"); } xmlNamespaceManager = new XmlNamespaceManager(xmlElement.OwnerDocument.NameTable); xmlNamespaceManager.AddNamespace("xsd", XadesSignedXml.XadesNamespaceUri); xmlNodeList = xmlElement.SelectNodes("xsd:SignedProperties", xmlNamespaceManager); if (xmlNodeList.Count == 0) { throw new CryptographicException("SignedProperties missing"); } this.signedProperties = new SignedProperties(); this.signedProperties.LoadXml((XmlElement)xmlNodeList.Item(0)); xmlNodeList = xmlElement.SelectNodes("xsd:UnsignedProperties", xmlNamespaceManager); if (xmlNodeList.Count != 0) { this.unsignedProperties = new UnsignedProperties(); this.unsignedProperties.LoadXml((XmlElement)xmlNodeList.Item(0), counterSignedXmlElement); } }
private X509Certificate2[] ValidateCertificateByOCSP(UnsignedProperties unsignedProperties, X509Certificate2 client, X509Certificate2 issuer) { bool byKey = false; List<string> ocspServers = new List<string>(); Org.BouncyCastle.X509.X509Certificate clientCert = CertUtil.ConvertToX509Certificate(client); Org.BouncyCastle.X509.X509Certificate issuerCert = CertUtil.ConvertToX509Certificate(issuer); OcspClient ocsp = new OcspClient(); string certOcspUrl = ocsp.GetAuthorityInformationAccessOcspUrl(issuerCert); if (!string.IsNullOrEmpty(certOcspUrl)) { ocspServers.Add(certOcspUrl); } foreach (var ocspUrl in _firma.OCSPServers) { ocspServers.Add(ocspUrl); } foreach (var ocspUrl in ocspServers) { byte[] resp = ocsp.QueryBinary(clientCert, issuerCert, ocspUrl); FirmaXadesNet.Clients.CertificateStatus status = ocsp.ProcessOcspResponse(clientCert, issuerCert, resp); if (status == FirmaXadesNet.Clients.CertificateStatus.Revoked) { throw new Exception("Certificado revocado"); } else if (status == FirmaXadesNet.Clients.CertificateStatus.Good) { Org.BouncyCastle.Ocsp.OcspResp r = new OcspResp(resp); byte[] rEncoded = r.GetEncoded(); BasicOcspResp or = (BasicOcspResp)r.GetResponseObject(); string guidOcsp = Guid.NewGuid().ToString(); OCSPRef ocspRef = new OCSPRef(); ocspRef.OCSPIdentifier.UriAttribute = "#OcspValue" + guidOcsp; DigestUtil.SetCertDigest(rEncoded, _firma.RefsDigestMethod, ocspRef.CertDigest); Org.BouncyCastle.Asn1.Ocsp.ResponderID rpId = or.ResponderId.ToAsn1Object(); string name = GetResponderName(rpId, ref byKey); if (!byKey) { ocspRef.OCSPIdentifier.ResponderID = RevertIssuerName(name); } else { ocspRef.OCSPIdentifier.ResponderID = name; ocspRef.OCSPIdentifier.ByKey = true; } ocspRef.OCSPIdentifier.ProducedAt = or.ProducedAt.ToLocalTime(); unsignedProperties.UnsignedSignatureProperties.CompleteRevocationRefs.OCSPRefs.OCSPRefCollection.Add(ocspRef); OCSPValue ocspValue = new OCSPValue(); ocspValue.PkiData = rEncoded; ocspValue.Id = "OcspValue" + guidOcsp; unsignedProperties.UnsignedSignatureProperties.RevocationValues.OCSPValues.OCSPValueCollection.Add(ocspValue); return (from cert in or.GetCerts() select new X509Certificate2(cert.GetEncoded())).ToArray(); } } throw new Exception("El certificado no ha podido ser validado"); }
private bool ValidateCertificateByCRL(UnsignedProperties unsignedProperties, X509Certificate2 certificate, X509Certificate2 issuer) { Org.BouncyCastle.X509.X509Certificate clientCert = CertUtil.ConvertToX509Certificate(certificate); Org.BouncyCastle.X509.X509Certificate issuerCert = CertUtil.ConvertToX509Certificate(issuer); foreach (var crlEntry in _firma.CRLEntries) { if (crlEntry.IssuerDN.Equivalent(issuerCert.SubjectDN) && crlEntry.NextUpdate.Value > DateTime.Now) { if (!crlEntry.IsRevoked(clientCert)) { if (!ExistsCRL(unsignedProperties.UnsignedSignatureProperties.CompleteRevocationRefs.CRLRefs.CRLRefCollection, issuer.Subject)) { string idCrlValue = "CRLValue-" + Guid.NewGuid().ToString(); CRLRef crlRef = new CRLRef(); crlRef.CRLIdentifier.UriAttribute = "#" + idCrlValue; crlRef.CRLIdentifier.Issuer = issuer.Subject; crlRef.CRLIdentifier.IssueTime = crlEntry.ThisUpdate.ToLocalTime(); var crlNumber = GetCRLNumber(crlEntry); if (crlNumber.HasValue) { crlRef.CRLIdentifier.Number = crlNumber.Value; } byte[] crlEncoded = crlEntry.GetEncoded(); DigestUtil.SetCertDigest(crlEncoded, _firma.RefsDigestMethod, crlRef.CertDigest); CRLValue crlValue = new CRLValue(); crlValue.PkiData = crlEncoded; crlValue.Id = idCrlValue; unsignedProperties.UnsignedSignatureProperties.CompleteRevocationRefs.CRLRefs.CRLRefCollection.Add(crlRef); unsignedProperties.UnsignedSignatureProperties.RevocationValues.CRLValues.CRLValueCollection.Add(crlValue); } return true; } else { throw new Exception("Certificado revocado"); } } } return false; }
/// <summary> /// Determina si un certificado ya ha sido añadido a la colección de certificados /// </summary> /// <param name="cert"></param> /// <param name="unsignedProperties"></param> /// <returns></returns> private bool CertificateChecked(X509Certificate2 cert, UnsignedProperties unsignedProperties) { string certHash = null; using (var hashAlg = DigestUtil.GetHashAlg(_firma.RefsDigestMethod)) { certHash = Convert.ToBase64String(hashAlg.ComputeHash(cert.GetRawCertData())); } foreach (Cert item in unsignedProperties.UnsignedSignatureProperties.CompleteCertificateRefs.CertRefs.CertCollection) { if (Convert.ToBase64String(item.CertDigest.DigestValue) == certHash) { return true; } } return false; }
/// <summary> /// Inserta y valida los certificados del servidor de sellado de tiempo. /// </summary> /// <param name="unsignedProperties"></param> private void AddTSACertificates(UnsignedProperties unsignedProperties) { TimeStampToken token = new TimeStampToken(new Org.BouncyCastle.Cms.CmsSignedData(unsignedProperties.UnsignedSignatureProperties.SignatureTimeStampCollection[0].EncapsulatedTimeStamp.PkiData)); IX509Store store = token.GetCertificates("Collection"); Org.BouncyCastle.Cms.SignerID signerId = token.SignerID; List<X509Certificate2> tsaCerts = new List<X509Certificate2>(); foreach (var tsaCert in store.GetMatches(null)) { X509Certificate2 cert = new X509Certificate2(((Org.BouncyCastle.X509.X509Certificate)tsaCert).GetEncoded()); tsaCerts.Add(cert); } X509Certificate2 startCert = DetermineStartCert(tsaCerts); AddCertificate(startCert, unsignedProperties, true, tsaCerts.ToArray()); }
/// <summary> /// Inserta en la lista de certificados el certificado y comprueba la valided del certificado. /// </summary> /// <param name="cert"></param> /// <param name="unsignedProperties"></param> /// <param name="addCertValue"></param> /// <param name="extraCerts"></param> private void AddCertificate(X509Certificate2 cert, UnsignedProperties unsignedProperties, bool addCert, X509Certificate2[] extraCerts = null) { if (addCert) { if (CertificateChecked(cert, unsignedProperties)) { return; } string guidCert = Guid.NewGuid().ToString(); Cert chainCert = new Cert(); chainCert.IssuerSerial.X509IssuerName = cert.IssuerName.Name; chainCert.IssuerSerial.X509SerialNumber = CertUtil.HexToDecimal(cert.SerialNumber); DigestUtil.SetCertDigest(cert.GetRawCertData(), _firma.RefsDigestMethod, chainCert.CertDigest); chainCert.URI = "#Cert" + guidCert; unsignedProperties.UnsignedSignatureProperties.CompleteCertificateRefs.CertRefs.CertCollection.Add(chainCert); EncapsulatedX509Certificate encapsulatedX509Certificate = new EncapsulatedX509Certificate(); encapsulatedX509Certificate.Id = "Cert" + guidCert; encapsulatedX509Certificate.PkiData = cert.GetRawCertData(); unsignedProperties.UnsignedSignatureProperties.CertificateValues.EncapsulatedX509CertificateCollection.Add(encapsulatedX509Certificate); } var chain = CertUtil.GetCertChain(cert, extraCerts).ChainElements; if (chain.Count > 1) { X509ChainElementEnumerator enumerator = chain.GetEnumerator(); enumerator.MoveNext(); // el mismo certificado que el pasado por parametro enumerator.MoveNext(); bool valid = ValidateCertificateByCRL(unsignedProperties, cert, enumerator.Current.Certificate); if (!valid) { var ocspCerts = ValidateCertificateByOCSP(unsignedProperties, cert, enumerator.Current.Certificate); if (ocspCerts != null) { X509Certificate2 startOcspCert = DetermineStartCert(new List<X509Certificate2>(ocspCerts)); if (startOcspCert.IssuerName.Name != enumerator.Current.Certificate.SubjectName.Name) { var chainOcsp = CertUtil.GetCertChain(startOcspCert, ocspCerts); AddCertificate(chainOcsp.ChainElements[1].Certificate, unsignedProperties, true, ocspCerts); } } } AddCertificate(enumerator.Current.Certificate, unsignedProperties, true, extraCerts); } }
/// <summary> /// Default constructor /// </summary> public QualifyingProperties() { this.signedProperties = new SignedProperties(); this.unsignedProperties = new UnsignedProperties(); }