Example #1
0
        internal Signature(XmlElement signatureElement, ILookup <XmlElement, XmlElement> childIndex)
        {
            // store element for countersigning
            XmlElement = signatureElement;
            // parse signature
            _xades = Xades.Load(signatureElement);
            // check signature; resolve external references relative to main document
            string baseUri = signatureElement.OwnerDocument?.BaseURI;

            IsValid = _xades.CheckSignature(out X509Certificate2 certificate, u =>
            {
                Uri uri = baseUri == null ? new Uri(u) : new Uri(new Uri(baseUri), u);
                return(File.OpenRead(uri.LocalPath));
            });
            // store certificate
            Certificate = certificate;
            if (certificate != null)
            {
                X509Chain chain = new X509Chain();
                chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                //chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
                CertificateIsValid = chain.Build(certificate);
                CertificateError   = (CertificateIsValid == false) ? chain.ChainStatus?.First().StatusInformation.Trim() : null;
                CACertificate      = chain.ChainElements.OfType <X509ChainElement>().LastOrDefault(x => x.Certificate.Extensions.OfType <X509BasicConstraintsExtension>().Any(y => y.CertificateAuthority))?.Certificate;
            }

            XadesSignatureProperties signatureProperties = _xades.SignatureProperties;

            if (signatureProperties != null)
            {
                // store date
                SignatureDate = _xades.SignatureProperties.SigningTime;

                // read signature policy
                if (signatureProperties.PolicyImplied)
                {
                    SignaturePolicy = new SignaturePolicy();
                }
                else if (signatureProperties.PolicyId != null)
                {
                    SignaturePolicy = new SignaturePolicy(signatureProperties.PolicyId);
                }
            }

            // store signed item references
            Items = _xades.References.Select(x => new SignedItem(signatureElement, x, SignaturePolicy)).ToList();
            // determine type of signature
            Type = Items.Any(x => x.Type == SignedItemType.Document) ? SignatureType.Document : Items.Any(x => x.Type == SignedItemType.Signature) ? SignatureType.CounterSignature : SignatureType.Generic;

            // parse child signatures
            Signatures = childIndex[signatureElement].Select(x => new Signature(x, childIndex)).ToList();
        }
Example #2
0
        internal SignedItem(XmlElement signatureElement, XadesReference reference, SignaturePolicy signaturePolicy)
        {
            // determine type from reference uri
            Uri = reference.URI;
            if (Uri == "" || Uri == "#xpointer(/)")
            {
                Type = SignedItemType.Document;
            }
            else if (reference.Type == Xades.CounterSignatureRefernceType)
            {
                Type = SignedItemType.Signature;
            }
            else if (Uri[0] == '#')
            {
                string     idref = Uri.Substring(1);
                XmlElement node  = signatureElement.OwnerDocument.SelectSingleNode("//*[@id='" + idref + "' or @Id='" + idref + "']") as XmlElement;
                if (node != null && node.LocalName == "SignatureValue" && node.NamespaceURI == SignedXml.XmlDsigNamespaceUrl)
                {
                    Type = SignedItemType.Signature;
                }
                else
                {
                    Type = SignedItemType.Fragment;
                }
            }
            else
            {
                Type = SignedItemType.File;
            }

            // store transform
            Transform = new TransformSet(null, reference.TransformChain);
            // find or add commitment type in/to policy
            if (reference.CommitmentTypeId != null)
            {
                SignaturePolicy.CommitmentType commitmentType = signaturePolicy.CommitmentTypes.FirstOrDefault(x => x.Identifier == reference.CommitmentTypeId.Identifier);
                if (commitmentType == null)
                {
                    commitmentType = new SignaturePolicy.CommitmentType()
                    {
                        Identifier = reference.CommitmentTypeId.Identifier, Description = reference.CommitmentTypeId.Description
                    };
                    signaturePolicy.CommitmentTypes.Add(commitmentType);
                }
                CommitmentType = commitmentType;
            }

            IsValid = reference.IsValid;
        }
Example #3
0
        public bool Countersign(X509Certificate2 cert, List <SignedItem> items, SignaturePolicy policy)
        {
            XmlDocument xmlDocument = XmlElement.OwnerDocument;

            // find or add id to signature value
            XmlElement signatureValue = XmlElement["SignatureValue", SignedXml.XmlDsigNamespaceUrl];

            if (signatureValue == null)
            {
                return(false);
            }
            string id = (signatureValue.Attributes["Id"] ?? signatureValue.Attributes["id"])?.Value;

            if (id == null)
            {
                HashSet <string> ids = new HashSet <string>(xmlDocument.SelectNodes("//@id | //@Id").OfType <XmlAttribute>().Select(x => x.Value));
                Random           rnd = new Random();
                for (; ;)
                {
                    id = $"signature-value-{rnd.Next():x8}";
                    if (!ids.Contains(id))
                    {
                        break;
                    }
                }
                signatureValue.SetAttribute("Id", id);
            }

            // find or add unsigned properties
            XmlElement qualifyingProperties = XmlElement.ChildNodes.OfType <XmlElement>().Where(x => x.LocalName == "Object" && x.NamespaceURI == SignedXml.XmlDsigNamespaceUrl).Select(x => x["QualifyingProperties", Xades.XadesNamespaceUrl]).SingleOrDefault(x => x != null);

            if (qualifyingProperties == null)
            {
                return(false);
            }
            XmlElement unsignedSignatureProperties = qualifyingProperties.GetOrCreate("UnsignedProperties", Xades.XadesNamespaceUrl).GetOrCreate("UnsignedSignatureProperties", Xades.XadesNamespaceUrl);
            XmlElement signatureLocation           = xmlDocument.CreateElement("CounterSignature", Xades.XadesNamespaceUrl);

            unsignedSignatureProperties.AppendChild(signatureLocation);

            // create signature
            Xades xades = Xades.Create(xmlDocument, signatureLocation);

            xades.SignatureProperties.SigningTime = DateTime.UtcNow;
            // add policy
            if (policy != null)
            {
                xades.SignatureProperties.PolicyId = new ObjectIdentifier()
                {
                    Identifier = policy.Identifier, Description = policy.Description
                };
                xades.SignatureProperties.PolicyURIs = new List <string>()
                {
                    policy.URI
                };
                // todo: determine transforms, calculate digest
            }
            // add countersignature reference
            XadesReference reference = new XadesReference($"#{id}", TransformSet.Signature.TransformChain)
            {
                Type = Xades.CounterSignatureRefernceType
            };
            SignedItem signatureItem = items.Single(x => x.Type == SignedItemType.Signature);

            if (policy != null && signatureItem.CommitmentType != null)
            {
                reference.CommitmentTypeId = new ObjectIdentifier()
                {
                    Identifier = signatureItem.CommitmentType.Identifier, Description = signatureItem.CommitmentType.Description
                }
            }
            ;
            xades.References.Add(reference);
            // add other references
            foreach (SignedItem item in items.Where(x => x.Type != SignedItemType.Signature))
            {
                reference = new XadesReference(item.Uri, item.Transform.TransformChain);
                if (policy != null && item.CommitmentType != null)
                {
                    reference.CommitmentTypeId = new ObjectIdentifier()
                    {
                        Identifier = signatureItem.CommitmentType.Identifier, Description = signatureItem.CommitmentType.Description
                    }
                }
                ;
                xades.References.Add(reference);
            }
            // sign
            string baseUri = xmlDocument.BaseURI;

            xades.UriResolver = u =>
            {
                Uri uri = baseUri == null ? new Uri(u) : new Uri(new Uri(baseUri), u);
                return(File.OpenRead(uri.LocalPath));
            };
            XmlElement result = xades.Sign(cert);

            signatureLocation.AppendChild(result);
            return(true);
        }
    }
}