Discuss this help topic in SecureBlackbox Forum
XML: Decrypt XML node(s)
After you called TElXMLDecryptor.Decrypt() method to perform decryption, you need to check the value of TElXMLDecryptor.EncryptedDataType. If the property value is xedtElement, the decrypted node is contained in TElXMLDecryptor.DecryptedNode property. If the property value is xedtContent, then the decrypted nodes can be contained in TElXMLDecryptor.DecryptedNode property if there was only one node decrypted, or in TElXMLDecryptor.DecryptedNodeList property, if there were several nodes decrypted.
After you've decrypted the node(s), you need to put them back to the right place of the document. You need to replace the EncryptedData element with the node(s) that were decrypted. This is done using ReplaceChild() method of the parent node, if you have just one decrypted node, or using InsertBefore() method of the parent node when you need to insert several elements. Note, that TElXMLDOMNodeList class, which contains the nodes in DecryptedNodeList property, owns the nodes, so you can't add those nodes directly. You need to use CloneNode() method of the node and add the clone to the document (as the original will be destroyed in future).
C#:
byte[] Decrypt(TElXMLDOMElement EncryptedDataElement, byte[] UserKey)
{
TElXMLDecryptor Decryptor = new TElXMLDecryptor(null);
TElXMLKeyInfoSymmetricData SymKeyData = new TElXMLKeyInfoSymmetricData(true);
try
{
Decryptor.Load(EncryptedDataElement);
if (Decryptor.EncryptKey)
throw new Exception("Encrypted keys are not supported by this short sample.");
// setup the key
SymKeyData.Key.Key = UserKey;
Decryptor.KeyData = SymKeyData;
int k = Decryptor.Decrypt(EncryptedDataElement.OwnerDocument);
if (k != SBXMLEnc.Unit.SB_XML_ENC_ERROR_OK)
{
if ((!Decryptor.EncryptKey && (k == SBXMLEnc.Unit.SB_XML_ENC_ERROR_INVALID_KEY)) ||
(Decryptor.EncryptKey && (k == SBXMLEnc.Unit.SB_XML_ENC_ERROR_INVALID_KEK)))
throw new Exception("Decryption failed. Bad key or data is corrupted");
else
throw new Exception(string.Format("Decryption failed. Error code: {0}", k));
}
if (Decryptor.EncryptedDataType != SBXMLSec.Unit.xedtExternal)
{
// additionally, we can replace xenc:EncryptedData element with decrypted node(s)
TElXMLDOMNode ParentNode = EncryptedDataElement.ParentNode;
if (Decryptor.DecryptedNode != null)
{
// replace
ParentNode.ReplaceChild(Decryptor.DecryptedNode, EncryptedDataElement);
Decryptor.DecryptedNode = null;
}
else
if ((Decryptor.EncryptedDataType == SBXMLSec.Unit.xedtContent) && (Decryptor.DecryptedNodeList != null))
{
for (int i = 0; i < Decryptor.DecryptedNodeList.Length; i++)
ParentNode.InsertBefore(Decryptor.DecryptedNodeList.get_Item(i).CloneNode(true), EncryptedDataElement);
ParentNode.RemoveChild(EncryptedDataElement);
}
}
// return the decrypted data
return Decryptor.DecryptedData;
}
finally
{
Decryptor.Dispose();
SymKeyData.Dispose();
}
}
Delphi:
function Decrypt(EncryptedDataElement : TElXMLDOMElement; const UserKey : ByteArray) : ByteArray;
var
Decryptor : TElXMLDecryptor;
SymKeyData : TElXMLKeyInfoSymmetricData;
ParentNode : TElXMLDOMNode;
i, k : Integer;
begin
Decryptor := TElXMLDecryptor.Create(nil);
SymKeyData := TElXMLKeyInfoSymmetricData.Create(True);
try
Decryptor.Load(EncryptedDataElement);
if Decryptor.EncryptKey then
raise Exception.Create('Encrypted keys are not supported by this short sample.');
// setup the key
SymKeyData.Key.Key := UserKey;
Decryptor.KeyData := SymKeyData;
k := Decryptor.Decrypt(EncryptedDataElement.OwnerDocument);
if k <> SB_XML_ENC_ERROR_OK then
begin
if (not Decryptor.EncryptKey and (k = SB_XML_ENC_ERROR_INVALID_KEY)) or
(Decryptor.EncryptKey and (k = SB_XML_ENC_ERROR_INVALID_KEK)) then
raise Exception.Create('Decryption failed. Bad key or data is corrupted')
else
raise Exception.CreateFmt('Decryption failed. Error code: 0x%x', [k]);
end;
// return the decrypted data
Result := Decryptor.DecryptedData;
if Decryptor.EncryptedDataType <> xedtExternal then
begin
// additionally, we can replace xenc:EncryptedData element with decrypted node(s)
ParentNode := EncryptedDataElement.ParentNode;
if Assigned(Decryptor.DecryptedNode) then
begin
// replace
ParentNode.ReplaceChild(Decryptor.DecryptedNode, EncryptedDataElement);
Decryptor.DecryptedNode := nil;
end
else
if (Decryptor.EncryptedDataType = xedtContent) and Assigned(Decryptor.DecryptedNodeList) then
begin
for i := 0 to Decryptor.DecryptedNodeList.Length - 1 do
ParentNode.InsertBefore(Decryptor.DecryptedNodeList.Item[i].CloneNode(True), EncryptedDataElement);
ParentNode.RemoveChild(EncryptedDataElement);
end;
end;
finally
FreeAndNil(Decryptor);
FreeAndNil(SymKeyData);
end;
end;