However, what is missing, is advice about how to encrypt XML content, i.e. in the famous XML example
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
you might not want to decrypt the whole <creditcard> element, but rather its two subnodes <number> and <expiry>. This is necessary when the http://www.w3.org/2001/04/xmlenc#Content standard is used.
I just reuse the code from the how-to-article and add specific lines for the content-encryption:
For Encryption, you use this method:
public static XmlDocument Encrypt(XmlDocument doc, string elementToEncryptName, X509Certificate2 cert)
{
// Check the arguments.
if (doc == null)
throw new ArgumentNullException("doc");
if (elementToEncryptName == null)
throw new ArgumentNullException("elementToEncryptName");
if (cert == null)
throw new ArgumentNullException("cert");
////////////////////////////////////////////////
// Find the specified element in the XmlDocument
// object and create a new XmlElemnt object.
////////////////////////////////////////////////
XmlElement elementToEncrypt = doc.GetElementsByTagName(elementToEncryptName)[0] as XmlElement;
// Throw an XmlException if the element was not found.
if (elementToEncrypt == null)
{
throw new XmlException("The specified element was not found");
}
//////////////////////////////////////////////////
// Create a new instance of the EncryptedXml class
// and use it to encrypt the XmlElement with the
// a new random symmetric key.
//////////////////////////////////////////////////
// Create a 256 bit Rijndael key.
RijndaelManaged sessionKey = new RijndaelManaged();
sessionKey.KeySize = 128;
// Set RSA crypto provider to certificate's public key
RSACryptoServiceProvider alg = (RSACryptoServiceProvider) cert.PublicKey.Key;
// Encrypt the content of the XML element
EncryptedXml eXml = new EncryptedXml();
byte[] encryptedElement = eXml.EncryptData(Encoding.UTF8.GetBytes(elementToEncrypt.InnerXml), sessionKey);
////////////////////////////////////////////////
// Construct an EncryptedData object and populate
// it with the desired encryption information.
////////////////////////////////////////////////
EncryptedData edElement = new EncryptedData();
edElement.Type = EncryptedXml.XmlEncElementContentUrl;
//edElement.Id = encryptionElementId;
// Create an EncryptionMethod element so that the
// receiver knows which algorithm to use for decryption.
edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES128Url);
// Encrypt the session key and add it to an EncryptedKey element.
EncryptedKey ek = new EncryptedKey();
byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, alg, true);
ek.CipherData = new CipherData(encryptedKey);
ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSAOAEPUrl);
edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
//// Create a new KeyInfo element.
KeyInfo ki = new KeyInfo();
ki.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.EndCertOnly));
// Add the KeyInfoName element to the
// EncryptedKey object.
ek.KeyInfo = ki;
// Add the encrypted element data to the
// EncryptedData object.
edElement.CipherData.CipherValue = encryptedElement;
////////////////////////////////////////////////////
// Replace the element from the original XmlDocument
// object with the EncryptedData element.
////////////////////////////////////////////////////
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, true);
sessionKey.Clear();
return doc;
}
The decryption can be taken from the MSDN example:
public static XmlDocument Decrypt(XmlDocument doc)
{
// Check the arguments.
if (doc == null)
throw new ArgumentNullException("doc");
// Decrypt the XML document, with the help of the private key from the certification store
EncryptedXml exml = new EncryptedXml(doc);
exml.DecryptDocument();
return doc;
}
The calling code will be:
X509Certificate2 cert = new X509Certificate2("xxx.pfx", "xxx");
var encrypted = Encrypt(xmlDoc, "creditcard", cert);
var decrypted = Decrypt(encrypted);
No comments:
Post a Comment