Hi I am new to SAML and SSO techniques. I am trying to create a valid SAML reponse with signed and encrypted Assertion. I have created a SAML response which is signed but i am not able to encrypte the assertion and create the tag. My Generated SAML response is,
<samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_88a4cf19-6f41-46ee-9dc3-98ac80168bd9" Version="2.0" IssueInstant="2015-03-26T11:43:13.4468624Z" Destination="Test1" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<saml:Issuer>Test</saml:Issuer>
<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#rsa-sha1" />
<Reference URI="#_49bc8835-7c9a-4ee2-8087-7cfcbe48375f">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>My4iQVO1Oy3i6jV+Jlp0czX0mpA=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>GWfdKMCHbiqq6OhyHQ0y2LoDQkmC95fs3SKWyPMzu6jSjbf6vrMRFCrlch+DU1k3+sfsj1tFkJNMPKpxZIx2XksjnEQv3Hdqy7oPSoGiODmrky7CTKEdYbCQqu6a8dwNBLNQTClYAgDz/m5yfbFlJNPy9TtsCl2l1R/qg6dzVkA=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIBwTCCAS6gAwIBAgIQr71oSHfrBKpKpRUTWmBFCzAJBgUrDgMCHQUAMCMxITAfBgNVBAMeGABCAEYASQBcAGQAcwBwAGUAaQBnAGgAdDAeFw0xMDAyMTkxMzI4MzlaFw0xMTAyMTkxOTI4MzlaMCMxITAfBgNVBAMeGABCAEYASQBcAGQAcwBwAGUAaQBnAGgAdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxXmIj8FBaL+94B/fNsBcoNZZraicGsm5+8VtWQIaGdM65q6vgDSQAg4zOkTQCqKh2vlN2NHSZb2XjcrUTWm2Vb279dvkOZfZ1mdQeLjM2LbXvrY4e7qK1dhZy9gZ3Mhvuk3cKPwwPsLNFifOt6OsS8ZzK7/PC+uUKznZtRsCAwEAATAJBgUrDgMCHQUAA4GBADGP1MjZm28GdYy3mQGprHQNDn8fIyBQvhwVwl4SVPxYDTKG7OsUC/QDUzy8vGXm+9qd2Es5creZS1DTAweC60JsJLdmp631FnbG4xJOCRHbR0HWyruhGkN6wPJ0RyJbdUrAcEPG4cfcYwl3oBeL48MfUD56UC0jSfBezUvnOMBX</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<saml:Assertion Version="2.0" ID="_49bc8835-7c9a-4ee2-8087-7cfcbe48375f" IssueInstant="2015-03-26T11:43:13.6835615Z">
<saml:Issuer>Test</saml:Issuer>
<saml:Subject>
<saml:NameID NameQualifier="TestDomain">TestSubject</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2015-03-26T11:48:13.7304370Z" Recipient="Test1" />
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2015-03-26T11:43:13.6835615Z" NotOnOrAfter="2015-03-26T11:48:13.6835615Z">
<saml:AudienceRestriction>
<saml:Audience>TestDomain</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2015-03-26T11:43:13.6835615Z">
<saml:AuthnContext>
<saml:AuthnContextClassRef>AuthnContextClassRef</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="UserId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xmlns:q1="http://www.w3.org/2001/XMLSchema" p7:type="q1:string" xmlns:p7="http://www.w3.org/2001/XMLSchema-instance">1000001</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="UserName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xmlns:q2="http://www.w3.org/2001/XMLSchema" p7:type="q2:string" xmlns:p7="http://www.w3.org/2001/XMLSchema-instance">Manish Pandey</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
Can any one suggest any method to accomplish this?
it depends what kind of encryption you want to use... Basically you would have to encrypt signed assertion and replace assertion node with EncryptedAssertion node.
I recommend using both symmetric and asymmetric encryption.
Using Symmetric key to encrypt the whole of assertion node and then use asymmetric (i.e. certificate public/private key to encrypt symmetric key). I have used our client's certificate public key to encrypt symmetric key so only they can decrypt using their private key.
I have also specified certificate I want to use in web.config...
string samlResponseXml = '<SAML Response Message>'
XmlDocument loginResponseXmlDocument = new XmlDocument();
loginResponseXmlDocument.LoadXml(samlResponseXml);
// Add name spaces
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(loginResponseXmlDocument.NameTable);
namespaceManager.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol");
namespaceManager.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion");
namespaceManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
namespaceManager.AddNamespace("xenc", "http://www.w3.org/2001/04/xmlenc#");
Encrypt(loginResponseXmlDocument, namespaceManager);
private void Encrypt(XmlDocument document, XmlNamespaceManager namespaceManager)
{
// create symmetric key
var key = new RijndaelManaged();
key.BlockSize = 128;
key.KeySize = 256;
key.Padding = PaddingMode.ISO10126;
key.Mode = CipherMode.CBC;
XmlElement assertion = (XmlElement)document.SelectSingleNode("/samlp:Response/saml:Assertion", namespaceManager);
EncryptedXml eXml = new EncryptedXml();
byte[] encryptedElement = eXml.EncryptData(assertion, key, false);
EncryptedData edElement = new EncryptedData
{
Type = EncryptedXml.XmlEncAES256Url
};
const string encryptionMethod = EncryptedXml.XmlEncAES256Url;
edElement.EncryptionMethod = new EncryptionMethod(encryptionMethod);
edElement.CipherData.CipherValue = encryptedElement;
// edElement = EncryptedData
// Now encrypt symmetric key
string certificateDn = ConfigurationManager.AppSettings["CertificateDN"];
X509Certificate2 x509Certificate = GetCertificate(certificateDn);
RSACryptoServiceProvider rsa = x509Certificate.PublicKey.Key as RSACryptoServiceProvider;
byte[] cryptedData = rsa.Encrypt(key.Key, false);
//string data = Convert.ToBase64String(cryptedData);
//byte[] encryptedKey = EncryptedXml.EncryptKey(key.Key, rsa, true);
EncryptedKey ek = new EncryptedKey();
ek.CipherData = new CipherData(cryptedData);
ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);
//EncryptedData edkey = new EncryptedData();
//string data1 = Convert.ToBase64String(encryptedKey);
//edkey.CipherData.CipherValue = System.Text.Encoding.Unicode.GetBytes(data);
rsa.Clear();
XmlDocument encryptedAssertion = new XmlDocument();
// Add name spaces
XmlDeclaration xmlDeclaration = encryptedAssertion.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlElement encryptedRoot = encryptedAssertion.DocumentElement;
encryptedAssertion.InsertBefore(xmlDeclaration, encryptedRoot);
XmlElement encryptedAssertionElement = encryptedAssertion.CreateElement("saml", "EncryptedAssertion", "urn:oasis:names:tc:SAML:2.0:assertion");
encryptedAssertion.AppendChild(encryptedAssertionElement);
string xml = edElement.GetXml().OuterXml;
XmlElement element = AddPrefix(xml, "xenc", "http://www.w3.org/2001/04/xmlenc#");
var encryptedDataNode = encryptedAssertion.ImportNode(element, true);
encryptedAssertionElement.AppendChild(encryptedDataNode);
xml = ek.GetXml().OuterXml;
element = AddPrefix(xml, "xenc", "http://www.w3.org/2001/04/xmlenc#");
var encryptedKeyNode = encryptedAssertion.ImportNode(element, true);
encryptedAssertionElement.AppendChild(encryptedKeyNode);
var root = document.DocumentElement;
var node = root.OwnerDocument.ImportNode(encryptedAssertionElement, true);
root.RemoveChild(assertion);
root.AppendChild(node);
}
Once assertion is encrypted.. this is what it will look like:
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Destination="https://aviva-rpt.distribution-technology.com" ID="_fba2f5af-a430-8001-5cb8-9714f3aeb4bc"
IssueInstant="2015-02-04T16:32:33.446Z" Version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://www.client.sds</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<saml:EncryptedAssertion>
<xenc:EncryptedData>
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
<xenc:CipherData>
<xenc:CipherValue>zjAgkZ=</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
<xenc:EncryptedKey>
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
<xenc:CipherData>
<xenc:CipherValue>DyA22==</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedKey>
</saml:EncryptedAssertion>
</samlp:Response>
Related
I'm incorporating a software license system into a program of mine.
The client asks for a license, sends me the data I need, then I generate an XML file, being the license file that my program must check at the clients side.
So I generate a x509 certificate on my development computer (win10) and sign the license file.
X509Store store = new X509Store(StoreName, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = store.Certificates;
X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, $"CN={CertificateName}", false);
X509Certificate2 cert = signingCert[0]; // has private and public
store.Close();
CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
var exportedKeyMaterial = signingCert[0].PrivateKey.ToXmlString(true);
var key = new RSACryptoServiceProvider(new CspParameters(24));
key.PersistKeyInCsp = true;
key.FromXmlString(exportedKeyMaterial);
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
// LicenseInfo is the info about her computer etc. my client provides, eg. by e-mail
using (TextReader sr = new StringReader(LicenseInfo))
{
doc.Load(sr);
}
SignedXml signedXml = new SignedXml(doc);
signedXml.SigningKey = key;
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
Reference reference = new Reference();
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
reference.Uri = "";
reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(cert));
signedXml.KeyInfo = keyInfo;
signedXml.ComputeSignature();
XmlElement sig = signedXml.GetXml();
doc.DocumentElement.AppendChild(doc.ImportNode(sig,true));
if (doc.FirstChild is XmlDeclaration)
{
doc.RemoveChild(doc.FirstChild);
}
// and here it finally is: the license!
LicenseText = doc.OuterXml;
The signature goes into the license file which will then look like this, after signing:
<License>
<MailAddress>....</MailAddress>
<LicenseNr>8309847560354</LicenseNr>
<RequestTimeStamp>8/15/2019 11:28:47 AM</RequestTimeStamp>
<ExpirationTimeStamp>8/14/2020 11:28:47 AM</ExpirationTimeStamp>
<X5>78-BB-2F-65-4blabla45-A8-B5-4D-82</X5>
<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#rsa-sha256" />
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>Gg9WLq12JSYFh6tatRTCnGbzEzMg8PidcXK4iWwPcXg=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>JdC09BIeHcw8...q24JFVseBZWXOo==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIC8zCCAd+gAwIBAgIQgwuqv2X..........oP7f5f</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</License>
What is in that <X509Certificate/> ?
My public key?
If so, I do not need to include my public key in the program as an embeded resource because it will be in my clients license file, that must be processed anyway...
Correct?
The will not include my private key, I hope...?
Here is how i (try to) verify the license validity (not including the expiration date, only seeing if the license file was not tampered with)
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(Name); // the license file
SignedXml signedXml = new SignedXml(xmlDocument);
XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
RSACryptoServiceProvider Key = new RSACryptoServiceProvider(new CspParameters(24));
Key.ToXmlString(false);
return signedXml.CheckSignature(Resources.PubKey.FromXmlString()); // ????? or what?
So:
1: What is in the X509Certificate in the signature?
2: Verification does not work. Any suggestions?
3: Do I include my public key in the program that checks the license, or is the signature itself the source?
PS:
Please, don't point out that this will not give me 100% security. I know.
My questions are about X509, not about guarding against theft. That is another, much broader, issue. It's interesting, programming this stuff and learning.
I've signed a XML file to send with the proper securities but somehow the service I'm sending detects the file has an invalid signature (X.509 certificate validation it's ok).
I've been searching if it's possible, once I have signed an specific XML, to retrieve the XML signed informations back (like a decryption) to verify if I'm using the right nodes to sign the XML. Could anyone help me?
Ps.: I still have public and private certificate key.
This is the code I used to sign the elements "infEvento" of the XML, and after it, the XML element.
public XmlDocument retornaEvtsXMLAssinados(X509Certificate2 cert, string MensagemXML)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(MensagemXML);
XmlNodeList evtsNode = xmlDoc.GetElementsByTagName("evento");
foreach (XmlElement evtNode in evtsNode)
{
RSACryptoServiceProvider key = new System.Security.Cryptography.RSACryptoServiceProvider();
System.Security.Cryptography.Xml.SignedXml SignedDocument;
var keyInfo = new System.Security.Cryptography.Xml.KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(cert));
key = (System.Security.Cryptography.RSACryptoServiceProvider)cert.PrivateKey;
SignedDocument = new System.Security.Cryptography.Xml.SignedXml(evtNode);
SignedDocument.SigningKey = key;
SignedDocument.KeyInfo = keyInfo;
Reference reference = new System.Security.Cryptography.Xml.Reference();
reference.Uri = "#" + evtNode["infEvento"].Attributes["Id"].Value;
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigC14NTransform(false));
SignedDocument.AddReference(reference);
SignedDocument.ComputeSignature();
XmlElement xmlDigitalSignature = SignedDocument.GetXml();
XmlNode nodeAss = xmlDoc.ImportNode(xmlDigitalSignature, true);
evtNode.AppendChild(nodeAss);
}
return xmlDoc;
}
And here is the XML element:
<?xml version="1.0" encoding="utf-8"?>
<envEvento xmlns="http://www.portalfiscal.inf.br/nfe" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" versao="1.00">
<idLote>1</idLote>
<evento versao="1.00">
<infEvento Id="ID2102103518064328381100910655001000067942126336601001">
<cOrgao>91</cOrgao>
<tpAmb>1</tpAmb>
<CNPJ>53773073000182</CNPJ>
<chNFe>35180643283811009106550010000679421263366010</chNFe>
<dhEvento>2018-07-25T02:47:06-03:00</dhEvento>
<tpEvento>210210</tpEvento>
<nSeqEvento>1</nSeqEvento>
<verEvento>1.00</verEvento>
<detEvento versao="1.00">
<descEvento>Ciencia da Operacao</descEvento>
</detEvento>
</infEvento>
<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#rsa-sha1" />
<Reference URI="#ID2102103518064328381100910655001000067942126336601001">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>BahmhJGVCbcRzzZ2a3IdfoGggSY=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>01MRXk7YiSo9g8OBqR0H4gmYxXBHCFAfoloKacDOYMZr/1Y4kl0GZcfqOCM6+AyxpNmVUYPh860tMklqdTqwXeJR4eceIafJag9lntCD3BuiXnR/O9uP6jxouPu+aGf2fpuVbsOex6WnKG5gPtOnV02cvZ0nB0pMbyhetFEOptq/F8Mv/+wcYsQGnFAFLD2jqqSD0HGeNJPh8C4M6JGh6jjgC8FOnLtihd+cqydNH/OTjDwSczhtEM/3GyeHULf+RJS4DEfRhLLcpdpJAsV9yzSIhkf1ecnVvdjncc4SZdySEOMYhtJLOhQqU6pTGhZS0D0/BiA3O6E6ZTgB1xPUQw==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>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</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</evento>
<evento versao="1.00">
<infEvento Id="ID2102103518064328381100910655001000067986126343904601">
<cOrgao>91</cOrgao>
<tpAmb>1</tpAmb>
<CNPJ>53773073000182</CNPJ>
<chNFe>35180643283811009106550010000679861263439046</chNFe>
<dhEvento>2018-07-25T02:47:06-03:00</dhEvento>
<tpEvento>210210</tpEvento>
<nSeqEvento>1</nSeqEvento>
<verEvento>1.00</verEvento>
<detEvento versao="1.00">
<descEvento>Ciencia da Operacao</descEvento>
</detEvento>
</infEvento>
<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#rsa-sha1" />
<Reference URI="#ID2102103518064328381100910655001000067986126343904601">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>atbTWNxi44DcxulttJidbuNCxQo=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>+wxGkr1l7uFnzlcPFhOSnMN675j9syXlPW9L2UupO1lAienG0GQ9Ta786Wh3/RmqLywfhjob6KXXkh2iiVXAUrOVcQU9akRxwlse93auCEJRff5uQChgKryQycu6XigB/nhNPE50ay8xnhFsSR3nHGYjWcWVnKi6uQAnM69Bx6lOQpvTTh+pSNM2/lXD/eC94b3iKzEi4DkE0yfQ1LRUGd7tUnB0/Y8j+Hu+w8pFYh6Nurabmv1GjNRzpDooZUGxcuWkvtVsFd3VshVqIZ7FKIMnGw8fcsN2h+sv3/OQqe7MJ78z98fMoUv/R1FTklWYqV6vUptK1XnyJ61VbHz1XQ==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>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</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</evento>
</envEvento>
Thanks for the attention
Here is what I currently use for one of mine. Some like adding an additional element may not be needed in your case but, just in case I left it in there.
private static void SignXml(XmlDocument doc, X509Certificate2 cert)
{
var signer = new SignedXmlWithId(doc);
signer.SigningKey = cert.PrivateKey;
signer.KeyInfo = new KeyInfo();
var s = new SecurityTokenReference();
s.Reference = "uuid-639b0-fc-1";
s.ValueType = "http://Something.com";
signer.KeyInfo.AddClause(s);
signer.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
var bodyRef = new Reference("#ID-00008");
var messageRef = new Reference("#ID-00004");
var usernameRef = new Reference("#ID-00001");
bodyRef.AddTransform(new XmlDsigExcC14NTransform());
messageRef.AddTransform(new XmlDsigExcC14NTransform());
usernameRef.AddTransform(new XmlDsigExcC14NTransform());
signer.AddReference(bodyRef);
signer.AddReference(messageRef);
signer.AddReference(usernameRef);
signer.ComputeSignature();
var signData = signer.GetXml();
var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("wsee", "http://stuff.to.add");
nsmgr.AddNamespace("cwsh", "http://more.stuff.to.add");
var security = doc.SelectSingleNode("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsee:Security", nsmgr);
security.AppendChild(doc.ImportNode(signData, true));
}
//Subclass to add namespace when signing
public class SignedXmlWithId : SignedXml
{
public SignedXmlWithId(XmlDocument xml) : base(xml)
{
}
public SignedXmlWithId(XmlElement xmlElement) : base(xmlElement)
{
}
public override XmlElement GetIdElement(XmlDocument doc, string id)
{
// check to see if it's a standard ID reference
var idElem = base.GetIdElement(doc, id);
if (idElem == null)
{
var nsManager = new XmlNamespaceManager(doc.NameTable);
nsManager.AddNamespace("wsu",
"http://wsssecurity.location");
idElem = doc.SelectSingleNode("//*[#wsu:Id=\"" + id + "\"]", nsManager) as XmlElement;
}
return idElem;
}
}
I have been assigned a task where I (the iDP) need to connect to a service provider.
So far I have the code:
public ActionResult SSO(string SAMLRequest)
{
var model = new ApiSsoModel();
try
{
if (SAMLRequest == null)
throw new ArgumentNullException("The parameter \"SAMLRequest\" is null.");
byte[] decoded2 = Convert.FromBase64String(SAMLRequest);
string decoded3 = string.Empty;
using (MemoryStream stream2 = new MemoryStream(decoded2))
{
using (MemoryStream stream3 = new MemoryStream())
{
using (StreamReader reader3 = new StreamReader(stream3))
{
stream2.Position = 0L;
new DeflateStream(stream2, CompressionMode.Decompress).CopyTo(stream3);
stream3.Position = 0L;
decoded3 = reader3.ReadToEnd();
reader3.Close();
}
stream3.Close();
}
stream2.Close();
}
string assertion = System.IO.File.ReadAllText(Server.MapPath("~/assertion.xml"));
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
XmlDocument assertionDoc = new XmlDocument();
assertionDoc.LoadXml(assertion);
XmlDocument response = new XmlDocument();
response.LoadXml(decoded3);
SignedXml signedXml = new SignedXml(assertionDoc);
Reference reference = new Reference();
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;
reference.Uri = "#_79723ebe12aed3704c4d8de6ea16cf90c0d7451da0";
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
reference.DigestMethod = SignedXml.XmlDsigSHA1Url;
reference.DigestValue = Encoding.ASCII.GetBytes("3jdMJaumbeC3UJ16d8VQJWjKQKU=");
signedXml.AddReference(reference);
signedXml.SigningKey = rsaKey;
HMACSHA256 key = new HMACSHA256();
signedXml.ComputeSignature(key);
XmlElement xmlDigitalSignature = signedXml.GetXml();
assertionDoc.GetElementsByTagName("ds:SignatureValue")[0].InnerText = xmlDigitalSignature.InnerText;
model.Base64EncodedAssertion = Convert.ToBase64String(Encoding.ASCII.GetBytes(assertionDoc.InnerXml));
model.Message += "Success";
}
catch (Exception ex)
{
model.Message = ex.Message;
}
return View(model);
}
I am loading up an assertion file which was provided in an SSO 2.0 documentation file
<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="9f84acebb80533147969eac6a0aead9603c807b5b" Version="2.0" IssueInstant="2015-07-08T09:44:20Z" Destination="https://testdata.redpoints.co.uk/saml/consume" InResponseTo="_e4098d80-0783-0133-f409-7cd1c3f7b75b">
<saml:Issuer>https://openidp.feide.no</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#_b9f84acebb80533147969eac6a0aead9603c807b5b">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>3jdMJaumbeC3UJ16d8VQJWjKQKU=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>dewQ7U/QjQtaeUHHk/wgzyCLXi0B6mnmMNCUJgj+taxa/c+HsrKVx97iMbMaoFWRd9Ps9SjNr5P40yC2I5j3Dx9pheBAgKX6RRAl0C7CJM36XZAqWwA1CBlDCqx1H3vTeSeotuOovzKVhnpQj9AL38GmFYqHnNS1e5pCfugI72o=</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<saml:Assertion xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="_79723ebe12aed3704c4d8de6ea16cf90c0d7451da0" Version="2.0" IssueInstant="2015-07-08T09:44:20Z">
<saml:Issuer>https://openidp.feide.no</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#_79723ebe12aed3704c4d8de6ea16cf90c0d7451da0">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>sDFB4zP6PHBacygh64DRtaeowZ8=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>GY1M5iO5yht1JLOAOmFBUdZPtxKZeek5jG77w7Ct6A+H1qbUAbX7u8PmniGdOXkllxPWqB+L4Gtd39WbCEoWiQ9QvY/pVz2xe6xzI9gVsnJBP0alalyCZglnxNpQ2x+692OcpVXnbau4LJoFv2+0zktXPhQEI3CfAyixOpASu1w=</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID SPNameQualifier="https://testdata.redpoints.co.uk/saml/metadata" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_36355e0a362adec0f5753911aff3b14f9b21d9c2b8</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2017-11-08T09:49:20Z" Recipient="https://testdata.redpoints.co.uk/saml/consume" InResponseTo="_e4098d80-0783-0133-f409-7cd1c3f7b75b" />
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2015-07-08T09:43:50Z" NotOnOrAfter="2017-11-08T09:49:20Z">
<saml:AudienceRestriction>
<saml:Audience>https://testdata.redpoints.co.uk/saml/metadata</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2015-07-08T09:15:58Z" SessionNotOnOrAfter="2017-11-08T17:44:20Z" SessionIndex="_066bce0e07565d6a61ae7e94fe95d8bcdd79a3cfd0">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml:AttributeValue xsi:type="xs:string">102112</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
I have tried many different methods to make this work, downloading multiple .net libraries which are meant to help with setting up SSO for the iDP but not had no luck.
My reply might not help you but at least it gives you few ideas.
there are 2 flows in SAML:
Sp-Initiated [Service Provider Initiated]: Service provider starts the flow by sending SSO SAML request to the Idp. Idp server process the request and make sure that user is authenticated and authorized to use this service then Idp sends SSO SAML response to Service provider (SP) contains assertions (data about authenticated user).
Idp-Initiated [Identity Provider Initiated]: Idp authenticate and authorize the user and send SSO SAML Request to Service Provider (Only the second part of the Sp-Initiated).
As you are waiting for SAML request. That means your flow is SP-Initiated.
First you need to generate your meta data and send it to redpoints. This meta data should at least includes your entityId and SSO end point and X.509 cert for sign/encrypt.
You can use onlogin website to generate your metadata
If you already did that. I would recommend you use https://www.componentspace.com/ library. It is fast, efficient and well-maintained. Unfortunately, It is paid but there is a trial period so you can test it.
Have a look on the library documentation on this link
If you use this library, all what you need to do is to add saml.config file as following
<?xml version="1.0"?>
<SAMLConfiguration xmlns="urn:componentspace:SAML:2.0:configuration">
<IdentityProvider Name="YourEntityId"
Description="Description"
LocalCertificateFile="Your certificate private key *.pfx"
LocalCertificatePassword="Your certificate password"/>
<PartnerServiceProviders>
<PartnerServiceProvider Name="https://testdata.redpoints.co.uk/saml/metadata"
Description="Red Point Service Provider"
<!-- those options should be based on redpoint metadata WantAuthnRequestSigned="true"
SignSAMLResponse="false"
SignAssertion="true"
EncryptAssertion="false"-->
AssertionConsumerServiceUrl="https://testdata.redpoints.co.uk/saml/consume"
PartnerCertificateFile="Path to redpoint certificate file .cer"/>
</PartnerServiceProviders>
</SAMLConfiguration>
and add to your action method the following:
SAMLConfigurationFile.Load();
string partnerSP = null;
SSOOptions options = null;
SAMLIdentityProvider.ReceiveSSO(Request, out partnerSP, out options);
string userName = "robert#test.com";
IDictionary<string, string> attributes = new Dictionary<string, string>();
attributes.Add("NameID", "robert#test.com"); // as an example for possible attribute
SAMLIdentityProvider.SendSSO(Response, userName, attributes);
I would recommend you also install browser extension to detect SAML requests/response. This is will help you to see the output that you are sending.
I hope my reply gives you a little help.
There are a number of SAML stacks around - SAML : SAML connectivity / toolkit .
I would definitely suggest that you don't roll your own. You'll fix this only to come across the next problem.
The problem with most of the stacks is that they are client side. You want server side.
Agree with componentspace suggestion - it can do both sides.
Or this one - currently in beta.
Or have a look at the OpenSAML source - it's Java but the principles are the same.
I want to sign a XML with SHA256 by using a self-signed X.509 certificate. I was inspired by many articles in Stackoverflow and use this code:
X509Certificate2 cert = new X509Certificate2();
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 cert2 in store.Certificates)
{
if (cert2.Subject == "CN=TestCerificate")
{
cert = cert2;
break;
}
}
store.Close();
CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
var exportedKeyMaterial = cert.PrivateKey.ToXmlString(true);
var key = new RSACryptoServiceProvider(new CspParameters(24));
key.PersistKeyInCsp = false;
key.FromXmlString(exportedKeyMaterial);
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load("test.xml");
SignedXml signedXml = new SignedXml(doc);
signedXml.SigningKey = key;
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
Reference reference = new Reference();
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
reference.Uri = "";
reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(cert));
signedXml.KeyInfo = keyInfo;
signedXml.ComputeSignature();
doc.Save("testSig.xml");
Afterwards, the generated signed XML part of "testSig.xml" looks like this:
<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#dsa-sha1" />
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>ghOEPeYtAUs5Kb8VMOCIS3f2wIY=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>HANI0GrICbyc5tlmvtU9cB7txdxtuY4uDsntp5XVzaRQbts76ff3Qg==</SignatureValue>
</Signature>
As you can see the XML says that "SHA1" was used to sign the XML instead (see nodes "SignatureMethod" & "DigestMethod"). But I would expect, that the SHA256-URLs have to be stated in these nodes. Is this assumption correct? If yes, does anybody know how to solve this problem? I use C# 4.6.0.
With best regards,
Michael
While you successfully called signedXml.ComputeSignature() that just does the computation, it doesn't insert a signature element into the document (the XmlDocument you pass in the constructor is just what document GetXml()'s node will parent to).
You need to call signedXml.GetXml() (after ComputeSignature) to get the computed ds:Signature element, then insert that into your document.
The fact that your document has a signature node already in it is confusing. My first thought was that test.xml already had that signature in it, but your comment says that it was just some oops code from elsewhere. Lesson learned, I guess :).
I know there is a SignedXml class for signing XML document. However I am trying to calculate the signature value on my own, to understand what exactly is happening. More exactly, I am trying to sign a soap:Body element of SOAP message.
I have manually crated the Signature tag so it matches the template. Also I have succesfully calculated the digest of and inserted this value into DigestValue tag. However I am not able to calculate correct value for the SigantureValue tag.
My approach is:
Canonicalize the SignedInfo tag using excl n14n transform
Hash the canonicalized data using SHA256
Use RSACryptoServiceProvider to sign the hash value
My code looks something like this:
// 1 Canonicalize the SignedInfo tag
XmlDsigExcC14NTransform serializer = new XmlDsigExcC14NTransform();
XmlDocument doc = new XmlDocument();
string toBeCanonicalized = signedInfoTag.OuterXml;
doc.LoadXml(toBeCanonicalized);
serializer.LoadInput(doc);
string c14n = new StreamReader((Stream)serializer.GetOutput(typeof(Stream))).ReadToEnd();
// 2 Hash the SignedInfo tag
SHA256 HashAlg = SHA256.Create();
byte[] hash = HashAlg.ComputeHash(Encoding.UTF8.GetBytes(c14n));
// 3 Sign the hash
byte[] signature;
using (RSACryptoServiceProvider csp = new RSACryptoServiceProvider())
{
csp.ImportParameters(((RSACryptoServiceProvider)mCertificate.PrivateKey).ExportParameters(true));
signature = csp.SignData(Encoding.UTF8.GetBytes(c14n), "SHA256");
}
signValueTag.InnerText = Convert.ToBase64String(signature);
What I am doing wrong?
The example of valid SOAP message is here:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1">
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-A72D6FD4C41B1F545F14700558816386">MIID6zCCAtOgAwIBAgIEAQAAAzANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJDWjEaMBgGA1UEAwwRR0ZSIEVFVCB0ZXN0IENBIDExLTArBgNVBAoMJEdlbmVyw6FsbsOtIGZpbmFuxI1uw60gxZllZGl0ZWxzdHbDrTAeFw0xNjA1MTkxMjQ1MDJaFw0xODA1MTkxMjQ1MDJaMFMxCzAJBgNVBAYTAkNaMRUwEwYDVQQDDAxDWjEyMTIxMjEyMTgxFzAVBgNVBAoMDk9zb2JhIEZ5emlja8OhMRQwEgYDVQQFEwtUMDAwMDAwMDAwMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMt0eW9n+RB0PSawKSJbtAg3j7e1I5p7P9OvEj0n9raEMI496Zuw7s4VaE8JEX4iowjWhlPIOPljDiAXX6HgZzH4PDps0rFm388KZxj7Ek/ZLyyh5jRovc0Yccfgm3i2huBepk7ZtifZXOZzDEDT0CZsxRpypZJp9PK6SOdj2zPIc11F+prwsGQCDAZsRtama5/W5qn2YUWjjk+4c5Zu3TcknC7bcp1dg7RJ9yMtNiYPY7LNV3uWQhAXZVFpmOpbfYwT1F8H3/UrWDSJ5zrHshICPreMyZ0skU9SUANQ8QQKE6lSlgSs59YaeEmCyGtpttVjN+iR/L9M9FRtq3ZhZz0CAwEAAaOBwTCBvjAeBgNVHREEFzAVgRNlcG9kcG9yYUBmcy5tZmNyLmN6MB8GA1UdIwQYMBaAFHpa/A3L7DamDdppGWaMm++Cw6k0MB0GA1UdDgQWBBQbyTbuGBZdorOZZm7usMraGAJ2STBMBgNVHSAERTBDMEEGCmCGSAFlAwIBMAIwMzAxBggrBgEFBQcCAjAlGiNUZW50byBjZXJ0aWZpa2F0IEpFIFBPVVpFIFRFU1RPVkFDSTAOBgNVHQ8BAf8EBAMCBsAwDQYJKoZIhvcNAQELBQADggEBAC3L8Bm7ZlWui9xWrjM00SlvCokpc2ldGCxNvj4hANaISoLRdPVZAPeLd1X4KsRyxOIazR5oq3EKVZV1ZP3sCF4QFL+SqurkPiBbIrrbABDLyDpf/8DIfyA1x/+zNpN9ul9j9Ca1739P4L1x3wpQcYhEuvSrTiLztndlJb69LXgYZOFfqcBSRedRuMwRdtux9OWkkZjrd9wNHTCDOIfOPaPRRoq5IPHP32shsXaTLvhsT7ktvR5Fr/SQ8CkWq3U6tdcOQRN35ZWyYSyOd5/vkJqK773R/gAeBUE80gpLMdqgVj8HaD7RlHrYyYJEVUI9gbctTfUIJW/9LZ3K78JLXXg=</wsse:BinarySecurityToken>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-A72D6FD4C41B1F545F147005588163810">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#id-A72D6FD4C41B1F545F14700558816389">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList=""/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>iiyihYsFMjO7QxIVCauydehAhjSm5LZlRGm3lT0VFY0=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>cGbhgNKCwrmUPXg2AKgqs1mceNcywK8BvrmmrOH627/3vadzKVnPiTn6ZaLBAcV1pYgTpNvh7RvAa8uZYXmS77YCQcYIOErbWKSTDVwBWv63d8fLm9Ljpx/1/PZrI7zSeIafXTLwPB2Lzt239ylZWPdhfg9XMhS43k4p7u1DZerVeRNSi76Q8u6jIWadDIQkn9mVEbhL5RIRGPoGJBof9QQVk42NHChdESW2RFXG7SSs2VYmdZ+IQUdEC7uPFoT/vxK2My1hGhYhvl6HNbMd5VIz/xMlDPrOCzbLWkA7oqyqSboTCObwkTwD2V20sxn6rb8mtak55zYaGXJldno66g==</ds:SignatureValue>
<ds:KeyInfo Id="KI-A72D6FD4C41B1F545F14700558816387">
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STR-A72D6FD4C41B1F545F14700558816388">
<wsse:Reference URI="#X509-A72D6FD4C41B1F545F14700558816386" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</SOAP-ENV:Header>
<soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-A72D6FD4C41B1F545F14700558816389">
<Trzba xmlns="http://fs.mfcr.cz/eet/schema/v3">
<Hlavicka dat_odesl="2016-09-19T19:06:37+02:00" prvni_zaslani="false" uuid_zpravy="f5ce1350-e688-4247-b1af-3d2bc592b83c"/>
<Data celk_trzba="34113.00" cerp_zuct="679.00" cest_sluz="5460.00" dan1="-172.39" dan2="-530.73" dan3="975.65" dat_trzby="2016-08-05T00:30:12+02:00" dic_popl="CZ1212121218" id_pokl="/5546/RO24" id_provoz="273" porad_cis="0/6460/ZQ42" pouzit_zboz1="784.00" pouzit_zboz2="967.00" pouzit_zboz3="189.00" rezim="0" urceno_cerp_zuct="324.00" zakl_dan1="-820.92" zakl_dan2="-3538.20" zakl_dan3="9756.46" zakl_nepodl_dph="3036.00"/>
<KontrolniKody>
<pkp cipher="RSA2048" digest="SHA256" encoding="base64">D84gY6RlfUi8dWdhL1zn0LE0s+aqLohtIxY0y88GoG5Ak8pBEH3/Ff2aFW7H6fvRxDMKsvM/VIYtUQxoDEctVGMSU/JDf9Vd0eQwgfLm683p316Sa4BUnVrIsHzwMyYkjpn66I072G2AvOUP4X5UiIYtHTwyMVyp+N/zzay3D7Q619ylDb6puN2iIlLsu+GNSB9DvsQbiLXPH6iK0R9FpR15v2y+0Uhh8NNJKl7O8Us9jbgokrA9gze+erQbhmwTm2nn2+7JGrPDqhyhwWZNLUziGSbC99wJpkEnIs0das/4hFNE3DnLvv4MsXwWCLOUZty6t6DAijlCzQj7KFKw0g==</pkp>
<bkp digest="SHA1" encoding="base16">8F8ABFEB-B76E7064-343A1460-6C6E6D86-B0F99C24</bkp>
</KontrolniKody>
</Trzba>
</soap:Body>
</soap:Envelope>
After banging my head against the wall trying to encrypt, hash, sign, with the certificate keys, I decided to check if there was some source code available for the SignedXml class. Thank God there is a reference source for .NET. So I went to the SignedXml.ComputeSignature method, to see how it worked. TL;DR, here is the code, based on those sources:
// Get signature description (using signature method algorithm http://www.w3.org/2001/04/xmldsig-more#rsa-sha256)
var signatureDescription
= System.Security.Cryptography.CryptoConfig.CreateFromName(System.Security.Cryptography.Xml.SignedXml.XmlDsigRSASHA256Url) as System.Security.Cryptography.SignatureDescription;
if (signatureDescription == null)
throw new System.Security.Cryptography.CryptographicException("SignatureDescriptionNotCreated");
// Get hash algorithm from signature description
System.Security.Cryptography.HashAlgorithm hashAlg = signatureDescription.CreateDigest();
if (hashAlg == null)
throw new System.Security.Cryptography.CryptographicException("CreateHashAlgorithmFailed");
// Load SignedInfo OuterXml in a separate XmlDocument, and canonicalize
var doc = new System.Xml.XmlDocument();
string toBeCanonicalized = signedInfoTag.OuterXml;
doc.LoadXml(toBeCanonicalized);
var transform = new System.Security.Cryptography.Xml.XmlDsigExcC14NTransform();
transform.LoadInput(doc);
byte[] hashvalue = transform.GetDigestedOutput(hashAlg); // hashvalue is not used, but I
// think this process allows to
// use hashAlg to get the
// SignatureValue later
// Create signature formatter using certificate's private key
System.Security.Cryptography.AsymmetricSignatureFormatter asymmetricSignatureFormatter
= signatureDescription.CreateFormatter(mCertificate.PrivateKey);
// Get signature value
byte[] signatureValueBytes = asymmetricSignatureFormatter.CreateSignature(hashAlg);
// Set signature value to node text, as Base64 string
signValueTag.InnerText = Convert.ToBase64String(signatureValueBytes)
Try to use
string toBeCanonicalized = signedInfoTag.InnerXml;
instead of
string toBeCanonicalized = signedInfoTag.OuterXml;
Complete code:
// 1 Canonicalize the SignedInfo tag
XmlDsigExcC14NTransform serializer = new XmlDsigExcC14NTransform();
XmlDocument doc = new XmlDocument();
string toBeCanonicalized = signedInfoTag.InnerXml;
doc.LoadXml(toBeCanonicalized);
serializer.LoadInput(doc);
string c14n = new StreamReader((Stream)serializer.GetOutput(typeof(Stream))).ReadToEnd();
// 2 Hash the SignedInfo tag
SHA256 HashAlg = SHA256.Create();
byte[] hash = HashAlg.ComputeHash(Encoding.UTF8.GetBytes(c14n));
// 3 Sign the hash
byte[] signature;
using (RSACryptoServiceProvider csp = new RSACryptoServiceProvider())
{
csp.ImportParameters(((RSACryptoServiceProvider)mCertificate.PrivateKey)
.ExportParameters(true));
signature = csp.SignData(Encoding.UTF8.GetBytes(c14n), "SHA256");
}
signValueTag.InnerText = Convert.ToBase64String(signature);