Friday, August 31, 2018

WSSE - XML SOAP security and key encryption and storing (EncryptedData/EncryptedKey)

Leave a Comment

I have now spent the last couple of days to find documentation about this..

I need to send a XML via SOAP with the WSSE security header, but don't know how to encrypt and store the encrypted keys

Here is an example

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">     <soap:Header>         <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">             <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EK-1B758D26C51BFCD86614340101135741">                 <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>                 <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">                     <wsse:SecurityTokenReference>                         <wsse:KeyIdentifier 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">MIIDODCCAiCgAwIBAgIGAU0FlCVCMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxCYW5rIENvbm5lY3QxFTATBgNVBAsTDEJhbmsgQ29ubmVjdDEdMBsGA1UEAxMUQmFuayBDb25uZWN0IElBLXRlc3QwHhcNMTUwNDI5MTQyODI0WhcNMTgwNDI5MTQyODI0WjAcMRowGAYDVQQDExFiYW5rIGNvbm5lY3QtdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI23KdtaRKPTFTe/A1PnsF9dpSlTiXurKmio0OCgTP9wClHwync3JsInRwGTooA20P9zWobUnEFbEiAgRVYCxuYoldRE6NLhSC854/YTjMBeevH1TNa38lpavGiI4UwFhg70U9/JuYs21hoFyzVfaWlVfOkAMm1U/n4wHq6FZW461S5PY4A/UI1Mr8WgeIHU9GqMBtFvjynzq3SLenOPgdmKtyJ3V8EOU+DlgwKmDbxMVMtYNDZtoQvOWnuvlJ6ICDcqcW7OUkmwCKodjxxPvrdaPxyZDhT7h4FgRtrAOS8qR6L7x9D4ZIoxOMPudGvr99OSb4KVtaAEt/R7hKxG3OsCAwEAAaNCMEAwHwYDVR0jBBgwFoAU680YSkZnx1IaJAmI49LlTGiia0wwHQYDVR0OBBYEFMaWOY7Vf/iB3WVA96j5kRtbF8prMA0GCSqGSIb3DQEBCwUAA4IBAQAJ+bssSFWE6KsYT7HSDKag4Eot7yNGMY4Don/MilDnOREdu20QUS131DKrSkpBQiCXbyRUQjUoun4yue0EG+rlG3QUIlNNdJ4KZJB+dTYdLUV7XTYJNPimKAmoZ+PFNvT1eGgWcMT+MbTfpk0mw0V8IprYGa8UPchd6vtSVwpbTcPc/F4bgUTlm/V+FG4bQS61gF0koj0DEZjzat7CBHpozRgfRlXgwu26vnhWGc99uKH4GAKN4JpqPi/6Yz+7iQNJUC3yeezgBxFrIXuLpkBZSP4zunf9VxsICnxkFUXOTuYBdcbhPNzqMknD5ijFcFRZITwdv7x3uJGLkM7iUfBp</wsse:KeyIdentifier>                     </wsse:SecurityTokenReference>                 </ds:KeyInfo>                 <xenc:CipherData>                     <xenc:CipherValue>af9+FhA91ytLwjeRvTYJsRCkhjHmAQGwqYwMBoNZBn7BZhF/a6EUpM9ByarVhx1SRCpjW5fb8tBVuJO1ZkjfTUZ5EAh/oDLbkmwPdSAAVzmAURHwCq3XQgMZV3lAczlLnPamxjjZBCGqxvAmBo1CvFFPC4AcBedqY92mP8XGyVHpS7JYKOxqXK2vUA1by7371x+Mu0aoS2zJPyPLa1IPwOYgR9qicmWz1RNPiEVA8ZBCN0NRyg7FLJxdUcE81z+1SjButBo2j3qcwkNcecHzZAnweY+LSWp3H5JA3WNzUHUuvFHEaPzT5jd7fUI16xo8NLK8/Rd8Eq/zDD+T3baeVQ==</xenc:CipherValue>                 </xenc:CipherData>                 <xenc:ReferenceList>                     <xenc:DataReference URI="#ED-1B758D26C51BFCD86614340101135852"/>                 </xenc:ReferenceList>             </xenc:EncryptedKey>         </wsse:Security>         <technicalAddress xmlns="http://example.com/schema/2014" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"/>         <activationHeader xmlns="http://example.com/schema/2014" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#">             <organisationIdentification>                 <mainRegistrationNumber>8079</mainRegistrationNumber>                 <isoCountryCode>DK</isoCountryCode>             </organisationIdentification>             <functionIdentification>112233445566778899</functionIdentification>             <erpInformation/>             <endToEndMessageId>d28b6a7dad414014a59029ef1a7e84d4</endToEndMessageId>             <createDateTime>2015-06-11T10:08:33.258+02:00</createDateTime>         </activationHeader>     </soap:Header>     <soap:Body>         <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="ED-1B758D26C51BFCD86614340101135852" Type="http://www.w3.org/2001/04/xmlenc#Content">             <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>             <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">                 <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey">                     <wsse:Reference URI="#EK-1B758D26C51BFCD86614340101135741"/>                 </wsse:SecurityTokenReference>             </ds:KeyInfo>             <xenc:CipherData>                 <xenc:CipherValue>dTSVuEJ90OYguQOsOz2ZtcE2mybwuvVl19pp7/e5yuvNygx3w5v+prpEvbjYLauiIAB3lrVDK2astJeYJGnDbaVJVeU0YqH5ItYVn7Wz36jJM52KB+UNbYo8EdTKYjsZuADzH+tAoA+pwYxGBXMEQctNI+C711HgP2hbpHNYOG7nAMOIrP/0B3FCy+st+9CbYlwAEENreTYunEEA41hciFnWCsIx0el7OeuiA6V51fAmvrF19RPNKwaptvbvmVdKj//RQ/0U1kRny16mDnFfX92bI3HBQm4XJA0nEfSvio7EUAAdhe77GMfu7+JELqXNowPGPLlvrbCFYnQhxGRITHtTIEbtJA6MKtBzHgjtw5pt7oWxKgGUnaJTfOPOSv43RLFGggkT/+gTjnZOagu8hhXp0x5HXJuZzw90aIS3jAfSPDc2ivct4WhWk0wcuQyC2rAh4I7gtiR+LqJJGqvucw4S+NR95FunKHKEW4yasKW1oU31/rRbp4Bmwo6BPsQlxnaSHPtk68IVkYDBslz1A5gOP+M/Iam2WI02y6sE/7aAH1ruN3pZlVuYFc3JDNHOPOvevP110d60lroknGdc9vxcFfj48OCKw/8Ed6tiXtAvk0Qu9Qt4ZyLUoPKIWEqjdLjwVadTDJQFAxRptNgiCos7s0czadUu7FNCRxfndjDxhA7trvys44ufEyK++YzZIgNu3r4dywNI22Nm+JZtLj+rX8ARE6FTPlxGBD0SSdXsfCfY2N1ytBBHQRnPsVaHK1p7KOhwQVbqEupcGyvaRolnymOzDLGFdS06OGYFrYXdgIbuqYtZP8QerXtUl0sWNAvvqHSPCQcpKecpMEecar+FUVwLEA+H1wzOprCMbRR+EgIboeDqQ7GxXqugkuFyvnlLDgxnaWhEhQb/5kAcQmnyUZ57MhDcUJqqQ4Cdmwrcxho1P+YqWY9yn0E86F+hl5976a/gH5KBobB84OWmgcX42eAmqpJf+8c8SuBv+7NctbQOk21aYlFEpkwSme/kG1/edtyoHQH/hF0RB1cT8g+u9S9AK2rs3s2G+Ap0U5oyY8pqJalGdZSBudE0sU4mhOV8trtx0FrN9A7pNkTcGPH25nCtyIz6rzR+DP8Mtgw5385s5ivVlDb+z74Wbh6iu7ZkVAogNTpUYU/1BxDXWJqFMkFmfziNxQ5AQqm1vGlBzXifoQkUFX1riutNphmu0Hs+7KMmMLvtW2cXmQDpkHFKVheeN4w7pBCEZ8KhZ0VTOwRZcdvrNcpYfXM13/QdTHQmCqqwgS/VvlUFz7PDn0/OKo6moUic8W6b1iEvd3kfc7QkunxoOUoJr4RwJ+PqCzN6PxQivAFA2tmDPc8qEa1PAdxTeNFoR/6dNQRojouuJq3C1LrbmGf6lQPvKi3KeKHXyjmDr7Tve+al2tcWJVr+1qEM3/XuthoiZbuTDxYUjZ2nf2fhHrmNcfvrfNxSNHVdQPp2R9Rf3eGxlRJsmRpef66VbYhOpmiH4xmq45EWiyBZmYm+tZtjsP51EDMIvdFbVRSGO/hMqURrDSsJXJeot27Iup2s0P2n/6a9k0c4SVvf/WXNN5x9JNvjU97bQNDQRfonJmo9pRYYHl1tSqNIYBK7KsMH+qr1vmiJuhrXUuL/RtOKvE9KXQ8kGoC9oF5rFn21z40ElxG5XRTASg==</xenc:CipherValue>             </xenc:CipherData>         </xenc:EncryptedData>     </soap:Body> </soap:Envelope> 

First of all I have never worked with SOAP before so chances I do things wrong has pretty good odds :)

The body of the SOAP request is encrypted with AES-256-CBC, a 16 char random-generated iv and a 16 char random-generated key. My first problem is how the symmetric key is stored in the security header?

Have found something here, but I need more details https://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html#aes256-cbc

How are the iv and the key stored in CipherValue in the header?

When sending the XML request to the webservice I get this error

23-08-2018 12:50:02   General exception:Padding is invalid and cannot be removed. 23-08-2018 12:50:02   Stack trace:    at System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[] block, Int32 offset, Int32 count)    at System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)    at System.Security.Cryptography.Xml.EncryptedXml.DecryptData(EncryptedData encryptedData, SymmetricAlgorithm symmetricAlgorithm)    at SomeClassCore.XmlSecurity.Decryptor.DecryptData(Byte[] symmetricKey)    at SomeClassCore.SecurityServiceImpl.UnwrapRequest(ServiceRequest serviceRequest)    at BD.BCA.MessageHandler.MessageHandler.ProcessRequest(HttpContext context) 

The way I store the symmetric key is like this

$key_length = 16; $cipher     = 'AES-256-CBC';  $iv     = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher)); $key    = openssl_random_pseudo_bytes($key_length);  // Encryption of the body $encrypted_body = openssl_encrypt($body, $cipher, $key, 0, $iv);  // length 32 chars $symmetric_key = $iv.$key;  // The symmetric key is then encrypted via RSA and the public key.. $public_cert = openssl_pkey_get_public('the public cert'); openssl_public_encrypt($symmetric_key, $encrypted_key, $public_cert, OPENSSL_PKCS1_OAEP_PADDING);  // encrypted key is put in header EncryptedKey $encrypted_key;  // encrypted body is put in EncryptedData $encrypted_body; 

The part with the RSA encryption/decryption seems to work according to the error log right? It fails when decrypting the AES right?

This is how the symmetric key, and the iv and key alone looks like when dumping them with var_dump

symmetric key (not encrypted): string(32) "��J�    v��rb։�3�U���_$6p9�;p" iv: string(16) "��J�    v��rb։�" key: string(16) "3�U���_$6p9�;p" 

Symmetric key (base64 and not encrypted): 1/hKgBsfCXaUn3IaYtaJyzP0EFXK0uJfJDZwOR3AO3A=

update

Have searched a bit more.. Maybe the iv must be a part of the stored data. But it's still not working? Same error as above

class Encryption {     public function data_encrypt(string $data, string $cipher, int $key_length): Array{         $iv     = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));         $key    = openssl_random_pseudo_bytes($key_length);          return [             'data'  => base64_encode($iv.openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA, $iv)),             'key'   => $key         ];     }      public function key_encrypt(string $key): string{         $public_cert = openssl_pkey_get_public('contents of public cert');         openssl_public_encrypt($key, $data, $public_cert, OPENSSL_PKCS1_OAEP_PADDING);         openssl_free_key($public_cert);          return base64_encode($data);     } }  $Enc = new Encryption; $data_encrypted = $Env->data_encrypt('The message I want to encrypt', 'AES-256-CBC', 32);  //  This base64 encoded string goes to <EncryptedData> $data_encrypted['data'];  //  This base64 encoded string goes to <EncryptedKey> in the header $Enc->key_encrypt($data_encrypted['key']); 

0 Answers

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment