Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Kazakov <vladimir.kazakov@live.com>2018-01-05 01:20:13 +0300
committerMarek Safar <marek.safar@gmail.com>2018-01-05 01:20:13 +0300
commitd0369589868f971fd13668906b178b158541344e (patch)
treee54e28eac29de0bcf23552bf9857f553287f3cf4 /mcs/class/System.Security
parent87315d19c6bdbb76f916b0f5c0df5043e717f579 (diff)
XMLDSIG from .NET Core. (#6154)
Diffstat (limited to 'mcs/class/System.Security')
-rw-r--r--mcs/class/System.Security/Makefile1
-rw-r--r--mcs/class/System.Security/System.Security.Cryptography.Xml/KeyInfoX509Data.cs285
-rw-r--r--mcs/class/System.Security/System.Security.Cryptography.Xml/Manifest.cs119
-rw-r--r--mcs/class/System.Security/System.Security.Cryptography.Xml/Signature.cs221
-rw-r--r--mcs/class/System.Security/System.Security.Cryptography.Xml/SignedInfo.cs219
-rw-r--r--mcs/class/System.Security/System.Security.Cryptography.Xml/SignedXml.cs1419
-rw-r--r--mcs/class/System.Security/System.Security.Cryptography.Xml/X509IssuerSerial.cs56
-rw-r--r--mcs/class/System.Security/System.Security.Cryptography.Xml/XmlSignature.cs128
-rw-r--r--mcs/class/System.Security/System.Security.dll.sources15
-rw-r--r--mcs/class/System.Security/Test/System.Security.Cryptography.Xml/EncryptedXmlTest.cs17
-rw-r--r--mcs/class/System.Security/Test/System.Security.Cryptography.Xml/SignedXmlTest.cs184
-rw-r--r--mcs/class/System.Security/common_System.Security.dll.sources9
12 files changed, 877 insertions, 1796 deletions
diff --git a/mcs/class/System.Security/Makefile b/mcs/class/System.Security/Makefile
index ae2de1a6370..04a3bea4d1e 100644
--- a/mcs/class/System.Security/Makefile
+++ b/mcs/class/System.Security/Makefile
@@ -8,6 +8,7 @@ MONO_SECURITY=Mono.Security
endif
LIBRARY = System.Security.dll
+API_BIN_REFS := System.Numerics
LIB_REFS = secxml/System bare/System.Xml $(MONO_SECURITY)
KEYFILE = ../msfinal.pub
LIB_MCS_FLAGS = \
diff --git a/mcs/class/System.Security/System.Security.Cryptography.Xml/KeyInfoX509Data.cs b/mcs/class/System.Security/System.Security.Cryptography.Xml/KeyInfoX509Data.cs
deleted file mode 100644
index 74280cb9151..00000000000
--- a/mcs/class/System.Security/System.Security.Cryptography.Xml/KeyInfoX509Data.cs
+++ /dev/null
@@ -1,285 +0,0 @@
-//
-// KeyInfoX509Data.cs - KeyInfoX509Data implementation for XML Signature
-//
-// Authors:
-// Sebastien Pouliot <sebastien@ximian.com>
-// Atsushi Enomoto (atsushi@ximian.com)
-// Tim Coleman (tim@timcoleman.com)
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) Tim Coleman, 2004
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Collections;
-using System.Runtime.InteropServices;
-using System.Security.Cryptography.X509Certificates;
-using System.Xml;
-
-namespace System.Security.Cryptography.Xml {
-
- public class KeyInfoX509Data : KeyInfoClause {
-
- private byte[] x509crl;
- private ArrayList IssuerSerialList;
- private ArrayList SubjectKeyIdList;
- private ArrayList SubjectNameList;
- private ArrayList X509CertificateList;
-
- public KeyInfoX509Data ()
- {
- }
-
- public KeyInfoX509Data (byte[] rgbCert)
- {
- AddCertificate (new X509Certificate (rgbCert));
- }
-
- public KeyInfoX509Data (X509Certificate cert)
- {
- AddCertificate (cert);
- }
-
-#if SECURITY_DEP
- public KeyInfoX509Data (X509Certificate cert, X509IncludeOption includeOption)
- {
- if (cert == null)
- throw new ArgumentNullException ("cert");
-
- switch (includeOption) {
- case X509IncludeOption.None:
- case X509IncludeOption.EndCertOnly:
- AddCertificate (cert);
- break;
- case X509IncludeOption.ExcludeRoot:
- AddCertificatesChainFrom (cert, false);
- break;
- case X509IncludeOption.WholeChain:
- AddCertificatesChainFrom (cert, true);
- break;
- }
- }
-
- // this gets complicated because we must:
- // 1. build the chain using a X509Certificate2 class;
- // 2. test for root using the Mono.Security.X509.X509Certificate class;
- // 3. add the certificates as X509Certificate instances;
- private void AddCertificatesChainFrom (X509Certificate cert, bool root)
- {
- X509Chain chain = new X509Chain ();
- chain.Build (new X509Certificate2 (cert));
- foreach (X509ChainElement ce in chain.ChainElements) {
- byte[] rawdata = ce.Certificate.RawData;
- if (!root) {
- // exclude root
- Mono.Security.X509.X509Certificate mx = new Mono.Security.X509.X509Certificate (rawdata);
- if (mx.IsSelfSigned)
- rawdata = null;
- }
-
- if (rawdata != null)
- AddCertificate (new X509Certificate (rawdata));
- }
- }
-#endif
-
- public ArrayList Certificates {
- get { return X509CertificateList; }
- }
-
- public byte[] CRL {
- get { return x509crl; }
- set { x509crl = value; }
- }
-
- public ArrayList IssuerSerials {
- get { return IssuerSerialList; }
- }
-
- public ArrayList SubjectKeyIds {
- get { return SubjectKeyIdList; }
- }
-
- public ArrayList SubjectNames {
- get { return SubjectNameList; }
- }
-
- public void AddCertificate (X509Certificate certificate)
- {
- if (certificate == null)
- throw new ArgumentNullException ("certificate");
- if (X509CertificateList == null)
- X509CertificateList = new ArrayList ();
- X509CertificateList.Add (certificate);
- }
-
- public void AddIssuerSerial (string issuerName, string serialNumber)
- {
- if (issuerName == null)
- throw new ArgumentException ("issuerName");
- if (IssuerSerialList == null)
- IssuerSerialList = new ArrayList ();
-
- X509IssuerSerial xis = new X509IssuerSerial (issuerName, serialNumber);
- IssuerSerialList.Add (xis);
- }
-
- public void AddSubjectKeyId (byte[] subjectKeyId)
- {
- if (SubjectKeyIdList == null)
- SubjectKeyIdList = new ArrayList ();
-
- SubjectKeyIdList.Add (subjectKeyId);
- }
-
- [ComVisible (false)]
- public void AddSubjectKeyId (string subjectKeyId)
- {
- if (SubjectKeyIdList == null)
- SubjectKeyIdList = new ArrayList ();
-
- byte[] id = null;
- if (subjectKeyId != null)
- id = Convert.FromBase64String (subjectKeyId);
- SubjectKeyIdList.Add (id);
- }
-
- public void AddSubjectName (string subjectName)
- {
- if (SubjectNameList == null)
- SubjectNameList = new ArrayList ();
-
- SubjectNameList.Add (subjectName);
- }
-
- public override XmlElement GetXml ()
- {
- XmlDocument document = new XmlDocument ();
- XmlElement xel = document.CreateElement (XmlSignature.ElementNames.X509Data, XmlSignature.NamespaceURI);
- // FIXME: hack to match MS implementation
- xel.SetAttribute ("xmlns", XmlSignature.NamespaceURI);
- // <X509IssuerSerial>
- if ((IssuerSerialList != null) && (IssuerSerialList.Count > 0)) {
- foreach (X509IssuerSerial iser in IssuerSerialList) {
- XmlElement isl = document.CreateElement (XmlSignature.ElementNames.X509IssuerSerial, XmlSignature.NamespaceURI);
- XmlElement xin = document.CreateElement (XmlSignature.ElementNames.X509IssuerName, XmlSignature.NamespaceURI);
- xin.InnerText = iser.IssuerName;
- isl.AppendChild (xin);
- XmlElement xsn = document.CreateElement (XmlSignature.ElementNames.X509SerialNumber, XmlSignature.NamespaceURI);
- xsn.InnerText = iser.SerialNumber;
- isl.AppendChild (xsn);
- xel.AppendChild (isl);
- }
- }
- // <X509SKI>
- if ((SubjectKeyIdList != null) && (SubjectKeyIdList.Count > 0)) {
- foreach (byte[] skid in SubjectKeyIdList) {
- XmlElement ski = document.CreateElement (XmlSignature.ElementNames.X509SKI, XmlSignature.NamespaceURI);
- ski.InnerText = Convert.ToBase64String (skid);
- xel.AppendChild (ski);
- }
- }
- // <X509SubjectName>
- if ((SubjectNameList != null) && (SubjectNameList.Count > 0)) {
- foreach (string subject in SubjectNameList) {
- XmlElement sn = document.CreateElement (XmlSignature.ElementNames.X509SubjectName, XmlSignature.NamespaceURI);
- sn.InnerText = subject;
- xel.AppendChild (sn);
- }
- }
- // <X509Certificate>
- if ((X509CertificateList != null) && (X509CertificateList.Count > 0)) {
- foreach (X509Certificate x509 in X509CertificateList) {
- XmlElement cert = document.CreateElement (XmlSignature.ElementNames.X509Certificate, XmlSignature.NamespaceURI);
- cert.InnerText = Convert.ToBase64String (x509.GetRawCertData ());
- xel.AppendChild (cert);
- }
- }
- // only one <X509CRL>
- if (x509crl != null) {
- XmlElement crl = document.CreateElement (XmlSignature.ElementNames.X509CRL, XmlSignature.NamespaceURI);
- crl.InnerText = Convert.ToBase64String (x509crl);
- xel.AppendChild (crl);
- }
- return xel;
- }
-
- public override void LoadXml (XmlElement element)
- {
- if (element == null)
- throw new ArgumentNullException ("element");
-
- if (IssuerSerialList != null)
- IssuerSerialList.Clear ();
- if (SubjectKeyIdList != null)
- SubjectKeyIdList.Clear ();
- if (SubjectNameList != null)
- SubjectNameList.Clear ();
- if (X509CertificateList != null)
- X509CertificateList.Clear ();
- x509crl = null;
-
- if ((element.LocalName != XmlSignature.ElementNames.X509Data) || (element.NamespaceURI != XmlSignature.NamespaceURI))
- throw new CryptographicException ("element");
-
- XmlElement [] xnl = null;
- // <X509IssuerSerial>
- xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509IssuerSerial);
- if (xnl != null) {
- for (int i=0; i < xnl.Length; i++) {
- XmlElement xel = (XmlElement) xnl[i];
- XmlElement issuer = XmlSignature.GetChildElement (xel, XmlSignature.ElementNames.X509IssuerName, XmlSignature.NamespaceURI);
- XmlElement serial = XmlSignature.GetChildElement (xel, XmlSignature.ElementNames.X509SerialNumber, XmlSignature.NamespaceURI);
- AddIssuerSerial (issuer.InnerText, serial.InnerText);
- }
- }
- // <X509SKI>
- xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509SKI);
- if (xnl != null) {
- for (int i=0; i < xnl.Length; i++) {
- byte[] skid = Convert.FromBase64String (xnl[i].InnerXml);
- AddSubjectKeyId (skid);
- }
- }
- // <X509SubjectName>
- xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509SubjectName);
- if (xnl != null) {
- for (int i=0; i < xnl.Length; i++) {
- AddSubjectName (xnl[i].InnerXml);
- }
- }
- // <X509Certificate>
- xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509Certificate);
- if (xnl != null) {
- for (int i=0; i < xnl.Length; i++) {
- byte[] cert = Convert.FromBase64String (xnl[i].InnerXml);
- AddCertificate (new X509Certificate (cert));
- }
- }
- // only one <X509CRL>
- XmlElement x509el = XmlSignature.GetChildElement (element, XmlSignature.ElementNames.X509CRL, XmlSignature.NamespaceURI);
- if (x509el != null) {
- x509crl = Convert.FromBase64String (x509el.InnerXml);
- }
- }
- }
-}
diff --git a/mcs/class/System.Security/System.Security.Cryptography.Xml/Manifest.cs b/mcs/class/System.Security/System.Security.Cryptography.Xml/Manifest.cs
deleted file mode 100644
index d52ea001d43..00000000000
--- a/mcs/class/System.Security/System.Security.Cryptography.Xml/Manifest.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-//
-// Manifest.cs - Manifest implementation for XML Signature
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2004 Novell (http://www.novell.com)
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Collections;
-using System.Xml;
-
-namespace System.Security.Cryptography.Xml {
-
- internal class Manifest {
-
- private ArrayList references;
- private string id;
- private XmlElement element;
-
- public Manifest ()
- {
- references = new ArrayList ();
- }
-
- public Manifest (XmlElement xel) : this ()
- {
- LoadXml (xel);
- }
-
- public string Id {
- get { return id; }
- set {
- element = null;
- id = value;
- }
- }
-
- public ArrayList References {
- get { return references; }
- }
-
- public void AddReference (Reference reference)
- {
- references.Add (reference);
- }
-
- public XmlElement GetXml ()
- {
- if (element != null)
- return element;
-
- XmlDocument document = new XmlDocument ();
- XmlElement xel = document.CreateElement (XmlSignature.ElementNames.SignedInfo, XmlSignature.NamespaceURI);
- if (id != null)
- xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
-
- // we add References afterward so we don't end up with extraneous
- // xmlns="..." in each reference elements.
- foreach (Reference r in references) {
- XmlNode xn = r.GetXml ();
- XmlNode newNode = document.ImportNode (xn, true);
- xel.AppendChild (newNode);
- }
-
- return xel;
- }
-
- private string GetAttribute (XmlElement xel, string attribute)
- {
- XmlAttribute xa = xel.Attributes [attribute];
- return ((xa != null) ? xa.InnerText : null);
- }
-
- public void LoadXml (XmlElement value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
-
- if ((value.LocalName != XmlSignature.ElementNames.Manifest) || (value.NamespaceURI != XmlSignature.NamespaceURI))
- throw new CryptographicException ();
-
- id = GetAttribute (value, XmlSignature.AttributeNames.Id);
-
- for (int i = 0; i < value.ChildNodes.Count; i++) {
- XmlNode n = value.ChildNodes [i];
- if (n.NodeType == XmlNodeType.Element &&
- n.LocalName == XmlSignature.ElementNames.Reference &&
- n.NamespaceURI == XmlSignature.NamespaceURI) {
- Reference r = new Reference ();
- r.LoadXml ((XmlElement) n);
- AddReference (r);
- }
- }
- element = value;
- }
- }
-}
diff --git a/mcs/class/System.Security/System.Security.Cryptography.Xml/Signature.cs b/mcs/class/System.Security/System.Security.Cryptography.Xml/Signature.cs
deleted file mode 100644
index 49e9d3ad991..00000000000
--- a/mcs/class/System.Security/System.Security.Cryptography.Xml/Signature.cs
+++ /dev/null
@@ -1,221 +0,0 @@
-//
-// Signature.cs - Signature implementation for XML Signature
-//
-// Author:
-// Sebastien Pouliot (spouliot@motus.com)
-// Tim Coleman (tim@timcoleman.com)
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) Tim Coleman, 2004
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Collections;
-using System.Security.Cryptography;
-using System.Xml;
-
-namespace System.Security.Cryptography.Xml {
-
- public class Signature {
- static XmlNamespaceManager dsigNsmgr;
-
- static Signature ()
- {
- dsigNsmgr = new XmlNamespaceManager (new NameTable ());
- dsigNsmgr.AddNamespace ("xd", XmlSignature.NamespaceURI);
- }
-
- private ArrayList list;
- private SignedInfo info;
- private KeyInfo key;
- private string id;
- private byte[] signature;
- private XmlElement element;
-
- public Signature ()
- {
- list = new ArrayList ();
- }
-
- public string Id {
- get { return id; }
- set {
- element = null;
- id = value;
- }
- }
-
- public KeyInfo KeyInfo {
- get { return key; }
- set {
- element = null;
- key = value;
- }
- }
-
- public IList ObjectList {
- get { return list; }
- set { list = ArrayList.Adapter (value); }
- }
-
- public byte[] SignatureValue {
- get { return signature; }
- set {
- element = null;
- signature = value;
- }
- }
-
- public SignedInfo SignedInfo {
- get { return info; }
- set {
- element = null;
- info = value;
- }
- }
-
- public void AddObject (DataObject dataObject)
- {
- list.Add (dataObject);
- }
-
- public XmlElement GetXml ()
- {
- return GetXml (null);
- }
-
- internal XmlElement GetXml (XmlDocument document)
- {
- if (element != null)
- return element;
-
- if (info == null)
- throw new CryptographicException ("SignedInfo");
- if (signature == null)
- throw new CryptographicException ("SignatureValue");
-
- if (document == null)
- document = new XmlDocument ();
-
- XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Signature, XmlSignature.NamespaceURI);
- if (id != null)
- xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
-
- XmlNode xn = info.GetXml ();
- XmlNode newNode = document.ImportNode (xn, true);
- xel.AppendChild (newNode);
-
- if (signature != null) {
- XmlElement sv = document.CreateElement (XmlSignature.ElementNames.SignatureValue, XmlSignature.NamespaceURI);
- sv.InnerText = Convert.ToBase64String (signature);
- xel.AppendChild (sv);
- }
-
- if (key != null) {
- xn = key.GetXml ();
- newNode = document.ImportNode (xn, true);
- xel.AppendChild (newNode);
- }
-
- if (list.Count > 0) {
- foreach (DataObject obj in list) {
- xn = obj.GetXml ();
- newNode = document.ImportNode (xn, true);
- xel.AppendChild (newNode);
- }
- }
-
- return xel;
- }
-
- private string GetAttribute (XmlElement xel, string attribute)
- {
- XmlAttribute xa = xel.Attributes [attribute];
- return ((xa != null) ? xa.InnerText : null);
- }
-
- public void LoadXml (XmlElement value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
-
- if ((value.LocalName == XmlSignature.ElementNames.Signature) && (value.NamespaceURI == XmlSignature.NamespaceURI)) {
- id = GetAttribute (value, XmlSignature.AttributeNames.Id);
-
- // LAMESPEC: This library is totally useless against eXtensibly Marked-up document.
- int i = NextElementPos (value.ChildNodes, 0, XmlSignature.ElementNames.SignedInfo, XmlSignature.NamespaceURI, true);
- XmlElement sinfo = (XmlElement) value.ChildNodes [i];
- info = new SignedInfo ();
- info.LoadXml (sinfo);
-
- i = NextElementPos (value.ChildNodes, ++i, XmlSignature.ElementNames.SignatureValue, XmlSignature.NamespaceURI, true);
- XmlElement sigValue = (XmlElement) value.ChildNodes [i];
- signature = Convert.FromBase64String (sigValue.InnerText);
-
- // signature isn't required: <element ref="ds:KeyInfo" minOccurs="0"/>
- i = NextElementPos (value.ChildNodes, ++i, XmlSignature.ElementNames.KeyInfo, XmlSignature.NamespaceURI, false);
- if (i > 0) {
- XmlElement kinfo = (XmlElement) value.ChildNodes [i];
- key = new KeyInfo ();
- key.LoadXml (kinfo);
- }
-
- XmlNodeList xnl = value.SelectNodes ("xd:Object", dsigNsmgr);
- foreach (XmlElement xn in xnl) {
- DataObject obj = new DataObject ();
- obj.LoadXml (xn);
- AddObject (obj);
- }
- }
- else
- throw new CryptographicException ("Malformed element: Signature.");
-
- // if invalid
- if (info == null)
- throw new CryptographicException ("SignedInfo");
- if (signature == null)
- throw new CryptographicException ("SignatureValue");
- }
-
- private int NextElementPos (XmlNodeList nl, int pos, string name, string ns, bool required)
- {
- while (pos < nl.Count) {
- if (nl [pos].NodeType == XmlNodeType.Element) {
- if (nl [pos].LocalName != name || nl [pos].NamespaceURI != ns) {
- if (required)
- throw new CryptographicException ("Malformed element " + name);
- else
- return -2;
- }
- else
- return pos;
- }
- else
- pos++;
- }
- if (required)
- throw new CryptographicException ("Malformed element " + name);
- return -1;
- }
- }
-}
diff --git a/mcs/class/System.Security/System.Security.Cryptography.Xml/SignedInfo.cs b/mcs/class/System.Security/System.Security.Cryptography.Xml/SignedInfo.cs
deleted file mode 100644
index f9d6d9f0048..00000000000
--- a/mcs/class/System.Security/System.Security.Cryptography.Xml/SignedInfo.cs
+++ /dev/null
@@ -1,219 +0,0 @@
-//
-// SignedInfo.cs - SignedInfo implementation for XML Signature
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-// Tim Coleman (tim@timcoleman.com)
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) Tim Coleman, 2004
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System.Collections;
-using System.Runtime.InteropServices;
-using System.Xml;
-
-namespace System.Security.Cryptography.Xml {
-
- public class SignedInfo : ICollection, IEnumerable {
-
- private ArrayList references;
- private string c14nMethod;
- private string id;
- private string signatureMethod;
- private string signatureLength;
- private XmlElement element;
-
- public SignedInfo()
- {
- references = new ArrayList ();
- c14nMethod = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
- }
-
- public string CanonicalizationMethod {
- get { return c14nMethod; }
- set {
- c14nMethod = value;
- element = null;
- }
- }
-
- [ComVisible (false)]
- [MonoTODO]
- public Transform CanonicalizationMethodObject {
- get { throw new NotImplementedException (); }
- }
-
- // documented as not supported (and throwing exception)
- public int Count {
- get { throw new NotSupportedException (); }
- }
-
- public string Id {
- get { return id; }
- set {
- element = null;
- id = value;
- }
- }
-
- // documented as not supported (and throwing exception)
- public bool IsReadOnly {
- get { throw new NotSupportedException (); }
- }
-
- // documented as not supported (and throwing exception)
- public bool IsSynchronized {
- get { throw new NotSupportedException (); }
- }
-
- // Manipulating this array never affects GetXml() when
- // LoadXml() was used.
- // (Actually, there is no way to detect modification.)
- public ArrayList References {
- get { return references; }
- }
-
- public string SignatureLength {
- get { return signatureLength; }
- set {
- element = null;
- signatureLength = value;
- }
- }
-
- public string SignatureMethod {
- get { return signatureMethod; }
- set {
- element = null;
- signatureMethod = value;
- }
- }
-
- // documented as not supported (and throwing exception)
- public object SyncRoot {
- get { throw new NotSupportedException (); }
- }
-
- public void AddReference (Reference reference)
- {
- references.Add (reference);
- }
-
- // documented as not supported (and throwing exception)
- public void CopyTo (Array array, int index)
- {
- throw new NotSupportedException ();
- }
-
- public IEnumerator GetEnumerator ()
- {
- return references.GetEnumerator ();
- }
-
- public XmlElement GetXml ()
- {
- if (element != null)
- return element;
-
- if (signatureMethod == null)
- throw new CryptographicException ("SignatureMethod");
- if (references.Count == 0)
- throw new CryptographicException ("References empty");
-
- XmlDocument document = new XmlDocument ();
- XmlElement xel = document.CreateElement (XmlSignature.ElementNames.SignedInfo, XmlSignature.NamespaceURI);
- if (id != null)
- xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
-
- if (c14nMethod != null) {
- XmlElement c14n = document.CreateElement (XmlSignature.ElementNames.CanonicalizationMethod, XmlSignature.NamespaceURI);
- c14n.SetAttribute (XmlSignature.AttributeNames.Algorithm, c14nMethod);
- xel.AppendChild (c14n);
- }
- if (signatureMethod != null) {
- XmlElement sm = document.CreateElement (XmlSignature.ElementNames.SignatureMethod, XmlSignature.NamespaceURI);
- sm.SetAttribute (XmlSignature.AttributeNames.Algorithm, signatureMethod);
- if (signatureLength != null) {
- XmlElement hmac = document.CreateElement (XmlSignature.ElementNames.HMACOutputLength, XmlSignature.NamespaceURI);
- hmac.InnerText = signatureLength;
- sm.AppendChild (hmac);
- }
- xel.AppendChild (sm);
- }
-
- // This check is only done when element is created here.
- if (references.Count == 0)
- throw new CryptographicException ("At least one Reference element is required in SignedInfo.");
-
- // we add References afterward so we don't end up with extraneous
- // xmlns="..." in each reference elements.
- foreach (Reference r in references) {
- XmlNode xn = r.GetXml ();
- XmlNode newNode = document.ImportNode (xn, true);
- xel.AppendChild (newNode);
- }
-
- return xel;
- }
-
- private string GetAttribute (XmlElement xel, string attribute)
- {
- XmlAttribute xa = xel.Attributes [attribute];
- return ((xa != null) ? xa.InnerText : null);
- }
-
- public void LoadXml (XmlElement value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
-
- if ((value.LocalName != XmlSignature.ElementNames.SignedInfo) || (value.NamespaceURI != XmlSignature.NamespaceURI))
- throw new CryptographicException ();
-
- id = GetAttribute (value, XmlSignature.AttributeNames.Id);
- c14nMethod = XmlSignature.GetAttributeFromElement (value, XmlSignature.AttributeNames.Algorithm, XmlSignature.ElementNames.CanonicalizationMethod);
-
- XmlElement sm = XmlSignature.GetChildElement (value, XmlSignature.ElementNames.SignatureMethod, XmlSignature.NamespaceURI);
- if (sm != null) {
- signatureMethod = sm.GetAttribute (XmlSignature.AttributeNames.Algorithm);
- XmlElement length = XmlSignature.GetChildElement (sm, XmlSignature.ElementNames.HMACOutputLength, XmlSignature.NamespaceURI);
- if (length != null) {
- signatureLength = length.InnerText;
- }
- }
-
- for (int i = 0; i < value.ChildNodes.Count; i++) {
- XmlNode n = value.ChildNodes [i];
- if (n.NodeType == XmlNodeType.Element &&
- n.LocalName == XmlSignature.ElementNames.Reference &&
- n.NamespaceURI == XmlSignature.NamespaceURI) {
- Reference r = new Reference ();
- r.LoadXml ((XmlElement) n);
- AddReference (r);
- }
- }
- element = value;
- }
- }
-}
diff --git a/mcs/class/System.Security/System.Security.Cryptography.Xml/SignedXml.cs b/mcs/class/System.Security/System.Security.Cryptography.Xml/SignedXml.cs
index 958f9138365..15e50ca5fcf 100644
--- a/mcs/class/System.Security/System.Security.Cryptography.Xml/SignedXml.cs
+++ b/mcs/class/System.Security/System.Security.Cryptography.Xml/SignedXml.cs
@@ -1,48 +1,57 @@
-//
-// SignedXml.cs - SignedXml implementation for XML Signature
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-// Atsushi Enomoto <atsushi@ximian.com>
-// Tim Coleman <tim@timcoleman.com>
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) Tim Coleman, 2004
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
using System.Collections;
-using System.IO;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using System.Security.Cryptography;
-using System.Security.Policy;
-using System.Net;
-using System.Text;
-using System.Xml;
using System.Security.Cryptography.X509Certificates;
+using System.Xml;
namespace System.Security.Cryptography.Xml {
-
public class SignedXml {
+ /// <internalonly />
+ protected Signature m_signature;
+ /// <internalonly />
+ protected string m_strSigningKeyName;
+
+ private AsymmetricAlgorithm _signingKey;
+ private XmlDocument _containingDocument;
+ private IEnumerator _keyInfoEnum;
+ private X509Certificate2Collection _x509Collection;
+ private IEnumerator _x509Enum;
+
+ private bool[] _refProcessed;
+ private int[] _refLevelCache;
+
+ internal XmlResolver _xmlResolver;
+ internal XmlElement _context;
+ private bool _bResolverSet;
+
+ private Func<SignedXml, bool> _signatureFormatValidator = DefaultSignatureFormatValidator;
+ private Collection<string> _safeCanonicalizationMethods;
+
+ // Built in canonicalization algorithm URIs
+ private static IList<string> s_knownCanonicalizationMethods;
+ // Built in transform algorithm URIs (excluding canonicalization URIs)
+ private static IList<string> s_defaultSafeTransformMethods;
+
+ // additional HMAC Url identifiers
+ private const string XmlDsigMoreHMACMD5Url = "http://www.w3.org/2001/04/xmldsig-more#hmac-md5";
+ private const string XmlDsigMoreHMACSHA256Url = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256";
+ private const string XmlDsigMoreHMACSHA384Url = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384";
+ private const string XmlDsigMoreHMACSHA512Url = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512";
+ private const string XmlDsigMoreHMACRIPEMD160Url = "http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160";
+
+ // defines the XML encryption processing rules
+ private EncryptedXml _exml;
+
+ //
+ // public constant Url identifiers most frequently used within the XML Signature classes
+ //
+
public const string XmlDsigNamespaceUrl = "http://www.w3.org/2000/09/xmldsig#";
public const string XmlDsigMinimalCanonicalizationUrl = "http://www.w3.org/2000/09/xmldsig#minimal";
public const string XmlDsigCanonicalizationUrl = XmlDsigC14NTransformUrl;
@@ -63,6 +72,9 @@ namespace System.Security.Cryptography.Xml {
public const string XmlDsigSHA512Url = "http://www.w3.org/2001/04/xmlenc#sha512";
public const string XmlDsigRSASHA512Url = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";
+ internal static readonly string XmlDsigDigestDefault = XmlDsigSHA256Url;
+ internal static readonly string XmlDsigRSADefault = XmlDsigRSASHA256Url;
+
public const string XmlDsigC14NTransformUrl = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
public const string XmlDsigC14NWithCommentsTransformUrl = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments";
public const string XmlDsigExcC14NTransformUrl = "http://www.w3.org/2001/10/xml-exc-c14n#";
@@ -74,91 +86,50 @@ namespace System.Security.Cryptography.Xml {
public const string XmlDecryptionTransformUrl = "http://www.w3.org/2002/07/decrypt#XML";
public const string XmlLicenseTransformUrl = "urn:mpeg:mpeg21:2003:01-REL-R-NS:licenseTransform";
- private EncryptedXml encryptedXml;
-
- protected Signature m_signature;
- private AsymmetricAlgorithm key;
- protected string m_strSigningKeyName;
- private XmlDocument envdoc;
- private IEnumerator pkEnumerator;
- private XmlElement signatureElement;
- private Hashtable hashes;
- // FIXME: enable it after CAS implementation
- internal XmlResolver _xmlResolver = new XmlUrlResolver ();
- private bool _bResolverSet = true;
- internal XmlElement _context;
- private ArrayList manifests;
- private IEnumerator _x509Enumerator;
-
- private static readonly char [] whitespaceChars = new char [] {' ', '\r', '\n', '\t'};
+ //
+ // public constructors
+ //
public SignedXml ()
{
- m_signature = new Signature ();
- m_signature.SignedInfo = new SignedInfo ();
- hashes = new Hashtable (2); // 98% SHA1 for now
- _context = null;
+ Initialize (null);
}
- public SignedXml (XmlDocument document) : this ()
+ public SignedXml (XmlDocument document)
{
if (document == null)
- throw new ArgumentNullException ("document");
- envdoc = document;
- _context = document.DocumentElement;
+ throw new ArgumentNullException (nameof (document));
+
+ Initialize (document.DocumentElement);
}
- public SignedXml (XmlElement elem) : this ()
+ public SignedXml (XmlElement elem)
{
if (elem == null)
- throw new ArgumentNullException ("elem");
- envdoc = new XmlDocument ();
- _context = elem;
- envdoc.LoadXml (elem.OuterXml);
- }
-
- [ComVisible (false)]
- public EncryptedXml EncryptedXml {
- get { return encryptedXml; }
- set { encryptedXml = value; }
- }
-
- public KeyInfo KeyInfo {
- get {
- if (m_signature.KeyInfo == null)
- m_signature.KeyInfo = new KeyInfo ();
- return m_signature.KeyInfo;
- }
- set { m_signature.KeyInfo = value; }
- }
-
- public Signature Signature {
- get { return m_signature; }
- }
-
- public string SignatureLength {
- get { return m_signature.SignedInfo.SignatureLength; }
+ throw new ArgumentNullException (nameof (elem));
+
+ Initialize (elem);
}
- public string SignatureMethod {
- get { return m_signature.SignedInfo.SignatureMethod; }
- }
+ private void Initialize (XmlElement element)
+ {
+ _containingDocument = (element == null ? null : element.OwnerDocument);
+ _context = element;
+ m_signature = new Signature ();
+ m_signature.SignedXml = this;
+ m_signature.SignedInfo = new SignedInfo ();
+ _signingKey = null;
- public byte[] SignatureValue {
- get { return m_signature.SignatureValue; }
+ _safeCanonicalizationMethods = new Collection<string> (KnownCanonicalizationMethods);
}
- public SignedInfo SignedInfo {
- get { return m_signature.SignedInfo; }
- }
+ //
+ // public properties
+ //
- public AsymmetricAlgorithm SigningKey {
- get { return key; }
- set { key = value; }
- }
-
- // NOTE: CryptoAPI related ? documented as fx internal
- public string SigningKeyName {
+ /// <internalonly />
+ public string SigningKeyName
+ {
get { return m_strSigningKeyName; }
set { m_strSigningKeyName = value; }
}
@@ -179,483 +150,221 @@ namespace System.Security.Cryptography.Xml {
get { return _bResolverSet; }
}
- public void AddObject (DataObject dataObject)
+ public Func<SignedXml, bool> SignatureFormatValidator
{
- m_signature.AddObject (dataObject);
+ get { return _signatureFormatValidator; }
+ set { _signatureFormatValidator = value; }
}
- public void AddReference (Reference reference)
+ public Collection<string> SafeCanonicalizationMethods
{
- if (reference == null)
- throw new ArgumentNullException ("reference");
- m_signature.SignedInfo.AddReference (reference);
+ get { return _safeCanonicalizationMethods; }
}
- private Stream ApplyTransform (Transform t, XmlDocument input)
+ public AsymmetricAlgorithm SigningKey
{
- // These transformer modify input document, which should
- // not affect to the input itself.
- if (t is XmlDsigXPathTransform
- || t is XmlDsigEnvelopedSignatureTransform
- || t is XmlDecryptionTransform
- )
- input = (XmlDocument) input.Clone ();
-
- t.LoadInput (input);
-
- if (t is XmlDsigEnvelopedSignatureTransform)
- // It returns XmlDocument for XmlDocument input.
- return CanonicalizeOutput (t.GetOutput ());
-
- object obj = t.GetOutput ();
- if (obj is Stream)
- return (Stream) obj;
- else if (obj is XmlDocument) {
- MemoryStream ms = new MemoryStream ();
- XmlTextWriter xtw = new XmlTextWriter (ms, Encoding.UTF8);
- ((XmlDocument) obj).WriteTo (xtw);
-
- xtw.Flush ();
+ get { return _signingKey; }
+ set { _signingKey = value; }
+ }
- // Rewind to the start of the stream
- ms.Position = 0;
- return ms;
- }
- else if (obj == null) {
- throw new NotImplementedException ("This should not occur. Transform is " + t + ".");
- }
- else {
- // e.g. XmlDsigXPathTransform returns XmlNodeList
- return CanonicalizeOutput (obj);
+ public EncryptedXml EncryptedXml
+ {
+ get
+ {
+ if (_exml == null)
+ _exml = new EncryptedXml (_containingDocument); // default processing rules
+
+ return _exml;
}
+
+ set { _exml = value; }
}
- private Stream CanonicalizeOutput (object obj)
+ public Signature Signature
{
- Transform c14n = GetC14NMethod ();
- c14n.LoadInput (obj);
- return (Stream) c14n.GetOutput ();
+ get { return m_signature; }
}
- private XmlDocument GetManifest (Reference r)
+ public SignedInfo SignedInfo
{
- XmlDocument doc = new XmlDocument ();
- doc.PreserveWhitespace = true;
-
- if (r.Uri [0] == '#') {
- // local manifest
- if (signatureElement != null) {
- XmlElement xel = GetIdElement (signatureElement.OwnerDocument, r.Uri.Substring (1));
- if (xel == null)
- throw new CryptographicException ("Manifest targeted by Reference was not found: " + r.Uri.Substring (1));
- doc.AppendChild (doc.ImportNode (xel, true));
- FixupNamespaceNodes (xel, doc.DocumentElement, false);
- }
- }
- else if (_xmlResolver != null) {
- // TODO: need testing
- Stream s = (Stream) _xmlResolver.GetEntity (new Uri (r.Uri), null, typeof (Stream));
- doc.Load (s);
- }
-
- if (doc.FirstChild != null) {
- // keep a copy of the manifests to check their references later
- if (manifests == null)
- manifests = new ArrayList ();
- manifests.Add (doc);
-
- return doc;
- }
- return null;
+ get { return m_signature.SignedInfo; }
}
- private void FixupNamespaceNodes (XmlElement src, XmlElement dst, bool ignoreDefault)
+ public string SignatureMethod
{
- // add namespace nodes
- foreach (XmlAttribute attr in src.SelectNodes ("namespace::*")) {
- if (attr.LocalName == "xml")
- continue;
- if (ignoreDefault && attr.LocalName == "xmlns")
- continue;
- dst.SetAttributeNode (dst.OwnerDocument.ImportNode (attr, true) as XmlAttribute);
- }
+ get { return m_signature.SignedInfo.SignatureMethod; }
}
- private byte[] GetReferenceHash (Reference r, bool check_hmac)
+ public string SignatureLength
{
- Stream s = null;
- XmlDocument doc = null;
- if (r.Uri == String.Empty) {
- doc = envdoc;
- }
- else if (r.Type == XmlSignature.Uri.Manifest) {
- doc = GetManifest (r);
- }
- else {
- doc = new XmlDocument ();
- doc.PreserveWhitespace = true;
- string objectName = null;
-
- if (r.Uri.StartsWith ("#xpointer")) {
- string uri = string.Join ("", r.Uri.Substring (9).Split (whitespaceChars));
- if (uri.Length < 2 || uri [0] != '(' || uri [uri.Length - 1] != ')')
- // FIXME: how to handle invalid xpointer?
- uri = String.Empty;
- else
- uri = uri.Substring (1, uri.Length - 2);
- if (uri == "/")
- doc = envdoc;
- else if (uri.Length > 6 && uri.StartsWith ("id(") && uri [uri.Length - 1] == ')')
- // id('foo'), id("foo")
- objectName = uri.Substring (4, uri.Length - 6);
- }
- else if (r.Uri [0] == '#') {
- objectName = r.Uri.Substring (1);
- }
- else if (_xmlResolver != null) {
- // TODO: test but doc says that Resolver = null -> no access
- try {
- // no way to know if valid without throwing an exception
- Uri uri = new Uri (r.Uri);
- s = (Stream) _xmlResolver.GetEntity (uri, null, typeof (Stream));
- }
- catch {
- // may still be a local file (and maybe not xml)
- s = File.OpenRead (r.Uri);
- }
- }
- if (objectName != null) {
- XmlElement found = null;
- foreach (DataObject obj in m_signature.ObjectList) {
- if (obj.Id == objectName) {
- found = obj.GetXml ();
- found.SetAttribute ("xmlns", SignedXml.XmlDsigNamespaceUrl);
- doc.AppendChild (doc.ImportNode (found, true));
- // FIXME: there should be theoretical justification of copying namespace declaration nodes this way.
- foreach (XmlNode n in found.ChildNodes)
- // Do not copy default namespace as it must be xmldsig namespace for "Object" element.
- if (n.NodeType == XmlNodeType.Element)
- FixupNamespaceNodes (n as XmlElement, doc.DocumentElement, true);
- break;
- }
- }
- if (found == null && envdoc != null) {
- found = GetIdElement (envdoc, objectName);
- if (found != null) {
- doc.AppendChild (doc.ImportNode (found, true));
- FixupNamespaceNodes (found, doc.DocumentElement, false);
- }
- }
- if (found == null)
- throw new CryptographicException (String.Format ("Malformed reference object: {0}", objectName));
- }
- }
-
- if (r.TransformChain.Count > 0) {
- foreach (Transform t in r.TransformChain) {
- if (s == null) {
- s = ApplyTransform (t, doc);
- }
- else {
- t.LoadInput (s);
- object o = t.GetOutput ();
- if (o is Stream)
- s = (Stream) o;
- else
- s = CanonicalizeOutput (o);
- }
- }
- }
- else if (s == null) {
- // we must not C14N references from outside the document
- // e.g. non-xml documents
- if (r.Uri [0] != '#') {
- s = new MemoryStream ();
- doc.Save (s);
- }
- else {
- // apply default C14N transformation
- s = ApplyTransform (new XmlDsigC14NTransform (), doc);
- }
- }
- HashAlgorithm digest = GetHash (r.DigestMethod, check_hmac);
- return (digest == null) ? null : digest.ComputeHash (s);
+ get { return m_signature.SignedInfo.SignatureLength; }
}
- private void DigestReferences ()
+ public byte[] SignatureValue
{
- // we must tell each reference which hash algorithm to use
- // before asking for the SignedInfo XML !
- foreach (Reference r in m_signature.SignedInfo.References) {
- // assume SHA-1 if nothing is specified
- if (r.DigestMethod == null)
- r.DigestMethod = XmlDsigSHA1Url;
- r.DigestValue = GetReferenceHash (r, false);
- }
+ get { return m_signature.SignatureValue; }
}
- private Transform GetC14NMethod ()
+ public KeyInfo KeyInfo
{
- Transform t = (Transform) CryptoConfig.CreateFromName (m_signature.SignedInfo.CanonicalizationMethod);
- if (t == null)
- throw new CryptographicException ("Unknown Canonicalization Method {0}", m_signature.SignedInfo.CanonicalizationMethod);
- return t;
+ get { return m_signature.KeyInfo; }
+ set { m_signature.KeyInfo = value; }
}
- private Stream SignedInfoTransformed ()
+ public XmlElement GetXml ()
{
- Transform t = GetC14NMethod ();
+ // If we have a document context, then return a signature element in this context
+ if (_containingDocument != null)
+ return m_signature.GetXml (_containingDocument);
+ else
+ return m_signature.GetXml ();
+ }
- if (signatureElement == null) {
- // when creating signatures
- XmlDocument doc = new XmlDocument ();
- doc.PreserveWhitespace = true;
- doc.LoadXml (m_signature.SignedInfo.GetXml ().OuterXml);
- if (envdoc != null)
- foreach (XmlAttribute attr in envdoc.DocumentElement.SelectNodes ("namespace::*")) {
- if (attr.LocalName == "xml")
- continue;
- if (attr.Prefix == doc.DocumentElement.Prefix)
- continue;
- doc.DocumentElement.SetAttributeNode (doc.ImportNode (attr, true) as XmlAttribute);
- }
- t.LoadInput (doc);
- }
- else {
- // when verifying signatures
- // TODO - check m_signature.SignedInfo.Id
- XmlElement el = signatureElement.GetElementsByTagName (XmlSignature.ElementNames.SignedInfo, XmlSignature.NamespaceURI) [0] as XmlElement;
- StringWriter sw = new StringWriter ();
- XmlTextWriter xtw = new XmlTextWriter (sw);
- xtw.WriteStartElement (el.Prefix, el.LocalName, el.NamespaceURI);
-
- // context namespace nodes (except for "xmlns:xml")
- XmlNodeList nl = el.SelectNodes ("namespace::*");
- foreach (XmlAttribute attr in nl) {
- if (attr.ParentNode == el)
- continue;
- if (attr.LocalName == "xml")
- continue;
- if (attr.Prefix == el.Prefix)
- continue;
- attr.WriteTo (xtw);
- }
- foreach (XmlNode attr in el.Attributes)
- attr.WriteTo (xtw);
- foreach (XmlNode n in el.ChildNodes)
- n.WriteTo (xtw);
+ public void LoadXml (XmlElement value)
+ {
+ if (value == null)
+ throw new ArgumentNullException (nameof (value));
- xtw.WriteEndElement ();
- byte [] si = Encoding.UTF8.GetBytes (sw.ToString ());
+ m_signature.LoadXml (value);
- MemoryStream ms = new MemoryStream ();
- ms.Write (si, 0, si.Length);
- ms.Position = 0;
+ if (_context == null)
+ _context = value;
- t.LoadInput (ms);
- }
- // C14N and C14NWithComments always return a Stream in GetOutput
- return (Stream) t.GetOutput ();
+ _bCacheValid = false;
}
- // reuse hash - most document will always use the same hash
- private HashAlgorithm GetHash (string algorithm, bool check_hmac)
- {
- HashAlgorithm hash = (HashAlgorithm) hashes [algorithm];
- if (hash == null) {
- hash = HashAlgorithm.Create (algorithm);
- if (hash == null)
- throw new CryptographicException ("Unknown hash algorithm: {0}", algorithm);
- hashes.Add (algorithm, hash);
- // now ready to be used
- }
- else {
- // important before reusing an hash object
- hash.Initialize ();
- }
- // we can sign using any hash algorith, including HMAC, but we can only verify hash (MS compatibility)
- if (check_hmac && (hash is KeyedHashAlgorithm))
- return null;
- return hash;
- }
+ //
+ // public methods
+ //
- public bool CheckSignature ()
+ public void AddReference (Reference reference)
{
- return (CheckSignatureInternal (null) != null);
+ m_signature.SignedInfo.AddReference (reference);
}
- private bool CheckReferenceIntegrity (ArrayList referenceList)
+ public void AddObject (DataObject dataObject)
{
- if (referenceList == null)
- return false;
-
- // check digest (hash) for every reference
- foreach (Reference r in referenceList) {
- // stop at first broken reference
- byte[] hash = GetReferenceHash (r, true);
- if (! Compare (r.DigestValue, hash))
- return false;
- }
- return true;
+ m_signature.AddObject (dataObject);
}
- public bool CheckSignature (AsymmetricAlgorithm key)
+ public bool CheckSignature ()
{
- if (key == null)
- throw new ArgumentNullException ("key");
- return (CheckSignatureInternal (key) != null);
+ AsymmetricAlgorithm signingKey;
+ return CheckSignatureReturningKey (out signingKey);
}
- private AsymmetricAlgorithm CheckSignatureInternal (AsymmetricAlgorithm key)
+ public bool CheckSignatureReturningKey (out AsymmetricAlgorithm signingKey)
{
- pkEnumerator = null;
+ SignedXmlDebugLog.LogBeginSignatureVerification (this, _context);
- if (key != null) {
- // check with supplied key
- if (!CheckSignatureWithKey (key))
- return null;
- } else {
- if (Signature.KeyInfo == null)
- return null;
- // no supplied key, iterates all KeyInfo
- while ((key = GetPublicKey ()) != null) {
- if (CheckSignatureWithKey (key)) {
- break;
- }
- }
- pkEnumerator = null;
- if (key == null)
- return null;
- }
+ signingKey = null;
+ bool bRet = false;
+ AsymmetricAlgorithm key = null;
- // some parts may need to be downloaded
- // so where doing it last
- if (!CheckReferenceIntegrity (m_signature.SignedInfo.References))
- return null;
+ if (!CheckSignatureFormat ())
+ return false;
- if (manifests != null) {
- // do not use foreach as a manifest could contain manifests...
- for (int i=0; i < manifests.Count; i++) {
- Manifest manifest = new Manifest ((manifests [i] as XmlDocument).DocumentElement);
- if (! CheckReferenceIntegrity (manifest.References))
- return null;
+ do {
+ key = GetPublicKey ();
+ if (key != null) {
+ bRet = CheckSignature (key);
+ SignedXmlDebugLog.LogVerificationResult (this, key, bRet);
}
- }
- return key;
+ } while (key != null && bRet == false);
+
+ signingKey = key;
+ return bRet;
}
- // Is the signature (over SignedInfo) valid ?
- private bool CheckSignatureWithKey (AsymmetricAlgorithm key)
+ public bool CheckSignature (AsymmetricAlgorithm key)
{
- if (key == null)
+ if (!CheckSignatureFormat ())
return false;
- SignatureDescription sd = (SignatureDescription) CryptoConfig.CreateFromName (m_signature.SignedInfo.SignatureMethod);
- if (sd == null)
+ if (!CheckSignedInfo (key)) {
+ SignedXmlDebugLog.LogVerificationFailure (this, SR.Log_VerificationFailed_SignedInfo);
return false;
+ }
- AsymmetricSignatureDeformatter verifier = (AsymmetricSignatureDeformatter) CryptoConfig.CreateFromName (sd.DeformatterAlgorithm);
- if (verifier == null)
+ // Now is the time to go through all the references and see if their DigestValues are good
+ if (!CheckDigestedReferences ()) {
+ SignedXmlDebugLog.LogVerificationFailure (this, SR.Log_VerificationFailed_References);
return false;
+ }
- try {
- verifier.SetKey (key);
- verifier.SetHashAlgorithm (sd.DigestAlgorithm);
+ SignedXmlDebugLog.LogVerificationResult (this, key, true);
+ return true;
+ }
- HashAlgorithm hash = GetHash (sd.DigestAlgorithm, true);
- // get the hash of the C14N SignedInfo element
- MemoryStream ms = (MemoryStream) SignedInfoTransformed ();
+ public bool CheckSignature (KeyedHashAlgorithm macAlg)
+ {
+ if (!CheckSignatureFormat ())
+ return false;
- byte[] digest = hash.ComputeHash (ms);
- return verifier.VerifySignature (digest, m_signature.SignatureValue);
+ if (!CheckSignedInfo (macAlg)) {
+ SignedXmlDebugLog.LogVerificationFailure (this, SR.Log_VerificationFailed_SignedInfo);
+ return false;
}
- catch {
- // e.g. SignatureMethod != AsymmetricAlgorithm type
+
+ if (!CheckDigestedReferences ()) {
+ SignedXmlDebugLog.LogVerificationFailure (this, SR.Log_VerificationFailed_References);
return false;
- }
+ }
+
+ SignedXmlDebugLog.LogVerificationResult (this, macAlg, true);
+ return true;
}
- private bool Compare (byte[] expected, byte[] actual)
+ public bool CheckSignature (X509Certificate2 certificate, bool verifySignatureOnly)
{
- bool result = ((expected != null) && (actual != null));
- if (result) {
- int l = expected.Length;
- result = (l == actual.Length);
- if (result) {
- for (int i=0; i < l; i++) {
- if (expected[i] != actual[i])
+ if (!verifySignatureOnly) {
+ // Check key usages to make sure it is good for signing.
+ foreach (X509Extension extension in certificate.Extensions) {
+ if (string.Compare (extension.Oid.Value, "2.5.29.15" /* szOID_KEY_USAGE */, StringComparison.OrdinalIgnoreCase) == 0) {
+ X509KeyUsageExtension keyUsage = new X509KeyUsageExtension ();
+ keyUsage.CopyFrom (extension);
+ SignedXmlDebugLog.LogVerifyKeyUsage (this, certificate, keyUsage);
+
+ bool validKeyUsage = (keyUsage.KeyUsages & X509KeyUsageFlags.DigitalSignature) != 0 ||
+ (keyUsage.KeyUsages & X509KeyUsageFlags.NonRepudiation) != 0;
+
+ if (!validKeyUsage) {
+ SignedXmlDebugLog.LogVerificationFailure (this, SR.Log_VerificationFailed_X509KeyUsage);
return false;
+ }
+ break;
}
}
- }
- return result;
- }
- public bool CheckSignature (KeyedHashAlgorithm macAlg)
- {
- if (macAlg == null)
- throw new ArgumentNullException ("macAlg");
+ // Do the chain verification to make sure the certificate is valid.
+ X509Chain chain = new X509Chain ();
+ chain.ChainPolicy.ExtraStore.AddRange (BuildBagOfCerts());
+ bool chainVerified = chain.Build (certificate);
+ SignedXmlDebugLog.LogVerifyX509Chain (this, chain, certificate);
- pkEnumerator = null;
-
- // Is the signature (over SignedInfo) valid ?
- Stream s = SignedInfoTransformed ();
- if (s == null)
- return false;
-
- byte[] actual = macAlg.ComputeHash (s);
- // HMAC signature may be partial and specified by <HMACOutputLength>
- if (m_signature.SignedInfo.SignatureLength != null) {
- int length = Int32.Parse (m_signature.SignedInfo.SignatureLength);
- // we only support signatures with a multiple of 8 bits
- // and the value must match the signature length
- if ((length & 7) != 0)
- throw new CryptographicException ("Signature length must be a multiple of 8 bits.");
-
- // SignatureLength is in bits (and we works on bytes, only in multiple of 8 bits)
- // and both values must match for a signature to be valid
- length >>= 3;
- if (length != m_signature.SignatureValue.Length)
- throw new CryptographicException ("Invalid signature length.");
-
- // is the length "big" enough to make the signature meaningful ?
- // we use a minimum of 80 bits (10 bytes) or half the HMAC normal output length
- // e.g. HMACMD5 output 128 bits but our minimum is 80 bits (not 64 bits)
- int minimum = Math.Max (10, actual.Length / 2);
- if (length < minimum)
- throw new CryptographicException ("HMAC signature is too small");
-
- if (length < actual.Length) {
- byte[] trunked = new byte [length];
- Buffer.BlockCopy (actual, 0, trunked, 0, length);
- actual = trunked;
+ if (!chainVerified) {
+ SignedXmlDebugLog.LogVerificationFailure (this, SR.Log_VerificationFailed_X509Chain);
+ return false;
}
}
- if (Compare (m_signature.SignatureValue, actual)) {
- // some parts may need to be downloaded
- // so where doing it last
- return CheckReferenceIntegrity (m_signature.SignedInfo.References);
+ using (AsymmetricAlgorithm publicKey = Utils.GetAnyPublicKey (certificate)) {
+ if (!CheckSignature (publicKey))
+ return false;
}
- return false;
- }
- [MonoTODO]
- [ComVisible (false)]
- public bool CheckSignature (X509Certificate2 certificate, bool verifySignatureOnly)
- {
- throw new NotImplementedException ();
+ SignedXmlDebugLog.LogVerificationResult (this, certificate, true);
+ return true;
}
- public bool CheckSignatureReturningKey (out AsymmetricAlgorithm signingKey)
+ public void ComputeSignature ()
{
- signingKey = CheckSignatureInternal (null);
- return (signingKey != null);
- }
+ SignedXmlDebugLog.LogBeginSignatureComputation (this, _context);
- public void ComputeSignature ()
- {
- DigestReferences ();
+ BuildDigestedReferences ();
+
+ // Load the key
+ AsymmetricAlgorithm key = SigningKey;
if (key == null)
throw new CryptographicException (SR.Cryptography_Xml_LoadKeyFailed);
@@ -665,86 +374,159 @@ namespace System.Security.Cryptography.Xml {
if (key is DSA) {
SignedInfo.SignatureMethod = XmlDsigDSAUrl;
} else if (key is RSA) {
- // Default to RSA-SHA1
- SignedInfo.SignatureMethod = XmlDsigRSASHA1Url;
+ if (SignedInfo.SignatureMethod == null)
+ SignedInfo.SignatureMethod = XmlDsigRSADefault;
} else {
throw new CryptographicException (SR.Cryptography_Xml_CreatedKeyFailed);
}
}
// See if there is a signature description class defined in the Config file
- SignatureDescription signatureDescription = CryptoConfig.CreateFromName (SignedInfo.SignatureMethod) as SignatureDescription;
+ SignatureDescription signatureDescription = CryptoHelpers.CreateFromName (SignedInfo.SignatureMethod) as SignatureDescription;
if (signatureDescription == null)
throw new CryptographicException (SR.Cryptography_Xml_SignatureDescriptionNotCreated);
-
HashAlgorithm hashAlg = signatureDescription.CreateDigest ();
if (hashAlg == null)
throw new CryptographicException (SR.Cryptography_Xml_CreateHashAlgorithmFailed);
-
- byte[] hashvalue = hashAlg.ComputeHash (SignedInfoTransformed ());
+ byte[] hashvalue = GetC14NDigest (hashAlg);
AsymmetricSignatureFormatter asymmetricSignatureFormatter = signatureDescription.CreateFormatter (key);
+ SignedXmlDebugLog.LogSigning (this, key, signatureDescription, hashAlg, asymmetricSignatureFormatter);
m_signature.SignatureValue = asymmetricSignatureFormatter.CreateSignature (hashAlg);
}
- public void ComputeSignature (KeyedHashAlgorithm macAlg)
+ public void ComputeSignature (KeyedHashAlgorithm macAlg)
{
if (macAlg == null)
- throw new ArgumentNullException ("macAlg");
-
- string method = null;
-
- if (macAlg is HMACSHA1) {
- method = XmlDsigHMACSHA1Url;
- } else if (macAlg is HMACSHA256) {
- method = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256";
- } else if (macAlg is HMACSHA384) {
- method = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384";
- } else if (macAlg is HMACSHA512) {
- method = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512";
- } else if (macAlg is HMACRIPEMD160) {
- method = "http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160";
+ throw new ArgumentNullException (nameof (macAlg));
+
+ HMAC hash = macAlg as HMAC;
+ if (hash == null)
+ throw new CryptographicException (SR.Cryptography_Xml_SignatureMethodKeyMismatch);
+
+ int signatureLength;
+ if (m_signature.SignedInfo.SignatureLength == null)
+ signatureLength = hash.HashSize;
+ else
+ signatureLength = Convert.ToInt32 (m_signature.SignedInfo.SignatureLength, null);
+ // signatureLength should be less than hash size
+ if (signatureLength < 0 || signatureLength > hash.HashSize)
+ throw new CryptographicException (SR.Cryptography_Xml_InvalidSignatureLength);
+ if (signatureLength % 8 != 0)
+ throw new CryptographicException (SR.Cryptography_Xml_InvalidSignatureLength2);
+
+ BuildDigestedReferences ();
+ switch (hash.HashName) {
+ case "SHA1":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigHMACSHA1Url;
+ break;
+ case "SHA256":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigMoreHMACSHA256Url;
+ break;
+ case "SHA384":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigMoreHMACSHA384Url;
+ break;
+ case "SHA512":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigMoreHMACSHA512Url;
+ break;
+ case "MD5":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigMoreHMACMD5Url;
+ break;
+ case "RIPEMD160":
+ SignedInfo.SignatureMethod = SignedXml.XmlDsigMoreHMACRIPEMD160Url;
+ break;
+ default:
+ throw new CryptographicException (SR.Cryptography_Xml_SignatureMethodKeyMismatch);
}
- if (method == null)
- throw new CryptographicException ("unsupported algorithm");
+ byte[] hashValue = GetC14NDigest (hash);
- DigestReferences ();
- m_signature.SignedInfo.SignatureMethod = method;
- m_signature.SignatureValue = macAlg.ComputeHash (SignedInfoTransformed ());
+ SignedXmlDebugLog.LogSigning (this, hash);
+ m_signature.SignatureValue = new byte [signatureLength / 8];
+ Buffer.BlockCopy (hashValue, 0, m_signature.SignatureValue, 0, signatureLength / 8);
}
- public virtual XmlElement GetIdElement (XmlDocument document, string idValue)
+ //
+ // virtual methods
+ //
+
+ protected virtual AsymmetricAlgorithm GetPublicKey ()
{
- if ((document == null) || (idValue == null))
- return null;
+ if (KeyInfo == null)
+ throw new CryptographicException (SR.Cryptography_Xml_KeyInfoRequired);
+
+ if (_x509Enum != null) {
+ AsymmetricAlgorithm key = GetNextCertificatePublicKey ();
+ if (key != null)
+ return key;
+ }
- // this works only if there's a DTD or XSD available to define the ID
- XmlElement xel = document.GetElementById (idValue);
- if (xel == null) {
- // search an "undefined" ID
- xel = (XmlElement) document.SelectSingleNode ("//*[@Id='" + idValue + "']");
- if (xel == null) {
- xel = (XmlElement) document.SelectSingleNode ("//*[@ID='" + idValue + "']");
- if (xel == null) {
- xel = (XmlElement) document.SelectSingleNode ("//*[@id='" + idValue + "']");
+ if (_keyInfoEnum == null)
+ _keyInfoEnum = KeyInfo.GetEnumerator ();
+
+ // In our implementation, we move to the next KeyInfo clause which is an RSAKeyValue, DSAKeyValue or KeyInfoX509Data
+ while (_keyInfoEnum.MoveNext()) {
+ RSAKeyValue rsaKeyValue = _keyInfoEnum.Current as RSAKeyValue;
+ if (rsaKeyValue != null)
+ return rsaKeyValue.Key;
+
+ DSAKeyValue dsaKeyValue = _keyInfoEnum.Current as DSAKeyValue;
+ if (dsaKeyValue != null)
+ return dsaKeyValue.Key;
+
+ KeyInfoX509Data x509Data = _keyInfoEnum.Current as KeyInfoX509Data;
+ if (x509Data != null) {
+ _x509Collection = Utils.BuildBagOfCerts (x509Data, CertUsageType.Verification);
+ if (_x509Collection.Count > 0) {
+ _x509Enum = _x509Collection.GetEnumerator ();
+ AsymmetricAlgorithm key = GetNextCertificatePublicKey ();
+ if (key != null)
+ return key;
}
}
}
- return xel;
+
+ return null;
+ }
+
+ private X509Certificate2Collection BuildBagOfCerts ()
+ {
+ X509Certificate2Collection collection = new X509Certificate2Collection ();
+ if (KeyInfo != null) {
+ foreach (KeyInfoClause clause in KeyInfo) {
+ KeyInfoX509Data x509Data = clause as KeyInfoX509Data;
+ if (x509Data != null)
+ collection.AddRange (Utils.BuildBagOfCerts (x509Data, CertUsageType.Verification));
+ }
+ }
+
+ return collection;
+ }
+
+ private AsymmetricAlgorithm GetNextCertificatePublicKey ()
+ {
+ while (_x509Enum.MoveNext ()) {
+ X509Certificate2 certificate = (X509Certificate2)_x509Enum.Current;
+ if (certificate != null)
+ return Utils.GetAnyPublicKey (certificate);
+ }
+
+ return null;
+ }
+
+ public virtual XmlElement GetIdElement (XmlDocument document, string idValue)
+ {
+ return DefaultGetIdElement (document, idValue);
}
- internal static XmlElement DefaultGetIdElement(XmlDocument document, string idValue)
+ internal static XmlElement DefaultGetIdElement (XmlDocument document, string idValue)
{
if (document == null)
return null;
- try
- {
- XmlConvert.VerifyNCName(idValue);
- }
- catch
- {
+ try {
+ XmlConvert.VerifyNCName (idValue);
+ } catch (XmlException) {
// Identifiers are required to be an NCName
// (xml:id version 1.0, part 4, paragraph 2, bullet 1)
//
@@ -753,152 +535,515 @@ namespace System.Security.Cryptography.Xml {
}
// Get the element with idValue
- XmlElement elem = document.GetElementById(idValue);
+ XmlElement elem = document.GetElementById (idValue);
- if (elem != null)
- {
+ if (elem != null) {
// Have to check for duplicate ID values from the DTD.
- XmlDocument docClone = (XmlDocument)document.CloneNode(true);
- XmlElement cloneElem = docClone.GetElementById(idValue);
+ XmlDocument docClone = (XmlDocument)document.CloneNode (true);
+ XmlElement cloneElem = docClone.GetElementById (idValue);
// If it's null here we want to know about it, because it means that
// GetElementById failed to work across the cloning, and our uniqueness
// test is invalid.
- System.Diagnostics.Debug.Assert(cloneElem != null);
+ System.Diagnostics.Debug.Assert (cloneElem != null);
// Guard against null anyways
- if (cloneElem != null)
- {
- cloneElem.Attributes.RemoveAll();
+ if (cloneElem != null) {
+ cloneElem.Attributes.RemoveAll ();
- XmlElement cloneElem2 = docClone.GetElementById(idValue);
+ XmlElement cloneElem2 = docClone.GetElementById (idValue);
if (cloneElem2 != null)
- {
- throw new CryptographicException(
- SR.Cryptography_Xml_InvalidReference);
- }
+ throw new CryptographicException (SR.Cryptography_Xml_InvalidReference);
}
return elem;
}
- elem = GetSingleReferenceTarget(document, "Id", idValue);
+ elem = GetSingleReferenceTarget (document, "Id", idValue);
if (elem != null)
return elem;
- elem = GetSingleReferenceTarget(document, "id", idValue);
+ elem = GetSingleReferenceTarget (document, "id", idValue);
if (elem != null)
return elem;
- elem = GetSingleReferenceTarget(document, "ID", idValue);
+ elem = GetSingleReferenceTarget (document, "ID", idValue);
return elem;
}
- private static XmlElement GetSingleReferenceTarget(XmlDocument document, string idAttributeName, string idValue)
+ //
+ // private methods
+ //
+
+ private bool _bCacheValid;
+ private byte[] _digestedSignedInfo;
+
+ private static bool DefaultSignatureFormatValidator (SignedXml signedXml)
{
- // idValue has already been tested as an NCName (unless overridden for compatibility), so there's no
- // escaping that needs to be done here.
- string xPath = "//*[@" + idAttributeName + "=\"" + idValue + "\"]";
+ // Reject the signature if it uses a truncated HMAC
+ if (signedXml.DoesSignatureUseTruncatedHmac ())
+ return false;
- // http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel says that for the form URI="#chapter1":
- //
- // Identifies a node-set containing the element with ID attribute value 'chapter1' ...
- //
- // Note that it uses the singular. Therefore, if the match is ambiguous, we should consider the document invalid.
- //
- // In this case, we'll treat it the same as having found nothing across all fallbacks (but shortcut so that we don't
- // fall into a trap of finding a secondary element which wasn't the originally signed one).
+ // Reject the signature if it uses a canonicalization algorithm other than
+ // one of the ones explicitly allowed
+ if (!signedXml.DoesSignatureUseSafeCanonicalizationMethod ())
+ return false;
- XmlNodeList nodeList = document.SelectNodes(xPath);
+ // Otherwise accept it
+ return true;
+ }
- if (nodeList == null || nodeList.Count == 0)
- {
- return null;
+ // Validation function to see if the current signature is signed with a truncated HMAC - one which
+ // has a signature length of fewer bits than the whole HMAC output.
+ private bool DoesSignatureUseTruncatedHmac ()
+ {
+ // If we're not using the SignatureLength property, then we're not truncating the signature length
+ if (SignedInfo.SignatureLength == null)
+ return false;
+
+ // See if we're signed witn an HMAC algorithm
+ HMAC hmac = CryptoHelpers.CreateFromName (SignatureMethod) as HMAC;
+ if (hmac == null)
+ return false; // We aren't signed with an HMAC algorithm, so we cannot have a truncated HMAC
+
+ // Figure out how many bits the signature is using
+ int actualSignatureSize = 0;
+ if (!int.TryParse (SignedInfo.SignatureLength, out actualSignatureSize))
+ return true; // If the value wasn't a valid integer, then we'll conservatively reject it all together
+
+ // Make sure the full HMAC signature size is the same size that was specified in the XML
+ // signature. If the actual signature size is not exactly the same as the full HMAC size, then
+ // reject the signature.
+ return actualSignatureSize != hmac.HashSize;
+ }
+
+ // Validation function to see if the signature uses a canonicalization algorithm from our list
+ // of approved algorithm URIs.
+ private bool DoesSignatureUseSafeCanonicalizationMethod ()
+ {
+ foreach (string safeAlgorithm in SafeCanonicalizationMethods) {
+ if (string.Equals (safeAlgorithm, SignedInfo.CanonicalizationMethod, StringComparison.OrdinalIgnoreCase))
+ return true;
}
- if (nodeList.Count == 1)
- {
- return nodeList[0] as XmlElement;
+ SignedXmlDebugLog.LogUnsafeCanonicalizationMethod (this, SignedInfo.CanonicalizationMethod, SafeCanonicalizationMethods);
+ return false;
+ }
+
+ private bool ReferenceUsesSafeTransformMethods (Reference reference)
+ {
+ TransformChain transformChain = reference.TransformChain;
+ int transformCount = transformChain.Count;
+
+ for (int i = 0; i < transformCount; i++) {
+ Transform transform = transformChain [i];
+
+ if (!IsSafeTransform (transform.Algorithm))
+ return false;
}
- throw new CryptographicException(SR.Cryptography_Xml_InvalidReference);
+ return true;
}
- // According to book ".NET Framework Security" this method
- // iterates all possible keys then return null
- protected virtual AsymmetricAlgorithm GetPublicKey ()
+ private bool IsSafeTransform (string transformAlgorithm)
{
- if (m_signature.KeyInfo == null)
- return null;
+ // All canonicalization algorithms are valid transform algorithms.
+ foreach (string safeAlgorithm in SafeCanonicalizationMethods) {
+ if (string.Equals (safeAlgorithm, transformAlgorithm, StringComparison.OrdinalIgnoreCase))
+ return true;
+ }
- if (pkEnumerator == null) {
- pkEnumerator = m_signature.KeyInfo.GetEnumerator ();
+ foreach (string safeAlgorithm in DefaultSafeTransformMethods) {
+ if (string.Equals (safeAlgorithm, transformAlgorithm, StringComparison.OrdinalIgnoreCase))
+ return true;
}
-
-#if SECURITY_DEP
- if (_x509Enumerator != null) {
- if (_x509Enumerator.MoveNext ()) {
- X509Certificate cert = (X509Certificate) _x509Enumerator.Current;
- return new X509Certificate2 (cert.GetRawCertData ()).PublicKey.Key;
- } else {
- _x509Enumerator = null;
+
+ SignedXmlDebugLog.LogUnsafeTransformMethod (
+ this,
+ transformAlgorithm,
+ SafeCanonicalizationMethods,
+ DefaultSafeTransformMethods);
+
+ return false;
+ }
+
+ // Get a list of the built in canonicalization algorithms, as well as any that the machine admin has
+ // added to the valid set.
+ private static IList<string> KnownCanonicalizationMethods {
+ get {
+ if (s_knownCanonicalizationMethods == null) {
+ // Start with the list that the machine admin added, if any
+ List<string> safeAlgorithms = new List<string> ();
+
+ // Built in algorithms
+ safeAlgorithms.Add (XmlDsigC14NTransformUrl);
+ safeAlgorithms.Add (XmlDsigC14NWithCommentsTransformUrl);
+ safeAlgorithms.Add (XmlDsigExcC14NTransformUrl);
+ safeAlgorithms.Add (XmlDsigExcC14NWithCommentsTransformUrl);
+
+ s_knownCanonicalizationMethods = safeAlgorithms;
}
- }
-#endif
- while (pkEnumerator.MoveNext ()) {
- AsymmetricAlgorithm key = null;
- KeyInfoClause kic = (KeyInfoClause) pkEnumerator.Current;
- if (kic is DSAKeyValue)
- key = DSA.Create ();
- else if (kic is RSAKeyValue)
- key = RSA.Create ();
+ return s_knownCanonicalizationMethods;
+ }
+ }
- if (key != null) {
- key.FromXmlString (kic.GetXml ().InnerXml);
- return key;
+ private static IList<string> DefaultSafeTransformMethods {
+ get {
+ if (s_defaultSafeTransformMethods == null) {
+ List<string> safeAlgorithms = new List<string> ();
+
+ // Built in algorithms
+
+ // KnownCanonicalizationMethods don't need to be added here, because
+ // the validator will automatically accept those.
+ //
+ // xmldsig 6.6.1:
+ // Any canonicalization algorithm that can be used for
+ // CanonicalizationMethod can be used as a Transform.
+ safeAlgorithms.Add (XmlDsigEnvelopedSignatureTransformUrl);
+ safeAlgorithms.Add (XmlDsigBase64TransformUrl);
+ safeAlgorithms.Add (XmlLicenseTransformUrl);
+ safeAlgorithms.Add (XmlDecryptionTransformUrl);
+
+ s_defaultSafeTransformMethods = safeAlgorithms;
}
-#if SECURITY_DEP
- if (kic is KeyInfoX509Data) {
- _x509Enumerator = ((KeyInfoX509Data) kic).Certificates.GetEnumerator ();
- if (_x509Enumerator.MoveNext ()) {
- X509Certificate cert = (X509Certificate) _x509Enumerator.Current;
- return new X509Certificate2 (cert.GetRawCertData ()).PublicKey.Key;
+ return s_defaultSafeTransformMethods;
+ }
+ }
+
+ private byte[] GetC14NDigest (HashAlgorithm hash)
+ {
+ bool isKeyedHashAlgorithm = hash is KeyedHashAlgorithm;
+ if (isKeyedHashAlgorithm || !_bCacheValid || !SignedInfo.CacheValid) {
+ string baseUri = (_containingDocument == null ? null : _containingDocument.BaseURI);
+ XmlResolver resolver = (_bResolverSet ? _xmlResolver : new XmlSecureResolver (new XmlUrlResolver (), baseUri));
+ XmlDocument doc = Utils.PreProcessElementInput (SignedInfo.GetXml (), resolver, baseUri);
+
+ // Add non default namespaces in scope
+ CanonicalXmlNodeList namespaces = (_context == null ? null : Utils.GetPropagatedAttributes (_context));
+ SignedXmlDebugLog.LogNamespacePropagation (this, namespaces);
+ Utils.AddNamespaces (doc.DocumentElement, namespaces);
+
+ Transform c14nMethodTransform = SignedInfo.CanonicalizationMethodObject;
+ c14nMethodTransform.Resolver = resolver;
+ c14nMethodTransform.BaseURI = baseUri;
+
+ SignedXmlDebugLog.LogBeginCanonicalization (this, c14nMethodTransform);
+ c14nMethodTransform.LoadInput (doc);
+ SignedXmlDebugLog.LogCanonicalizedOutput (this, c14nMethodTransform);
+ _digestedSignedInfo = c14nMethodTransform.GetDigestedOutput (hash);
+
+ _bCacheValid = !isKeyedHashAlgorithm;
+ }
+ return _digestedSignedInfo;
+ }
+
+ private int GetReferenceLevel (int index, ArrayList references)
+ {
+ if (_refProcessed [index]) return _refLevelCache [index];
+ _refProcessed [index] = true;
+ Reference reference = (Reference)references [index];
+ if (reference.Uri == null || reference.Uri.Length == 0 || (reference.Uri.Length > 0 && reference.Uri [0] != '#')) {
+ _refLevelCache [index] = 0;
+ return 0;
+ }
+ if (reference.Uri.Length > 0 && reference.Uri [0] == '#')
+ {
+ string idref = Utils.ExtractIdFromLocalUri (reference.Uri);
+ if (idref == "xpointer(/)") {
+ _refLevelCache [index] = 0;
+ return 0;
+ }
+ // If this is pointing to another reference
+ for (int j = 0; j < references.Count; ++j) {
+ if (((Reference)references [j]).Id == idref) {
+ _refLevelCache [index] = GetReferenceLevel (j, references) + 1;
+ return (_refLevelCache [index]);
}
}
-#endif
+ // Then the reference points to an object tag
+ _refLevelCache [index] = 0;
+ return 0;
}
- return null;
+ // Malformed reference
+ throw new CryptographicException (SR.Cryptography_Xml_InvalidReference);
}
- public XmlElement GetXml ()
+ private class ReferenceLevelSortOrder : IComparer
{
- return m_signature.GetXml (envdoc);
+ private ArrayList _references;
+
+ public ReferenceLevelSortOrder ()
+ {
+ }
+
+ public ArrayList References
+ {
+ get { return _references; }
+ set { _references = value; }
+ }
+
+ public int Compare (object a, object b)
+ {
+ Reference referenceA = a as Reference;
+ Reference referenceB = b as Reference;
+
+ // Get the indexes
+ int iIndexA = 0;
+ int iIndexB = 0;
+ int i = 0;
+ foreach (Reference reference in References) {
+ if (reference == referenceA) iIndexA = i;
+ if (reference == referenceB) iIndexB = i;
+ i++;
+ }
+
+ int iLevelA = referenceA.SignedXml.GetReferenceLevel (iIndexA, References);
+ int iLevelB = referenceB.SignedXml.GetReferenceLevel (iIndexB, References);
+ return iLevelA.CompareTo (iLevelB);
+ }
}
- public void LoadXml (XmlElement value)
+ private void BuildDigestedReferences ()
{
- if (value == null)
- throw new ArgumentNullException ("value");
+ // Default the DigestMethod and Canonicalization
+ ArrayList references = SignedInfo.References;
+ // Reset the cache
+ _refProcessed = new bool [references.Count];
+ _refLevelCache = new int [references.Count];
- signatureElement = value;
- m_signature.LoadXml (value);
+ ReferenceLevelSortOrder sortOrder = new ReferenceLevelSortOrder ();
+ sortOrder.References = references;
+ // Don't alter the order of the references array list
+ ArrayList sortedReferences = new ArrayList ();
- if (_context == null) {
- _context = value;
+ foreach (Reference reference in references)
+ sortedReferences.Add (reference);
+
+ sortedReferences.Sort (sortOrder);
+
+ CanonicalXmlNodeList nodeList = new CanonicalXmlNodeList ();
+
+ foreach (DataObject obj in m_signature.ObjectList)
+ nodeList.Add (obj.GetXml ());
+
+ foreach (Reference reference in sortedReferences) {
+ if (reference.DigestMethod == null)
+ reference.DigestMethod = XmlDsigDigestDefault;
+
+ SignedXmlDebugLog.LogSigningReference (this, reference);
+
+ reference.UpdateHashValue (_containingDocument, nodeList);
+ // If this reference has an Id attribute, add it
+ if (reference.Id != null)
+ nodeList.Add (reference.GetXml ());
}
+ }
+
+ private bool CheckDigestedReferences ()
+ {
+ ArrayList references = m_signature.SignedInfo.References;
+ for (int i = 0; i < references.Count; ++i) {
+ Reference digestedReference = (Reference)references [i];
+
+ if (!ReferenceUsesSafeTransformMethods (digestedReference))
+ return false;
+
+ SignedXmlDebugLog.LogVerifyReference (this, digestedReference);
+ byte[] calculatedHash = null;
+ try {
+ calculatedHash = digestedReference.CalculateHashValue (_containingDocument, m_signature.ReferencedItems);
+ } catch (CryptoSignedXmlRecursionException) {
+ SignedXmlDebugLog.LogSignedXmlRecursionLimit (this, digestedReference);
+ return false;
+ }
+ // Compare both hashes
+ SignedXmlDebugLog.LogVerifyReferenceHash (this, digestedReference, calculatedHash, digestedReference.DigestValue);
+
+ if (!CryptographicEquals (calculatedHash, digestedReference.DigestValue))
+ return false;
+ }
+
+ return true;
+ }
+
+ // Methods _must_ be marked both No Inlining and No Optimization to be fully opted out of optimization.
+ // This is because if a candidate method is inlined, its method level attributes, including the NoOptimization
+ // attribute, are lost.
+ // This method makes no attempt to disguise the length of either of its inputs. It is assumed the attacker has
+ // knowledge of the algorithms used, and thus the output length. Length is difficult to properly blind in modern CPUs.
+ [MethodImpl (MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
+ private static bool CryptographicEquals (byte[] a, byte[] b)
+ {
+ System.Diagnostics.Debug.Assert (a != null);
+ System.Diagnostics.Debug.Assert (b != null);
- // Need to give the EncryptedXml object to the
- // XmlDecryptionTransform to give it a fighting
- // chance at decrypting the document.
- foreach (Reference r in m_signature.SignedInfo.References) {
- foreach (Transform t in r.TransformChain) {
- if (t is XmlDecryptionTransform)
- ((XmlDecryptionTransform) t).EncryptedXml = EncryptedXml;
+ int result = 0;
+
+ // Short cut if the lengths are not identical
+ if (a.Length != b.Length)
+ return false;
+
+ unchecked
+ {
+ // Normally this caching doesn't matter, but with the optimizer off, this nets a non-trivial speedup.
+ int aLength = a.Length;
+
+ for (int i = 0; i < aLength; i++) {
+ // We use subtraction here instead of XOR because the XOR algorithm gets ever so
+ // slightly faster as more and more differences pile up.
+ // This cannot overflow more than once (and back to 0) because bytes are 1 byte
+ // in length, and result is 4 bytes. The OR propagates all set bytes, so the differences
+ // can't add up and overflow a second time.
+ result = result | (a [i] - b [i]);
}
}
+
+ return (0 == result);
+ }
+
+ // If we have a signature format validation callback, check to see if this signature's format (not
+ // the signature itself) is valid according to the validator. A return value of true indicates that
+ // the signature format is acceptable, false means that the format is not valid.
+ private bool CheckSignatureFormat ()
+ {
+ if (_signatureFormatValidator == null) {
+ // No format validator means that we default to accepting the signature. (This is
+ // effectively compatibility mode with v3.5).
+ return true;
+ }
+
+ SignedXmlDebugLog.LogBeginCheckSignatureFormat (this, _signatureFormatValidator);
+
+ bool formatValid = _signatureFormatValidator (this);
+ SignedXmlDebugLog.LogFormatValidationResult (this, formatValid);
+ return formatValid;
+ }
+
+ private bool CheckSignedInfo (AsymmetricAlgorithm key)
+ {
+ if (key == null)
+ throw new ArgumentNullException (nameof (key));
+
+ SignedXmlDebugLog.LogBeginCheckSignedInfo (this, m_signature.SignedInfo);
+
+ SignatureDescription signatureDescription = CryptoHelpers.CreateFromName (SignatureMethod) as SignatureDescription;
+ if (signatureDescription == null)
+ throw new CryptographicException (SR.Cryptography_Xml_SignatureDescriptionNotCreated);
+
+ // Let's see if the key corresponds with the SignatureMethod
+ Type ta = Type.GetType (signatureDescription.KeyAlgorithm);
+ if (!IsKeyTheCorrectAlgorithm (key, ta))
+ return false;
+
+ HashAlgorithm hashAlgorithm = signatureDescription.CreateDigest ();
+ if (hashAlgorithm == null)
+ throw new CryptographicException (SR.Cryptography_Xml_CreateHashAlgorithmFailed);
+ byte[] hashval = GetC14NDigest (hashAlgorithm);
+
+ AsymmetricSignatureDeformatter asymmetricSignatureDeformatter = signatureDescription.CreateDeformatter (key);
+ SignedXmlDebugLog.LogVerifySignedInfo (this,
+ key,
+ signatureDescription,
+ hashAlgorithm,
+ asymmetricSignatureDeformatter,
+ hashval,
+ m_signature.SignatureValue);
+ return asymmetricSignatureDeformatter.VerifySignature (hashval, m_signature.SignatureValue);
+ }
+
+ private bool CheckSignedInfo (KeyedHashAlgorithm macAlg)
+ {
+ if (macAlg == null)
+ throw new ArgumentNullException (nameof (macAlg));
+
+ SignedXmlDebugLog.LogBeginCheckSignedInfo (this, m_signature.SignedInfo);
+
+ int signatureLength;
+ if (m_signature.SignedInfo.SignatureLength == null)
+ signatureLength = macAlg.HashSize;
+ else
+ signatureLength = Convert.ToInt32 (m_signature.SignedInfo.SignatureLength, null);
+
+ // signatureLength should be less than hash size
+ if (signatureLength < 0 || signatureLength > macAlg.HashSize)
+ throw new CryptographicException (SR.Cryptography_Xml_InvalidSignatureLength);
+ if (signatureLength % 8 != 0)
+ throw new CryptographicException (SR.Cryptography_Xml_InvalidSignatureLength2);
+ if (m_signature.SignatureValue == null)
+ throw new CryptographicException (SR.Cryptography_Xml_SignatureValueRequired);
+ if (m_signature.SignatureValue.Length != signatureLength / 8)
+ throw new CryptographicException (SR.Cryptography_Xml_InvalidSignatureLength);
+
+ // Calculate the hash
+ byte[] hashValue = GetC14NDigest (macAlg);
+ SignedXmlDebugLog.LogVerifySignedInfo (this, macAlg, hashValue, m_signature.SignatureValue);
+
+ for (int i = 0; i < m_signature.SignatureValue.Length; i++)
+ if (m_signature.SignatureValue [i] != hashValue [i]) return false;
+
+ return true;
+ }
+
+ private static XmlElement GetSingleReferenceTarget (XmlDocument document, string idAttributeName, string idValue)
+ {
+ // idValue has already been tested as an NCName (unless overridden for compatibility), so there's no
+ // escaping that needs to be done here.
+ string xPath = "//*[@" + idAttributeName + "=\"" + idValue + "\"]";
+
+ // http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel says that for the form URI="#chapter1":
+ //
+ // Identifies a node-set containing the element with ID attribute value 'chapter1' ...
+ //
+ // Note that it uses the singular. Therefore, if the match is ambiguous, we should consider the document invalid.
+ //
+ // In this case, we'll treat it the same as having found nothing across all fallbacks (but shortcut so that we don't
+ // fall into a trap of finding a secondary element which wasn't the originally signed one).
+
+ XmlNodeList nodeList = document.SelectNodes (xPath);
+
+ if (nodeList == null || nodeList.Count == 0)
+ return null;
+
+ if (nodeList.Count == 1)
+ return nodeList [0] as XmlElement;
+
+ throw new CryptographicException (SR.Cryptography_Xml_InvalidReference);
+ }
+
+ private static bool IsKeyTheCorrectAlgorithm (AsymmetricAlgorithm key, Type expectedType)
+ {
+ Type actualType = key.GetType ();
+
+ if (actualType == expectedType)
+ return true;
+
+ // This check exists solely for compatibility with 4.6. Normally, we would expect "expectedType" to be the superclass type and
+ // the actualType to be the subclass.
+ if (expectedType.IsSubclassOf (actualType))
+ return true;
+
+ //
+ // "expectedType" comes from the KeyAlgorithm property of a SignatureDescription. The BCL SignatureDescription classes have historically
+ // denoted provider-specific implementations ("RSACryptoServiceProvider") rather than the base class for the algorithm ("RSA"). We could
+ // change those (at the risk of creating other compat problems) but we have no control over third party SignatureDescriptions.
+ //
+ // So, in the absence of a better approach, walk up the parent hierarchy until we find the ancestor that's a direct subclass of
+ // AsymmetricAlgorithm and treat that as the algorithm identifier.
+ //
+ while (expectedType != null && expectedType.BaseType != typeof (AsymmetricAlgorithm))
+ expectedType = expectedType.BaseType;
+
+ if (expectedType == null)
+ return false; // SignatureDescription specified something that isn't even a subclass of AsymmetricAlgorithm. For compatibility with 4.6, return false rather throw.
+
+ if (actualType.IsSubclassOf (expectedType))
+ return true;
+
+ return false;
}
}
-}
+} \ No newline at end of file
diff --git a/mcs/class/System.Security/System.Security.Cryptography.Xml/X509IssuerSerial.cs b/mcs/class/System.Security/System.Security.Cryptography.Xml/X509IssuerSerial.cs
deleted file mode 100644
index 505752920a1..00000000000
--- a/mcs/class/System.Security/System.Security.Cryptography.Xml/X509IssuerSerial.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// X509IssuerSerial.cs - X509IssuerSerial implementation for XML Encryption
-//
-// Author:
-// Tim Coleman (tim@timcoleman.com)
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Copyright (C) Tim Coleman, 2004
-// Copyright (C) 2004-2005 Novell Inc. (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-namespace System.Security.Cryptography.Xml {
-
- public
- struct X509IssuerSerial {
-
- private string _issuerName;
- private string _serialNumber;
-
- internal X509IssuerSerial (string issuer, string serial)
- {
- _issuerName = issuer;
- _serialNumber = serial;
- }
-
- public string IssuerName {
- get { return _issuerName; }
- set { _issuerName = value; }
- }
-
- public string SerialNumber {
- get { return _serialNumber; }
- set { _serialNumber = value; }
- }
- }
-}
-
diff --git a/mcs/class/System.Security/System.Security.Cryptography.Xml/XmlSignature.cs b/mcs/class/System.Security/System.Security.Cryptography.Xml/XmlSignature.cs
deleted file mode 100644
index 1dc64eac1dc..00000000000
--- a/mcs/class/System.Security/System.Security.Cryptography.Xml/XmlSignature.cs
+++ /dev/null
@@ -1,128 +0,0 @@
-//
-// XmlSignature.cs: Handles Xml Signature
-//
-// Author:
-// Sebastien Pouliot (spouliot@motus.com)
-// Atsushi Enomoto (atsushi@ximian.com)
-// Tim Coleman (tim@timcoleman.com)
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) Tim Coleman, 2004
-// (C) 2004 Novell Inc.
-//
-
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Collections;
-using System.Xml;
-
-namespace System.Security.Cryptography.Xml {
-
- // following the design of WSE
- internal class XmlSignature {
-
- public class ElementNames {
-
- public const string CanonicalizationMethod = "CanonicalizationMethod";
- public const string DigestMethod = "DigestMethod";
- public const string DigestValue = "DigestValue";
- public const string DSAKeyValue = "DSAKeyValue";
- public const string EncryptedKey = "EncryptedKey";
- public const string HMACOutputLength = "HMACOutputLength";
- public const string KeyInfo = "KeyInfo";
- public const string KeyName = "KeyName";
- public const string KeyValue = "KeyValue";
- public const string Manifest = "Manifest";
- public const string Object = "Object";
- public const string Reference = "Reference";
- public const string RetrievalMethod = "RetrievalMethod";
- public const string RSAKeyValue = "RSAKeyValue";
- public const string Signature = "Signature";
- public const string SignatureMethod = "SignatureMethod";
- public const string SignatureValue = "SignatureValue";
- public const string SignedInfo = "SignedInfo";
- public const string Transform = "Transform";
- public const string Transforms = "Transforms";
- public const string X509Data = "X509Data";
- public const string X509IssuerSerial = "X509IssuerSerial";
- public const string X509IssuerName = "X509IssuerName";
- public const string X509SerialNumber = "X509SerialNumber";
- public const string X509SKI = "X509SKI";
- public const string X509SubjectName = "X509SubjectName";
- public const string X509Certificate = "X509Certificate";
- public const string X509CRL = "X509CRL";
-
- public ElementNames () {}
- }
-
- public class AttributeNames {
-
- public const string Algorithm = "Algorithm";
- public const string Encoding = "Encoding";
- public const string Id = "Id";
- public const string MimeType = "MimeType";
- public const string Type = "Type";
- public const string URI = "URI";
-
- public AttributeNames () {}
- }
-
- public class Uri {
- public const string Manifest = "http://www.w3.org/2000/09/xmldsig#Manifest";
- }
-
- public const string NamespaceURI = "http://www.w3.org/2000/09/xmldsig#";
- public const string Prefix = "ds";
-
- public XmlSignature ()
- {
- }
-
- public static XmlElement GetChildElement (XmlElement xel, string element, string ns)
- {
- for (int i = 0; i < xel.ChildNodes.Count; i++) {
- XmlNode n = xel.ChildNodes [i];
- if (n.NodeType == XmlNodeType.Element && n.LocalName == element && n.NamespaceURI == ns)
- return n as XmlElement;
- }
- return null;
- }
-
- public static string GetAttributeFromElement (XmlElement xel, string attribute, string element)
- {
- XmlElement el = GetChildElement (xel, element, XmlSignature.NamespaceURI);
- return el != null ? el.GetAttribute (attribute) : null;
- }
-
- public static XmlElement [] GetChildElements (XmlElement xel, string element)
- {
- ArrayList al = new ArrayList ();
- for (int i = 0; i < xel.ChildNodes.Count; i++) {
- XmlNode n = xel.ChildNodes [i];
- if (n.NodeType == XmlNodeType.Element && n.LocalName == element && n.NamespaceURI == XmlSignature.NamespaceURI)
- al.Add (n);
- }
- return al.ToArray (typeof (XmlElement)) as XmlElement [];
- }
- }
-}
diff --git a/mcs/class/System.Security/System.Security.dll.sources b/mcs/class/System.Security/System.Security.dll.sources
index 75c0a6f9b0a..e77373a0ebe 100644
--- a/mcs/class/System.Security/System.Security.dll.sources
+++ b/mcs/class/System.Security/System.Security.dll.sources
@@ -1,5 +1,5 @@
#include common_System.Security.dll.sources
-corefx/SR.cs
+
Mono.Security.Cryptography/ManagedProtection.cs
Mono.Security.Cryptography/NativeDapiProtection.cs
System.Security.Cryptography/MemoryProtectionScope.cs
@@ -13,6 +13,8 @@ System.Security.Cryptography.Pkcs/SignerInfoEnumerator.cs
../System.Core/System.Security.Cryptography.X509Certificates/RSACertificateExtensions.cs
System.Security.Cryptography.X509Certificates/X509Certificate2UI.cs
System.Security.Cryptography.X509Certificates/X509SelectionFlag.cs
+
+# System.Security.Cryptography.Xml
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/AncestralNamespaceContextManager.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/AttributeSortOrder.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/C14NAncestralNamespaceContextManager.cs
@@ -57,9 +59,8 @@ System.Security.Cryptography.X509Certificates/X509SelectionFlag.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoName.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoNode.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoRetrievalMethod.cs
-System.Security.Cryptography.Xml/KeyInfoX509Data.cs
+../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfoX509Data.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyReference.cs
-System.Security.Cryptography.Xml/Manifest.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/MyXmlDocument.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/NamespaceFrame.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/NamespaceSortOrder.cs
@@ -72,8 +73,8 @@ System.Security.Cryptography.Xml/Manifest.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SHA384SignatureDescription.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SHA512SignatureDescription.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs
-System.Security.Cryptography.Xml/Signature.cs
-System.Security.Cryptography.Xml/SignedInfo.cs
+../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Signature.cs
+../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedInfo.cs
System.Security.Cryptography.Xml/SignedXml.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SymmetricKeyWrap.cs
@@ -90,8 +91,8 @@ System.Security.Cryptography.Xml/SignedXml.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXsltTransform.cs
../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlLicenseTransform.cs
-System.Security.Cryptography.Xml/XmlSignature.cs
-../../build/common/MonoTODOAttribute.cs
+
+# System.Security.Permissions
System.Security.Permissions/DataProtectionPermission.cs
System.Security.Permissions/DataProtectionPermissionAttribute.cs
System.Security.Permissions/DataProtectionPermissionFlags.cs
diff --git a/mcs/class/System.Security/Test/System.Security.Cryptography.Xml/EncryptedXmlTest.cs b/mcs/class/System.Security/Test/System.Security.Cryptography.Xml/EncryptedXmlTest.cs
index 7ff9beef391..82fc0fb433a 100644
--- a/mcs/class/System.Security/Test/System.Security.Cryptography.Xml/EncryptedXmlTest.cs
+++ b/mcs/class/System.Security/Test/System.Security.Cryptography.Xml/EncryptedXmlTest.cs
@@ -180,11 +180,22 @@ namespace MonoTests.System.Security.Cryptography.Xml
Assert.IsNull (ex.GetIdElement (null, "value"));
}
+ [TestCase (null, TestName = "null")]
+ [TestCase ("", TestName = "empty")]
+ public void GetIdElement_WhenElementNameMustBeNonColonizedAndItIsNotProvided_ThrowsArgumentNullException (string elementName)
+ {
+ var sut = new EncryptedXml ();
+
+ var ex = Assert.Throws<ArgumentNullException> (() => sut.GetIdElement (new XmlDocument (), elementName), "Exception");
+ Assert.That (ex.ParamName, Is.EqualTo ("name"), "ParamName");
+ }
+
[Test]
- public void GetIdElement_StringNull ()
+ public void GetIdElement_WhenElementNameMustBeNonColonizedAndItContainsColon_ReturnsNull ()
{
- EncryptedXml ex = new EncryptedXml ();
- Assert.IsNull (ex.GetIdElement (new XmlDocument (), null));
+ var sut = new EncryptedXml ();
+
+ Assert.That (sut.GetIdElement (new XmlDocument (), "t:test"), Is.Null);
}
[Test]
diff --git a/mcs/class/System.Security/Test/System.Security.Cryptography.Xml/SignedXmlTest.cs b/mcs/class/System.Security/Test/System.Security.Cryptography.Xml/SignedXmlTest.cs
index b5baf86ebdb..2a6aae4f774 100644
--- a/mcs/class/System.Security/Test/System.Security.Cryptography.Xml/SignedXmlTest.cs
+++ b/mcs/class/System.Security/Test/System.Security.Cryptography.Xml/SignedXmlTest.cs
@@ -253,7 +253,7 @@ namespace MonoTests.System.Security.Cryptography.Xml {
signedXml.ComputeSignature ();
Assert.IsNull (signedXml.SigningKeyName, "SigningKeyName");
- Assert.AreEqual (SignedXml.XmlDsigRSASHA1Url, signedXml.SignatureMethod, "SignatureMethod");
+ Assert.AreEqual (SignedXml.XmlDsigRSASHA256Url, signedXml.SignatureMethod, "SignatureMethod");
Assert.AreEqual (128, signedXml.SignatureValue.Length, "SignatureValue");
Assert.IsNull (signedXml.SigningKeyName, "SigningKeyName");
@@ -638,13 +638,13 @@ namespace MonoTests.System.Security.Cryptography.Xml {
public void DataReferenceToNonDataObject ()
{
XmlDocument doc = new XmlDocument ();
- doc.LoadXml ("<foo Id='id:1'/>");
+ doc.LoadXml ("<foo Id='test'/>");
SignedXml signedXml = new SignedXml (doc);
DSA key = DSA.Create ();
signedXml.SigningKey = key;
Reference reference = new Reference ();
- reference.Uri = "#id:1";
+ reference.Uri = "#test";
XmlDsigC14NTransform t = new XmlDsigC14NTransform ();
reference.AddTransform (t);
@@ -707,12 +707,30 @@ namespace MonoTests.System.Security.Cryptography.Xml {
return sw.ToString ();
}
+ [TestCase (null, TestName = "null")]
+ [TestCase ("", TestName = "empty")]
+ public void GetIdElement_WhenElementNameMustBeNonColonizedAndItIsNotProvided_ThrowsArgumentNullException (string elementName)
+ {
+ var sut = new SignedXml ();
+
+ var ex = Assert.Throws<ArgumentNullException> (() => sut.GetIdElement (new XmlDocument (), elementName), "Exception");
+ Assert.That (ex.ParamName, Is.EqualTo ("name"), "ParamName");
+ }
+
[Test]
- public void GetIdElement_Null ()
+ public void GetIdElement_WhenElementNameMustBeNonColonizedAndItContainsColon_ReturnsNull ()
{
- SignedXml sign = new SignedXml ();
- Assert.IsNull (sign.GetIdElement (null, "value"));
- Assert.IsNull (sign.GetIdElement (new XmlDocument (), null));
+ var sut = new SignedXml ();
+
+ Assert.That (sut.GetIdElement (new XmlDocument (), "t:test"), Is.Null);
+ }
+
+ [Test]
+ public void GetIdElement_WhenXmlDocumentIsNotProvided_ReturnsNull ()
+ {
+ var sut = new SignedXml ();
+
+ Assert.That (sut.GetIdElement (null, "value"), Is.Null);
}
[Test]
@@ -789,6 +807,7 @@ namespace MonoTests.System.Security.Cryptography.Xml {
SignedXml signedXml = new SignedXml (doc);
signedXml.SigningKey = cert.PrivateKey;
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
+ signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;
Reference reference = new Reference ();
reference.DigestMethod = SignedXml.XmlDsigSHA1Url;
@@ -1408,13 +1427,6 @@ namespace MonoTests.System.Security.Cryptography.Xml {
// verify MS-generated signature
Assert.IsTrue (sign.CheckSignature (new HMACRIPEMD160 (hmackey)));
}
- // CVE-2009-0217
- // * a 0-length signature is the worse case - it accepts anything
- // * between 1-7 bits length are considered invalid (not a multiple of 8)
- // * a 8 bits signature would have one chance, out of 256, to be valid
- // * and so on... until we hit (output-length / 2) or 80 bits (see ERRATUM)
-
- static bool erratum = true; // xmldsig erratum for CVE-2009-0217
static SignedXml GetSignedXml (string xml)
{
@@ -1426,31 +1438,15 @@ namespace MonoTests.System.Security.Cryptography.Xml {
return sign;
}
- static void CheckErratum (SignedXml signed, KeyedHashAlgorithm hmac, string message)
- {
- if (erratum) {
- try {
- signed.CheckSignature (hmac);
- Assert.Fail (message + ": unexcepted success");
- }
- catch (CryptographicException) {
- }
- catch (Exception e) {
- Assert.Fail (message + ": unexcepted " + e.ToString ());
- }
- } else {
- Assert.IsTrue (signed.CheckSignature (hmac), message);
- }
- }
-
- private void HmacMustBeMultipleOfEightBits (int bits)
+ [Test]
+ public void CheckSignature_WhenHmacOutputLengthIsNotMultipleOf8_ThrowsCryptographicException ()
{
string xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
<SignedInfo>
<CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315"" />
<SignatureMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#hmac-sha1"" >
- <HMACOutputLength>{0}</HMACOutputLength>
+ <HMACOutputLength>81</HMACOutputLength>
</SignatureMethod>
<Reference URI=""#object"">
<DigestMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#sha1"" />
@@ -1463,96 +1459,41 @@ namespace MonoTests.System.Security.Cryptography.Xml {
<Object Id=""object"">some other text</Object>
</Signature>
";
- SignedXml sign = GetSignedXml (String.Format (xml, bits));
- // only multiple of 8 bits are supported
- sign.CheckSignature (new HMACSHA1 (Encoding.ASCII.GetBytes ("secret")));
- }
- [Test]
- public void HmacMustBeMultipleOfEightBits ()
- {
- for (int i = 1; i < 160; i++) {
- // The .NET framework only supports multiple of 8 bits
- if (i % 8 == 0)
- continue;
-
- try {
- HmacMustBeMultipleOfEightBits (i);
- Assert.Fail ("Unexpected Success " + i.ToString ());
- }
- catch (CryptographicException) {
- }
- catch (Exception e) {
- Assert.Fail ("Unexpected Exception " + i.ToString () + " : " + e.ToString ());
- }
- }
- }
+ var sut = GetSignedXml (xml);
+ sut.SignatureFormatValidator = null;
- [Test]
- [Category ("NotDotNet")] // will fail until a fix is available
- public void VerifyHMAC_ZeroLength ()
- {
- string xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
-<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
- <SignedInfo>
- <CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315"" />
- <SignatureMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#hmac-sha1"" >
- <HMACOutputLength>0</HMACOutputLength>
- </SignatureMethod>
- <Reference URI=""#object"">
- <DigestMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#sha1"" />
- <DigestValue>nz4GS0NbH2SrWlD/4fX313CoTzc=</DigestValue>
- </Reference>
- </SignedInfo>
- <SignatureValue>
- </SignatureValue>
- <Object Id=""object"">some other text</Object>
-</Signature>
-";
- SignedXml sign = GetSignedXml (xml);
-
- CheckErratum (sign, new HMACSHA1 (Encoding.ASCII.GetBytes ("no clue")), "1");
- CheckErratum (sign, new HMACSHA1 (Encoding.ASCII.GetBytes ("")), "2");
- CheckErratum (sign, new HMACSHA1 (Encoding.ASCII.GetBytes ("oops")), "3");
- CheckErratum (sign, new HMACSHA1 (Encoding.ASCII.GetBytes ("secret")), "4");
+ var ex = Assert.Throws<CryptographicException> (() => sut.CheckSignature (new HMACSHA1 (Encoding.ASCII.GetBytes ("secret"))), "Exception");
+ Assert.That (ex.Message, Is.StringContaining ("multiple of 8").IgnoreCase, "Message");
}
[Test]
- [Category ("NotDotNet")] // will fail until a fix is available
- public void VerifyHMAC_SmallerThanMinimumLength ()
+ public void CheckSignature_WhenDefaultSignatureFormatValidatorIsUsedAndSignatureUsesTruncatedHmac_ReturnsFalse ()
{
- // 72 is a multiple of 8 but smaller than the minimum of 80 bits
- string xml = @"<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#""><SignedInfo><CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315"" /><SignatureMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#hmac-sha1""><HMACOutputLength>72</HMACOutputLength></SignatureMethod><Reference URI=""#object""><DigestMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#sha1"" /><DigestValue>nz4GS0NbH2SrWlD/4fX313CoTzc=</DigestValue></Reference></SignedInfo><SignatureValue>2dimB+P5Aw5K</SignatureValue><Object Id=""object"">some other text</Object></Signature>";
- SignedXml sign = GetSignedXml (xml);
- CheckErratum (sign, new HMACSHA1 (Encoding.ASCII.GetBytes ("secret")), "72");
- }
+ // The HMAC output length is 128, which is a half of HMACSHA256 that we're going to use.
+ string xml = @"<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#""><SignedInfo><CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315"" /><SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#hmac-sha256""><HMACOutputLength>128</HMACOutputLength></SignatureMethod><Reference URI=""#object""><DigestMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#sha1"" /><DigestValue>nz4GS0NbH2SrWlD/4fX313CoTzc=</DigestValue></Reference></SignedInfo><SignatureValue>aegpvkAwOL8gN/CjSnW6qw==</SignatureValue><Object Id=""object"">some other text</Object></Signature>";
+ var sut = GetSignedXml (xml);
- [Test]
- public void VerifyHMAC_MinimumLength ()
- {
- // 80 bits is the minimum (and the half-size of HMACSHA1)
- string xml = @"<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#""><SignedInfo><CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315"" /><SignatureMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#hmac-sha1""><HMACOutputLength>80</HMACOutputLength></SignatureMethod><Reference URI=""#object""><DigestMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#sha1"" /><DigestValue>nz4GS0NbH2SrWlD/4fX313CoTzc=</DigestValue></Reference></SignedInfo><SignatureValue>jVQPtLj61zNYjw==</SignatureValue><Object Id=""object"">some other text</Object></Signature>";
- SignedXml sign = GetSignedXml (xml);
- Assert.IsTrue (sign.CheckSignature (new HMACSHA1 (Encoding.ASCII.GetBytes ("secret"))));
- }
- [Test]
- [Category ("NotDotNet")] // will fail until a fix is available
- public void VerifyHMAC_SmallerHalfLength ()
- {
- // 80bits is smaller than the half-size of HMACSHA256
- string xml = @"<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#""><SignedInfo><CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315"" /><SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#hmac-sha256""><HMACOutputLength>80</HMACOutputLength></SignatureMethod><Reference URI=""#object""><DigestMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#sha1"" /><DigestValue>nz4GS0NbH2SrWlD/4fX313CoTzc=</DigestValue></Reference></SignedInfo><SignatureValue>vPtw7zKVV/JwQg==</SignatureValue><Object Id=""object"">some other text</Object></Signature>";
- SignedXml sign = GetSignedXml (xml);
- CheckErratum (sign, new HMACSHA256 (Encoding.ASCII.GetBytes ("secret")), "80");
+ // Although the XML Signature standard allows using truncated HMACs (with some limitations),
+ // .NET Framework, by default, doesn't allow using them, since it may result in security issues.
+ Assert.That (sut.CheckSignature (new HMACSHA256 (Encoding.ASCII.GetBytes ("secret"))), Is.False);
}
[Test]
- public void VerifyHMAC_HalfLength ()
+ public void CheckSignature_WhenDefaultSignatureFormatValidatorIsNotUsedAndSignatureUsesTruncatedHmac_ReturnsTrue ()
{
- // 128 is the half-size of HMACSHA256
+ // The HMAC output length is 128, which is a half of HMACSHA256 that we're going to use.
string xml = @"<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#""><SignedInfo><CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315"" /><SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#hmac-sha256""><HMACOutputLength>128</HMACOutputLength></SignatureMethod><Reference URI=""#object""><DigestMethod Algorithm=""http://www.w3.org/2000/09/xmldsig#sha1"" /><DigestValue>nz4GS0NbH2SrWlD/4fX313CoTzc=</DigestValue></Reference></SignedInfo><SignatureValue>aegpvkAwOL8gN/CjSnW6qw==</SignatureValue><Object Id=""object"">some other text</Object></Signature>";
- SignedXml sign = GetSignedXml (xml);
- Assert.IsTrue (sign.CheckSignature (new HMACSHA256 (Encoding.ASCII.GetBytes ("secret"))));
+ var sut = GetSignedXml (xml);
+
+ // By default, .NET Framework doesn't allow using truncated HMACs, since it may lead to security issues.
+ // That being said, the XML Signature standard allows using truncated HMACs, but with some limitations.
+ // It's possible to use truncated HMACs by using a custom signature format validator, or not using it at all.
+ sut.SignatureFormatValidator = null;
+
+ Assert.That (sut.CheckSignature (new HMACSHA256 (Encoding.ASCII.GetBytes ("secret"))), Is.True);
}
+
[Test]
public void VerifyHMAC_FullLength ()
{
@@ -1562,8 +1503,7 @@ namespace MonoTests.System.Security.Cryptography.Xml {
}
[Test]
- [ExpectedException (typeof (CryptographicException))]
- public void VerifyHMAC_HMACOutputLength_Signature_Mismatch ()
+ public void CheckSignature_WhenSignatureLengthIsGreaterThanHmacOutputLength_ThrowsCryptographicException ()
{
string xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
@@ -1582,13 +1522,15 @@ namespace MonoTests.System.Security.Cryptography.Xml {
<Object Id=""object"">some other text</Object>
</Signature>
";
- SignedXml sign = GetSignedXml (xml);
- sign.CheckSignature (new HMACSHA1 (Encoding.ASCII.GetBytes ("no clue")));
+ var sut = GetSignedXml (xml);
+ sut.SignatureFormatValidator = null;
+
+ var ex = Assert.Throws<CryptographicException> (() => sut.CheckSignature (new HMACSHA1 (Encoding.ASCII.GetBytes ("no clue"))), "Exception");
+ Assert.That (ex.Message, Is.StringContaining ("length of the signature").IgnoreCase, "Message");
}
[Test]
- [ExpectedException (typeof (FormatException))]
- public void VerifyHMAC_HMACOutputLength_Invalid ()
+ public void CheckSignature_WhenHmacOutputLengthIsInvalid_ThrowsFormatException ()
{
string xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
@@ -1607,8 +1549,10 @@ namespace MonoTests.System.Security.Cryptography.Xml {
<Object Id=""object"">some other text</Object>
</Signature>
";
- SignedXml sign = GetSignedXml (xml);
- sign.CheckSignature (new HMACSHA1 (Encoding.ASCII.GetBytes ("no clue")));
+ var sut = GetSignedXml (xml);
+ sut.SignatureFormatValidator = null;
+
+ Assert.Throws<FormatException> (() => sut.CheckSignature (new HMACSHA1 (Encoding.ASCII.GetBytes ("no clue"))));
}
[Test]
@@ -1628,7 +1572,7 @@ namespace MonoTests.System.Security.Cryptography.Xml {
}
[Test]
- public void ComputeSignature_WhenSignatureMethodIsNotSpecifiedAndRsaSigningKeyIsUsed_UsesRsaSha1Algorithm ()
+ public void ComputeSignature_WhenSignatureMethodIsNotSpecifiedAndRsaSigningKeyIsUsed_UsesRsaSha256Algorithm ()
{
var unsignedXml = new XmlDocument ();
unsignedXml.LoadXml ("<test />");
@@ -1651,7 +1595,7 @@ namespace MonoTests.System.Security.Cryptography.Xml {
string.Format ("/{0}:SignedInfo/{0}:SignatureMethod", XmlDsigNamespacePrefix),
namespaceManager);
- Assert.That (signatureMethodElement.Attributes["Algorithm"].Value, Is.EqualTo (SignedXml.XmlDsigRSASHA1Url));
+ Assert.That (signatureMethodElement.Attributes["Algorithm"].Value, Is.EqualTo (SignedXml.XmlDsigRSASHA256Url));
}
[Test]
diff --git a/mcs/class/System.Security/common_System.Security.dll.sources b/mcs/class/System.Security/common_System.Security.dll.sources
index 5a34119a3ad..321dc74da7c 100644
--- a/mcs/class/System.Security/common_System.Security.dll.sources
+++ b/mcs/class/System.Security/common_System.Security.dll.sources
@@ -1,12 +1,18 @@
Assembly/AssemblyInfo.cs
+corefx/SR.cs
+
../../build/common/Consts.cs
../../build/common/Locale.cs
../../build/common/MonoTODOAttribute.cs
+
+# System.Security.Cryptography
System.Security.Cryptography/CryptographicAttribute.cs
System.Security.Cryptography/CryptographicAttributeCollection.cs
System.Security.Cryptography/CryptographicAttributeEnumerator.cs
System.Security.Cryptography/DataProtectionScope.cs
System.Security.Cryptography/ProtectedData.cs
+
+# System.Security.Cryptography.Pkcs
System.Security.Cryptography.Pkcs/AlgorithmIdentifier.cs
System.Security.Cryptography.Pkcs/CmsRecipient.cs
System.Security.Cryptography.Pkcs/CmsRecipientCollection.cs
@@ -30,5 +36,6 @@ System.Security.Cryptography.Pkcs/SubjectIdentifier.cs
System.Security.Cryptography.Pkcs/SubjectIdentifierOrKey.cs
System.Security.Cryptography.Pkcs/SubjectIdentifierOrKeyType.cs
System.Security.Cryptography.Pkcs/SubjectIdentifierType.cs
-System.Security.Cryptography.Xml/X509IssuerSerial.cs
+# System.Security.Cryptography.Xml
+../../../external/corefx/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/X509IssuerSerial.cs