-
Notifications
You must be signed in to change notification settings - Fork 15
/
XmlSigningHelper.cs
120 lines (99 loc) · 4 KB
/
XmlSigningHelper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
Copyright (c) 2017 TPCWare - Nicolò Carandini
This file is licensed to you under the BSD 3-Clause License.
See the LICENSE file in the project root for more information.
Authors: Nicolò Carandini (see Git history for other contributors)
*/
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.Xml;
namespace Italia.Spid.Authentication.Saml
{
internal static class XmlSigningHelper {
/// <summary>
/// Signs an XML Document for a Saml Response
/// </summary>
internal static XmlElement SignXMLDoc(XmlDocument doc, X509Certificate2 certificate, string referenceUri)
{
if (doc == null)
{
throw new ArgumentNullException("The doc parameter can't be null");
}
if (certificate == null)
{
throw new ArgumentNullException("The cert2 parameter can't be null");
}
if (string.IsNullOrWhiteSpace(referenceUri))
{
throw new ArgumentNullException("The referenceUri parameter can't be null or empty");
}
AsymmetricAlgorithm privateKey;
try
{
privateKey = certificate.PrivateKey;
}
catch (Exception ex)
{
throw new FieldAccessException("Unable to find private key in the X509Certificate", ex);
}
#if NET461
var key = new RSACryptoServiceProvider(new CspParameters(24))
{
PersistKeyInCsp = false
};
key.FromXmlString(privateKey.ToXmlString(true));
SignedXml signedXml = new SignedXml(doc)
{
SigningKey = key
};
#else
SignedXml signedXml = new SignedXml(doc)
{
SigningKey = privateKey // key
};
#endif
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
Reference reference = new Reference
{
DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256"
};
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
reference.Uri = "#" + referenceUri;
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(certificate));
signedXml.KeyInfo = keyInfo;
signedXml.ComputeSignature();
XmlElement signature = signedXml.GetXml();
return signature;
}
internal static bool VerifySignature(XmlDocument signedDocument)
{
{
if (signedDocument == null)
{
throw new ArgumentNullException("The signedDocument parameter can't be null");
}
try
{
SignedXml signedXml = new SignedXml(signedDocument);
XmlNodeList nodeList = (signedDocument.GetElementsByTagName("ds:Signature")?.Count > 0) ?
signedDocument.GetElementsByTagName("ds:Signature") :
(signedDocument.GetElementsByTagName("ns2:Signature")?.Count > 0) ?
signedDocument.GetElementsByTagName("ns2:Signature") :
signedDocument.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
return signedXml.CheckSignature();
}
catch (Exception ex)
{
throw new Exception("Error on VerifySignature", ex);
}
}
}
}
}