DI Management Home > Cryptography > Encryption in XML documents using XMLENC

Encryption in XML documents using XMLENC


This page looks at encryption in XML documents using the W3C recommendation XML Encryption Syntax and Processing [XMLENC]. It looks at the common ways to encrypt all or part of an XML document, some of the encryption algorithms that can be used, some recommendations about insecure algorithms, and links to code to carry out encryption and decryption. We don't cover everything, just the most common encryption algorithms, and we don't look at signatures here. If you want to know more about signatures in XML documents, see Signing an XML document using XMLDSIG (Part 1) and XMLDSIG (Part 2).

The EncryptedData element

An XML document encrypted using XMLENC will have at least one EncryptedData element. A shorthand form of the structure of the EncryptedData element from [XMLENC] is as follows.

<EncryptedData Id? Type? MimeType? Encoding?>
  <EncryptionMethod/>?
  <ds:KeyInfo>
    <EncryptedKey>?
    <AgreementMethod>?
    <ds:KeyName>?
    <ds:RetrievalMethod>?
    <ds:*>?
  </ds:KeyInfo>?
  <CipherData>
    <CipherValue> | <CipherReference URI?>
  </CipherData>
  <EncryptionProperties>?
</EncryptedData>

where "?" denotes zero or one occurrence; "+" denotes one or more occurrences; "*" denotes zero or more occurrences; and "|" denotes a choice.

Note that everything is optional except the CipherData element. The CipherData element envelopes or references the raw encrypted data. We do not consider referenced data here.

The Types of EncryptedData

There are three ways to add encryption to an XML document. The Type attribute of the EncryptedData element gives a clue as to which case applies.

  1. Encrypt the entire document, which may be XML or arbitrary data.
  2. Encrypt an element, including any child elements: Type="http://www.w3.org/2001/04/xmlenc#Element"
  3. Encrypt an element's content, which may be the child elements or just character data, or a mixture: Type="http://www.w3.org/2001/04/xmlenc#Content"
In practice, when decrypting, these three cases are generally treated the same. All EncryptedData elements found in the document are decrypted and the resulting plaintext inserted into the output document to replace the EncryptedData element. Obviously checks are made as to whether the output is valid XML before continuing. Be aware that there are techniques to break XML encryption based on errors returned by this process (and the timing taken to report it). See [XMLENC-CBC-ATTACK]. Please don't go writing your own web service using the advice on this page.

Analysis of example documents

In the following sections, we take some example documents containing XML encryption, point out salient points in their structure, and show how to decrypt them. If you can follow this, then you should be able to do the reverse and create XML documents with encryption.

To make things simple, we'll start with some W3C examples from 2002, some of which use legacy algorithms that are no longer considered secure, but are easier to understand on a first pass, plus we know the documents are accurately formed and the encryption is done correctly. But first a warning:

A warning on legacy algorithms

CAUTION: DO NOT use any of the -CBC block encryption algorithms (tripledes-cbc, aes128-cbc, etc) or the rsa-1_5 key transport algorithm.

For block encryption, always use AES GCM (aes128-gcm, aes192-gcm, aes256-gcm). AES-GCM adds an authentication tag which provides protection against certain attacks on XML-ENC. For RSA key transport, always use RSA-OAEP (rsa-oaep, rsa-oaep-mgf1p). The key wrap algorithms (kw-aes128, etc) are OK.

In addition, the use of SHA-1 to compute a message digest is "discouraged" - use SHA-256 instead. Note that using the default MGF1-with-SHA1 with rsa-oaep is still OK (but it is recommended to use the same strength MGF1 digest algorithm as the DigestMethod). For more information on the attacks on CBC mode and RSA-1_5, see

Source of example files used here

We use example files from the W3C XML Encryption Implementation and Interoperability Report [XMLENC-INTEROP] Test Vectors Y1: merlin-xmlenc-five.tar.gz available from [XMLENC-INTEROP-SAMPLES].

YET ANOTHER CAUTION: These examples use keys composed of ASCII characters; for example, job's 128-bit key is represented in ASCII as the 16 bytes "abcdefghijklmnop". This is fine for simple demonstrations like this, but is very insecure in practice. Always use proper randomly-generated keys where each byte is chosen at random in the full 8-bit range [0,255]. Do not create keys by restricting each byte to be a printable character. If you need to use a readable passphrase, use a key-derivation algorithm like PBKDF2 to derive the actual key.

Entire document encrypted with known symmetric key

FILE: encrypt-data-aes128-cbc.xml [Caution: insecure legacy algorithm aes128-cbc]

<?xml version="1.0" encoding="UTF-8"?>
<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" MimeType="text/plain">
  <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
  <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
    <KeyName>job</KeyName>
  </KeyInfo>
  <CipherData>
    <CipherValue>
      QMpxhXq1DtBeyC9KfSaMQWrEtefe+e935gF/x62spvmL6IW0XeS0W4Kk31OgWzN0
    </CipherValue>
  </CipherData>
</EncryptedData>

This example uses AES-128-CBC to encrypt the entire document. The receiving party is expected to know the AES-128 symmetric key transmitted separately.

It is one of the simplest possible EncryptedData documents. It uses default namespaces (lines 2 and 4), so no need for prefixes. The optional KeyInfo element could have been omitted if the recipient already knew which key to use.

The MimeType="text/plain" attribute (line 2) is a hint to the receiver that the decrypted content is plain text. The encryption algorithm is given by the Algorithm identifier URI (line 3), and the base64-encoded ciphertext is given in the CipherValue (line 9). The optional KeyName element (line 5) is a reference to the key that has been used, which is a shared secret between the two parties. In this case, the recipient, job, knows his AES-128 key is represented in ASCII characters as "abcdefghijklmnop" or the byte string (0x)6162636465666768696A6B6C6D6E6F70 in hexadecimal encoding.

Encryption using CBC mode

The procedure when encrypting using CBC mode is to generate a unique initialization vector (IV) usually at random, pad the plaintext using W3C padding (see below), encrypt the padded plaintext block using the key and IV to produce the ciphertext block (CT), and then encode the concatenated IV|CT in base64.

CipherValue = BASE64(IV|CT) where
CT = ENCRYPT(KEY, IV, PADW3C(PT))

Code: see Encrypt data using block cipher in CBC mode

W3C Padding

If the block length of the cipher is B bytes (16 for all AES variants, 8 for Triple DES), then add N padding bytes to make the input length up to the next exact multiple of B. If the input length is already a multiple of B then add B padding bytes. Thus padding of length N between one and B bytes is always added. The value of final byte of the padding is set to N and the intermediate N-1 bytes are set to arbitrary values.

To remove the padding, set N to the value of the last byte and remove the last N bytes. We expect the value of N to be between one and B.

Note this is similar to the commonly-used PKCS#5/PKCS#7 padding except only the last byte is used to denote the number N of padding bytes, whereas with PKCS#5 padding all the padding bytes are set to value N. You can use the PKCS#5 padding algorithm to add padding and it is valid W3C padding (remember the other padding bytes are arbitrary and N is as arbitrary as any other value, isn't it?), but not the other way around (because when removing PKCS#5 padding it is an error if any of the other padding bytes is not N).

Decrypting the CipherValue

The base64 value QMpxhXq1DtBeyC9KfSaMQWrEtefe+e935gF/x62spvmL6IW0XeS0W4Kk31OgWzN0 decodes to the byte array encoded in hexadecimal

40CA71857AB50ED05EC82F4A7D268C416AC4B5E7DEF9EF77E6017FC7ADACA6F98BE885B45DE4B45B82A4DF53A05B3374
(hexadecimal makes it much easier to understand). We parse this to separate the prefixed IV, which we know is 16 bytes for AES, and CT block (which must be an exact multiple of 16 bytes)
        |------------IV----------------|   |----------------------------CT--------------------------------|
IV|CT = 40CA71857AB50ED05EC82F4A7D268C41 | 6AC4B5E7DEF9EF77E6017FC7ADACA6F98BE885B45DE4B45B82A4DF53A05B3374
Decrypting the CT block using the key and IV, we obtain the following
746F7020736563726574206D6573736167650A598231900E1EACED9AC0D2D20D
|------------------PT----------------||----13 padding bytes----|
The last byte 0x0D tells us there are 13 padding bytes, so we strip the last 13 bytes leaving our required plaintext
746F7020736563726574206D6573736167650A
which is the representation of the ASCII string "top secret message" plus a 0x0A newline character.
top secret message
 

Some cryptographic toolkits provide the feature to automatically parse the prefixed IV, do the decryption, and strip the padding in one go (hint, hint, we know one!).

Code to decrypt: Function to decrypt using block cipher in CBC mode
Decrypt encrypt-data-aes128-cbc.xml

[Go to top]

Entire document encrypted using a wrapped key

FILE: encrypt-data-aes192-cbc-kw-aes256.xml [Caution: insecure legacy algorithm aes192-cbc]

<?xml version="1.0" encoding="UTF-8"?>
<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" MimeType="text/plain">
  <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes192-cbc" />
  <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
    <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes256" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <KeyName>jed</KeyName>
      </KeyInfo>
      <CipherData>
        <CipherValue>
          4AAgyi3M7xNdBimbQZKdGJLn3/cS4Yv8QKuA01+gUnY=
        </CipherValue>
      </CipherData>
    </EncryptedKey>
  </KeyInfo>
  <CipherData>
    <CipherValue>
      50lv94d/DFJirJXYOUXaBlrO+7gIXpx8cqH+G2xvE4mueoIxmGs8RH7FBXwjuMgf
    </CipherValue>
  </CipherData>
</EncryptedData>

This time, the key used to encrypt the content is provided in a separate EncryptedKey element inside the KeyInfo element.

We have two CipherValue elements. The second one EncryptedData/CipherData/CipherValue (line 19) is the actual encrypted data, encrypted using AES-192-CBC (line 3). The AES-192 key used to encrypt the data is provided in key-wrapped form in the KeyInfo element (lines 4-16). The CipherValue in line 12 is the AES-192 content encryption key (CEK) encrypted using the AES-256 key wrap algorithm (line 6) with a 256-bit key encryption key (KEK) known to the recipient, jed (line 8), by other means.

In this case, jed's AES-256 key is represented in ASCII characters as "abcdefghijklmnopqrstuvwxyz012345" or the byte string (0x)6162636465666768696A6B6C6D6E6F707172737475767778797A303132333435 in hexadecimal encoding.

Encryption using Key Wrap

CipherValue = BASE64(WrappedKey) where
WrappedKey = ENCRYPT_KW(KEK, CEK)
CEK = content-encryption key
KEK = Key-encryption key used to encrypt CEK

Code: see Encrypt key material using key wrap

Decrypting the CipherValue

The wrapped key is in the CipherValue descendant of the EncryptedKey element (line 12).
4AAgyi3M7xNdBimbQZKdGJLn3/cS4Yv8QKuA01+gUnY=
E00020CA2DCCEF135D06299B41929D1892E7DFF712E18BFC40AB80D35FA05276
Decrypting this using the AES-256 key wrap algorithm and jed's 256-bit key, we obtain the 24-byte (192-bit) content encryption key.
F65CD2C48C1DA5565ED0AAB2D042713373C74C8E69332F2F

Code to decrypt key material: Function to decrypt key material from key wrap
Decrypt encrypt-data-aes192-cbc-kw-aes256.xml

The encrypted content is in the CipherValue descendant of the EncryptedData element (line 19).
50lv94d/DFJirJXYOUXaBlrO+7gIXpx8cqH+G2xvE4mueoIxmGs8RH7FBXwjuMgf
E7496FF7877F0C5262AC95D83945DA065ACEFBB8085E9C7C72A1FE1B6C6F1389AE7A8231986B3C447EC5057C23B8C81F
IV|CT = E7496FF7877F0C5262AC95D83945DA06 | 5ACEFBB8085E9C7C72A1FE1B6C6F1389AE7A8231986B3C447EC5057C23B8C81F
Decrypting this using the AES-192-CBC algorithm and the CEK from above, we obtain
746F7020736563726574206D6573736167650A78425C9539DFB7692F0C960F0D
which after stripping the padding, gives us the same plain text output as before.
top secret message

[Go to top]

An element encrypted with a key encrypted using RSA-1_5 key transport

FILE: encrypt-element-aes128-cbc-rsa-1_5.xml [Caution: insecure legacy algorithms rsa-1_5 and aes128-cbc]

<?xml version="1.0" encoding="UTF-8"?>
<PurchaseOrder xmlns="urn:example:po">
  <Items>
    <Item Code="001-001-001" Quantity="1">
      spade
    </Item>
    <Item Code="001-001-002" Quantity="1">
      shovel
    </Item>
  </Items>
  <ShippingAddress>
    Dig PLC, 1 First Ave, Dublin 1, Ireland
  </ShippingAddress>
  <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
    <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
      <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
        <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
        <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
          <X509Data>
            <X509Certificate>
              MIICkjCCAfugAwIBAgIGAOxN32E+MA0GCSqGSIb3DQEBBQUAMG4xCzAJBgNVBAYT
              AklFMQ8wDQYDVQQIEwZEdWJsaW4xJDAiBgNVBAoTG0JhbHRpbW9yZSBUZWNobm9s
              b2dpZXMgTHRkLjERMA8GA1UECxMIWC9TZWN1cmUxFTATBgNVBAMTDFRyYW5zaWVu
              dCBDQTAeFw0wMjAyMjgxNzUyNDZaFw0wMzAyMjgxNzUyNDBaMG8xCzAJBgNVBAYT
              AklFMQ8wDQYDVQQIEwZEdWJsaW4xJDAiBgNVBAoTG0JhbHRpbW9yZSBUZWNobm9s
              b2dpZXMgTHRkLjERMA8GA1UECxMIWC9TZWN1cmUxFjAUBgNVBAMTDU1lcmxpbiBI
              dWdoZXMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAORdNSxbNFWlQeNsOlYJ
              9gN9eZD+rguRqKhmhOm7i63VDd5ALm2APXhqAmGBPzLN5jlL9g2XALK5WSO4XKjJ
              McVfYg4+nPuOeHgqdD4HUgf19j/6SaTMcmDFJQMmx1Qw+Aakq3mGcSfvOJcBZctz
              a50VucfCGL1NdfBEcaL3BnhjAgMBAAGjOjA4MA4GA1UdDwEB/wQEAwIFoDARBgNV
              HQ4ECgQIjFG0ZGNyvNswEwYDVR0jBAwwCoAIhJXVlhr6O4wwDQYJKoZIhvcNAQEF
              BQADgYEAXzG7x5aCJYRusTbmuZqhidGM5iiA9+RmZ4JTPDEgbeiTiJROxpr+ZjnA
              TmsDKrCpqNUiHWjmsKEArYQp8R/KjdKl/pVe3jUvTxb0YZ+li/7k0GQ5LyRT/K4c
              2SgyLlyBPhpMq+z3g4P2egVRaZbxsLuKQILf7MIV/X5iAEBzu1w=
            </X509Certificate>
          </X509Data>
        </KeyInfo>
        <CipherData>
          <CipherValue>
            heZshNX5m7arS3OmR72+8WNCMMpznxE41dLWkgd6XJpzl+IN2xuijAf4YPEjjJmZ
            nt9PlO3/hiHl0Cvpg5vMR6AhvL49BvCz9JCeMG6x3MHBiKbRNhyEq2rX7o1GdJhC
            5cm35Q/ZDKV9DHG8jWmPcOb8yKU9NYo2LJKDb3YHOJY=
          </CipherValue>
        </CipherData>
      </EncryptedKey>
    </KeyInfo>
    <CipherData>
      <CipherValue>
        0wkECpTy60/FDwbVM4zgd9qJVjR4h0q4PLm5pyyIxAuhbEh0art03yEikmbWBt2H
        7qOk2G9iufUdwwqNPuZV5Qw5Rg2FMvTx234lDERGn5p+hhjOTcss5JF9QDzgdiec
        KABX3vbCESi/f3uwQ8BYDT+6SnxTR+xtcNv5xhbUCIFk/TaenSWx6p6fntTwTl1e
        lpwnI0EtM1yf4a9tBiH9PNd36BUv2rvSi4cZvJqSB3ZKvGtuwwyRzOzlzl259d1u
        QuoYysTBEAHw/WIop8eAexU9PUv7UbTkQAQag1yStda+GepVdpXEpu4hcxXQcvfs
        9AQgkAgh4JKrnY4Bhz2B/e4CHHfbEedDOi+FVYlZuLn0CzrKMnM+1nUmqxJVWHz7
        hytidpuqNRw3gcMkYvgH6g==
      </CipherValue>
    </CipherData>
  </EncryptedData>
</PurchaseOrder>

The element is encrypted using AES-128-CBC (line 15). The content encryption key (CEK) is passed to the recipient using the RSA-1_5 key transport algorithm (line 18). The X509Certificate element (lines 21-36) includes the public key used to encrypt the data and helps the recipient identify their EncryptedKey. The recipient should verify that their (secret) RSA private key matches the RSA public key in the certificate.

Encryption using RSA-1_5

The CEK is encrypted using the RSA-1_5 algorithm and the recipient's RSA public key. This key is usually contained in an X.509 certificate.

CipherValue = BASE64(EncryptedKey) where
EncryptedKey = ENCRYPT_RSA_1_5(CEK, RSA_PUBKEY)
CEK = content-encryption key

Code: see Encrypt key material using RSA-v1.5

RSA-v1.5 encoding

Before encryption, the CEK is encoded into an encryption block as follows. If the RSA key modulus is k bytes long (so a 2048-bit key has k = 2048/8 = 256 bytes), and the key data CEK has length d in bytes, then, providing d ≤ k-11, we form a k-byte encryption block EB as follows
EB = 00 || 02 || PS || 00 || CEK
where || denotes concatenation and PS is a string of length k-d-3 nonzero randomly-generated bytes (i.e. at least 8 random bytes). This encryption block is encrypted using the recipient's RSA public key to derive a k-byte EncryptedKey, which will be different each time. (For more details, see Encryption using PKCS#1v1.5).

Decrypting the CipherValue

The secret but unencrypted RSA private key used here is rsa-w3c.p8
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAORdNSxbNFWlQeNs
OlYJ9gN9eZD+rguRqKhmhOm7i63VDd5ALm2APXhqAmGBPzLN5jlL9g2XALK5WSO4
XKjJMcVfYg4+nPuOeHgqdD4HUgf19j/6SaTMcmDFJQMmx1Qw+Aakq3mGcSfvOJcB
Zctza50VucfCGL1NdfBEcaL3BnhjAgMBAAECgYEAs1OeVd6pEjhbrUNn6/iWf9cg
h4P3GI6hatxWs1TbMv6DjWvJCaQSoWRdykO8ZSDbEVNdPP6/RZnXLf2whbq4oVFh
R9o2wXqJV8YDLHVVYr+OC0+cJYNDLboRvLQGqltlHLVrowthUQb/lu9kTTUINXhe
22lOs1f3VZZxgZ24nEECQQDoQPVk6ojMGm5zYoCj5taaugIfz5xIOTSBWrpudEH4
QSFEKaj9WC+d1YvF97F0aYMg4AiKwHTo3lobMFIJoRj9AkEA+7Zw2+64E0vCuXE8
LA4SkgdhPiAmrxQy2Do7o36776dgIaErq6hUKaspj5R7DI0hywtkXSOw0jaomOJT
W9DE3wJBAN9AmeKAxDCV87f8ZrWmjoG67ZHQimSugHcbVHwaStOtH6Ia/bNR0qvA
exQ4LZ8+UWsHj454w6iZHDpob2OMNK0CQHXO2JmG6+5UCgoi/kecOoLQI2ohQBm3
OWjMMHd/7FPpIWv78+V+fg2Wh3gkxUaFk2hlp46UEsEARf5wBxW06z8CQGJxk4A+
/zgAGYV/KFeFhoC5pxokur/+OD635RFQ6D5dlL2dpGZrARDE6RlBWgx4qC+7Tn5X
gyeIWp1AEg0iSvk=
-----END PRIVATE KEY-----
Using this key to decrypt the //EncryptedKey/KeyInfo//CipherValue element (lines 41-43) we obtain the 128-bit CEK
493185CE8177AC09C4DE6C7C75524B16

Code to decrypt key material:
Function to decrypt key material using RSA-v1.5
Decrypt encrypt-element-aes128-cbc-rsa-1_5.xml

Using this CEK to decrypt the EncryptedData//CipherValue element (lines 50-56) we obtain the output
<PaymentInfo>
    <BillingAddress>
      Dig PLC, 1 First Ave, Dublin 1, Ireland
    </BillingAddress>
    <CreditCard Type="Amex">
      <Name>Foo B Baz</Name>
      <Number>1234 567890 12345</Number>
      <Expires Month="1" Year="2005" />
    </CreditCard>
  </PaymentInfo>
which should be substituted for the EncryptedData element in the original document (lines 14-59).
<?xml version="1.0" encoding="UTF-8"?>
<PurchaseOrder xmlns="urn:example:po">
  <Items>
	<Item Code="001-001-001" Quantity="1">
	  spade
	</Item>
	<Item Code="001-001-002" Quantity="1">
	  shovel
	</Item>
  </Items>
  <ShippingAddress>
	Dig PLC, 1 First Ave, Dublin 1, Ireland
  </ShippingAddress>
  <PaymentInfo>
	<BillingAddress>
	  Dig PLC, 1 First Ave, Dublin 1, Ireland
	</BillingAddress>
	<CreditCard Type="Amex">
	  <Name>Foo B Baz</Name>
	  <Number>1234 567890 12345</Number>
	  <Expires Month="1" Year="2005" />
	</CreditCard>
  </PaymentInfo>
</PurchaseOrder>

[Go to top]

An element encrypted for two recipients using key wrap

FILE: encrypt-element-aes256-cbc-carried-kw-aes256.xml [Caution: insecure legacy algorithm aes256-cbc]

<?xml version="1.0" encoding="UTF-8"?>
<PurchaseOrder xmlns="urn:example:po">
  <Items>
    <Item Code="001-001-001" Quantity="1">
      spade
    </Item>
    <Item Code="001-001-002" Quantity="1">
      shovel
    </Item>
  </Items>
  <ShippingAddress>
    Dig PLC, 1 First Ave, Dublin 1, Ireland
  </ShippingAddress>
  <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
    <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
      <KeyName>Foo Key</KeyName>
    </KeyInfo>
    <CipherData>
      <CipherValue>
        pdDtiyd7XQ/BFEEN0PMJuHnLUfCY+bJlsW+q04OiKSPnRd4/dS1tjaTfj5dPpGXe
        cY3fJvRsq9QP1CJiwyEC/EQ1zSLbzwOtZ+NtxtsFgYvPBJ9t86ZcXIjlErQ85z3L
        wnb8rSHpE9tu4tJ1rjgf2i6NCbdFnSMXLSDgLEs48+gkX0cJCmKxzRaSE4cV0OSl
        hBWND4EYzX1M679VlSYrI0de+lSPO3Vx+y/TuZ5Vo+uu9+YP+ce0LRkx2BicjjsP
        QO9sp+yjHPNDIV1Z7VHsDIWqqmBaNQo3GuzF5WzWgaXTKnPv/IgUQn+1t3EtgHyb
        JhnfR/1em16z/Zaf9Uy1Lfd//yfEJ9BCjqwe1UjwN6ytu1v2BHd+8bVjD2o+Dg8V
        7ayOLlkWOTOLvtJMPOXPqw==
      </CipherValue>
    </CipherData>
  </EncryptedData>
  <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
    <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#" Recipient="someone else">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes256" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <KeyName>ned</KeyName>
      </KeyInfo>
      <CipherData>
        <CipherValue>
          EWlIkFPGrkeW4cyjWSznLVoClVh/OEC7Klya9d9o7R6wll6JswZb2w==
        </CipherValue>
      </CipherData>
      <CarriedKeyName>Foo Key</CarriedKeyName>
    </EncryptedKey>
    <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#" Recipient="you">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes256" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <KeyName>jed</KeyName>
      </KeyInfo>
      <CipherData>
        <CipherValue>
          bsL63D0hPN6EOyzdgfEmKsAAvoJiGM+Wp9a9KZM92IKdl7s3YSntRg==
        </CipherValue>
      </CipherData>
      <CarriedKeyName>Foo Key</CarriedKeyName>
    </EncryptedKey>
  </KeyInfo>
</PurchaseOrder>

This is unusual in that we have an EncryptedData element followed by a separate, sibling KeyInfo element with cross-references provided by a CarriedKeyName. We will see another example later where the EncryptedKey elements are children of EncryptedData element.

<PurchaseOrder>
  <Items>
  <ShippingAddress>
  <EncryptedData>
  <KeyInfo>
</PurchaseOrder>

This separate KeyInfo contains two external EncryptedKey elements each of which contains a CarriedKeyName which is referenced by a KeyName "Foo Key" in the EncryptedData.

The EncryptedData element gives the EncryptionMethod aes-256-cbc (line 15) which is the algorithm used to encrypt the payload given in the CipherValue (lines 21-27). An AES-256 content-encryption key has been used to encrypt the payload referenced by the KeyName "Foo Key" (line 17).

In the following KeyInfo element (lines 31-56) we have two EncrypedKey elements both cross-referenced with the CarriedName of "Foo Key" (lines 42 and 54). Both encrypted keys are encrypted using AES-256 key wrap (kw-aes256) using AES-256 keys shared with the recipients.

The first EncrypedKey element is for a recipient "someone else" (line 32) who has a local KeyName of "ned" (line 35). We don't know anything about ned's key and cannot use this wrapped key.

The second EncrypedKey element is for a recipient "you" (line 44) with a KeyName of "jed" (line 47). We know (independently) that jed's 256-bit key is represented in ASCII characters as "abcdefghijklmnopqrstuvwxyz012345".

The wrapped KEK is in the CipherValue descendant of the second EncryptedKey element (line 51).
bsL63D0hPN6EOyzdgfEmKsAAvoJiGM+Wp9a9KZM92IKdl7s3YSntRg==
6EC2FADC3D213CDE843B2CDD81F1262AC000BE826218CF96A7D6BD29933DD8829D97BB376129ED46
Decrypting this using the AES-256 key wrap algorithm and jed's 256-bit key, we obtain the 32-byte (256-bit) CEK.
41559545888C22BF367F7936E6A9FFB6D810B2AB42BF70220F2168DB9B503DC6
The encrypted content is in the CipherValue descendant of the EncryptedData element (lines 21-27).
pdDtiyd7XQ/BFEEN0PMJuHnLUfCY+bJlsW+q04OiKSPnRd4/dS1tjaTfj5dPpGXe
cY3fJvRsq9QP1CJiwyEC/EQ1zSLbzwOtZ+NtxtsFgYvPBJ9t86ZcXIjlErQ85z3L
wnb8rSHpE9tu4tJ1rjgf2i6NCbdFnSMXLSDgLEs48+gkX0cJCmKxzRaSE4cV0OSl
hBWND4EYzX1M679VlSYrI0de+lSPO3Vx+y/TuZ5Vo+uu9+YP+ce0LRkx2BicjjsP
QO9sp+yjHPNDIV1Z7VHsDIWqqmBaNQo3GuzF5WzWgaXTKnPv/IgUQn+1t3EtgHyb
JhnfR/1em16z/Zaf9Uy1Lfd//yfEJ9BCjqwe1UjwN6ytu1v2BHd+8bVjD2o+Dg8V
7ayOLlkWOTOLvtJMPOXPqw==
Decrypting this using the AES-256-CBC algorithm and the CEK from above, we obtain the decrypted element.
<PaymentInfo>
    <BillingAddress>
      Dig PLC, 1 First Ave, Dublin 1, Ireland
    </BillingAddress>
    <CreditCard Type="Amex">
      <Name>Foo B Baz</Name>
      <Number>1234 567890 12345</Number>
      <Expires Month="1" Year="2005" />
    </CreditCard>
  </PaymentInfo>

[Go to top]

Entire document encrypted using AES-GCM

FILE: encrypt-data-aes256-gcm.xml

<?xml version="1.0" encoding="UTF-8"?>
<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" MimeType="text/plain">
  <EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes256-gcm" />
  <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
    <KeyName>jed</KeyName>
  </KeyInfo>
  <CipherData>
    <CipherValue>
      AQIDBAUGBwgJCgsMqYHeLKkzx8/iBLZa8f+ZCMGHulqDdiELj+ghwhU1jg62WW0=
    </CipherValue>
  </CipherData>
</EncryptedData>

This is similar to the first example above, except we use the more-secure GCM algorithm, in this case aes256-gcm (line 3). The recipient, jed (line 5), knows the AES-256 key by separate means. In this case it is represented in ASCII characters as "abcdefghijklmnopqrstuvwxyz012345".

Encryption using GCM mode

The procedure when encrypting using GCM mode is to generate a unique 12-byte initialization vector (IV), usually at random, encrypt the plaintext using counter mode, which outputs a ciphertext CT of the same length as the input, and simultaneously computes an authentication TAG of 16 bytes. The concatenated IV|CT|TAG is encoded in base64. What we call here the IV can also be called a nonce.

CipherValue = BASE64(IV|CT|TAG) where
(CT, TAG) = ENCRYPT_GCM(KEY, IV, PT)

Code: see Encrypt data using block cipher in AES-GCM mode

Decrypting the CipherValue

The CipherValue is
AQIDBAUGBwgJCgsMqYHeLKkzx8/iBLZa8f+ZCMGHulqDdiELj+ghwhU1jg62WW0=
0102030405060708090A0B0CA981DE2CA933C7CFE204B65AF1FF9908C187BA5A8376210B8FE821C215358E0EB6596D
We parse this to separate the prefixed IV, which we know is 12 bytes for AES-GCM, the CT (which is the same length as the plaintext) and the 16-byte TAG suffix.
        |----------IV----------| |----------------CT------------------| |-------------TAG--------------|
IV|CT = 0102030405060708090A0B0C A981DE2CA933C7CFE204B65AF1FF9908C187BA 5A8376210B8FE821C215358E0EB6596D
Unlike CBC mode, there is no padding to remove, and failure to reproduce the authentication tag causes an encryption failure, which prevents tampering with the ciphertext. Decrypting this using jed's 256-bit key gives our required plaintext
746F7020736563726574206D6573736167650A
which is the representation of the ASCII string "top secret message" plus a 0x0A newline character.
top secret message

Code to decrypt:
Function to decrypt using block cipher in AES-GCM mode
Decrypt encrypt-data-aes256-gcm.xml

[Go to top]

Element signed using AES-GCM using RSA-OAEP key transport

FILE: root-bob-oaep-gcm.xml

<root>
  <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
    <EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes128-gcm" />
    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
      <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
        <EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#rsa-oaep-mgf1p">
          <DigestMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        </EncryptionMethod>
        <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
          <KeyName>bob@smime.example</KeyName>
        </KeyInfo>
        <CipherData>
          <CipherValue>
            ne3BEmELlWOKCvevCnKmgZ9//JYNgSrtdighAztmUJAtuGCXWMqtfsSLccTUpEdm
            k4Vl+BampcxIiEvHduNkq1un9oV7ikyrTiT0A9jChlC8Tf8HU9XeU3I/I/5FqP8V
            IxWfnTLuvu/jp4lVyqoNmDtsooqlQtcaC0C7JRoc+bKeqMhzZxOgdUK3UM34aDDk
            HZHZSaMbWp8P59kJLUECMXTP+dW3q8MMucr7PEGhN5VGBKNH3/IlCvDvg3ROW/cY
            csCTh8Vve5h+eyiZUl2DcBITgj31qFkZ/QJtzoIG7PbkS5WU0NNtAguO6z7MbZlv
            PAOyQgvJpmSQqKUOrHro8g==
          </CipherValue>
        </CipherData>
      </EncryptedKey>
    </KeyInfo>
    <CipherData>
      <CipherValue>
        f4K4iAry8y7hz2mKl3Xpqnx5lVPTKkeKhM7PmGJITVE5pk4NZjFak1ZaKpgvoi3o
        oUP+sxUArXnNG/GrLYQ=
      </CipherValue>
    </CipherData>
  </EncryptedData>
</root>

This example uses recommended algorithms: AES-GCM for content encryption and RSA-OAEP (OAEP) for key transport.

The element is encrypted using AES128-GCM (line 3). The content encryption key (CEK) is passed to the recipient using the rsa-oaep-mgf1p key transport algorithm (line 6). The rsa-oaep-mgfp1 algorithm always uses MGF1-with-SHA1 as the mask generation algorithm (MGF) (this is the strict default and is OK security-wise). The DigestMethod element (line 7) defines the hash algorithm parameter as SHA-256 (if this were absent then the default would be SHA-1).

Code to encrypt the key: see Encrypt key material using RSA-OAEP

The recipient uses the KeyName "bob@smime.example" (line 10) and bob's private RSA key is bob-smime.p8

-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCZjluLi00rpoC
sq2s8SHqb91QPP5bdfzfaJg/G61lHUhfavEX9zZluyMwPPE50wqwV2RJX5dg0kSt
yH9s9Ja5D59pPnX8oJJ7XEqNKwxqSfJt7lRmM8BrDvSP55iP7Ofx+O+2MzVA4tA6
WUaUy2j9984CMmXH/CHjBK/+w21vSTmzFVGmeTqxxHONbd2zOqQ6Yqr/LBaHjAWl
+tj9Q+2nIjEQFKlWs6vZll3Xwid6+dAxrtpEO5rIpKZcbn40qT1pyDprylNk8h3P
90nwrOISpdlAJ2p71ZDdLfLd8c6qZGBPjmHwTUnjmH0oy33uBukT73RUW6raD8Mw
M4AhQ4ETAgMBAAECggEAC9CIpwCZcL030PgpA/y3sfbQfYLndomKL828iwFUnXOV
JW9rbahxnucrsU/S3U/NM4BsMOVlXtYIpIMt82I+Ess3Rf8szoi3vlWSllfKbl9G
I5Y7fOaiSB9lj6VkqUKdqiAV+X3NO79NJm6sknh2ThEUbR/A/dF+Ab0UMSiRaxTt
81LnZUKd05Z0Yi3QSaxkh9f0fyuedKtJOugOyT1xCPKMxwIftffjQoNRpUmVG3H7
ViVs9PK4oXads2NJZ+xiG4g4ZPjEabpOt1rPptaO7Efuc2sYqu07XhoTxe/nqwL4
nm6XBoiN/9X54NlV+lWCJfKrqhromKg+/u6vHtwhAQKBgQD2i+o6L85h0M1BMlcH
gs0y1LVYvGCunMT9I08RXleSdDnJ/quspnf6Wv+vrDY6mvg9j7f+KAygFlw3tiAg
z0OuSDpsMvOtLfngD11ksME0CAKcNHTJjztTd/aWOOkIDbNmtqFiGEqx/IzG3bDd
xSyjb305iCM3Atosjsute89rgQKBgQDJ2m9/D7N0RzTFsYYgtvjGKIWkljazrThq
5nf+z/L1be/wtIqvK0ceilA6DcYAu9CL4DItZEEholPMS54TqUhgidkjb5a8rbM/
YYHbX8lfkwjfHsBxGn//Wa7KGdbcZ/I8amDrNETjl1k+b2eSXLCXj7KXju5t0683
LGJ8GYPGkwKBgBAdvUXochk6yPAGFmJLTpaQCPqv9bH0VXwmnriH7jmIl25400gJ
6bXX1PbqzvCtyKRdjK10eL7ON2D86sS6R7ZQymDgQ8WCR985oeU/GKIKFAGZ/Dhg
wIQIR3oyZik8nAmOzqXW6KsR0zH8s98LUIuucgUcvRCPgyt+ehnxCfIBAoGBALpZ
PavI+/wyLKcCL/iN0vdlu5Np1hBkr3wJTuhgZEVufB/1HT+ALcUlHdGqm4xb17j6
fnhnYLXDXadye/pcwuPU/zB2uWtw1NWDmFXFhWwFmyAZDMKeG2LLEdGkrzaFhB2A
e/9IHv0Z4ZsBUFXP2nvhfpfqrXWZAt5lzHoTOBOfAoGBAONaa0OTzkDQZC4kFHtA
4H4Jdvf2PRrvxDDLCnH5diJuaD43doPXIkHxVW0dZhurfAznUR2PFhVqDIp3cgoi
Oc9sEhYiMVaoSANeYFE7DBHwMGl+99/eOHgmMr4u2+ceGHDT0q18K9kamVlh9J8L
W0u6h0Ew2PFRf27ThupPKrH+
-----END PRIVATE KEY-----

This key is taken from S/MIME Example Keys and Certificates draft-dkg-lamps-samples-02.

Using this key to decrypt the EncryptedData/EncryptedKey/CipherValue element (lines 14-19) we obtain the 128-bit CEK
E2493529B46E23907FC77AB0C4DD74BE

Code to decrypt key material:
Function to decrypt key material using RSA-OAEP
Decrypt root-bob-oaep-gcm.xml

Using this CEK with AES-128-GCM to decrypt the EncryptedData/CipherValue element (lines 26-27) we obtain the output
<encryptme>hello world</encryptme>
which should be substituted for the EncryptedData element in the original document (lines 2-30).
<root>
  <encryptme>hello world</encryptme>
</root>

[Go to top]

Element encrypted for two recipients using RSA-OAEP key transport

FILE: root-oaep-256-gcm-x2.xml

<root>
  <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
    <EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes128-gcm" />
    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
      <KeyName>foobarkey</KeyName>
      <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
        <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep">
          <MGF xmlns="http://www.w3.org/2009/xmlenc11#" Algorithm="http://www.w3.org/2009/xmlenc11#mgf1sha256" />
          <DigestMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        </EncryptionMethod>
        <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
          <KeyName>notyou@example.com</KeyName>
        </KeyInfo>
        <CipherData>
          <CipherValue>
            bS2f1o21py6I3We9oE/PaSa8fYSJKkTBL+MGaoXStzLDJq+WiMUcy++ScA5kxonM
            H3PXy5hbvAu+SNYoe9FUraqqWvX8W7lhEfNLSPrz+prz72m3rxRDlppLQglhOBpC
            bi3ZA3MgrbiThFixMhjRFOtKZ+/Z6Ey+ndBrE8oP6kaRMa/WVYV0BFbcskTs6qQd
            KioCHQVGXnQd+shtLJjAnLeYLXpr1rd6biTaPSpXW4dpVsFBbt3nu/ZDzTtk/sO4
            NlhP5+IwqTaVjNYUmCOXB6naSnhHWxr/4sVfaiWU2tL/hH6VXEday0nYmLuIfxMV
            DVLAc3CSyjvP5m9Y0XNOdw==
          </CipherValue>
        </CipherData>
        <CarriedKeyName>foobarkey</CarriedKeyName>
      </EncryptedKey>
      <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
        <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep">
          <MGF xmlns="http://www.w3.org/2009/xmlenc11#" Algorithm="http://www.w3.org/2009/xmlenc11#mgf1sha256" />
          <DigestMethod xmlns="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        </EncryptionMethod>
        <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
          <KeyName>bob@smime.example</KeyName>
        </KeyInfo>
        <CipherData>
          <CipherValue>
            qsIPCYkqgCSDv+xxNf0swqJiDZiVTsPrMdPcPFeaZW+yK3KqeHYHZubrTMV0Cj5b
            gezvKe/fq+OdIZVvxIDR/nJy0M/Jm6GiVnOmm2FzzP9YnsARubF2piwGGT5bo4a0
            wkoH+bBBcZEMPG1LHWBUThBn+pz6ApV/ogLB4q5f5bkiqKSi4rZktT8fxxJJvqdg
            lrYmLNSM+QS51YP35xtBwMups8BTHNQ/n+YOoz0/X3xBMIgCc0K0W14LG9qgXsgR
            AVtxezJkiOq8q+jj12vNyBLqQoR3MnTaOM9kmHcwHFkCoG4HBgDTQJWOd2oIrHGi
            2TfIvBsPHXk6STZKEj7u4A==
          </CipherValue>
        </CipherData>
        <CarriedKeyName>foobarkey</CarriedKeyName>
      </EncryptedKey>
    </KeyInfo>
    <CipherData>
      <CipherValue>e2kl8SXHPvyy/qbzY2Rk46+6vWtTLgt4rSL+1IMkdJqBQvpqaMPFeKa4k4yxsa4XauwZZYdOIfwj13sFvMA=</CipherValue>
    </CipherData>
  </EncryptedData>
</root>

This uses the recommended RSA-OAEP key transport algorithm for the encrypted keys (lines 7 and 27), and the recommended AES-GCM to encrypt the content (line 3). There are two EncryptedKey elements, this time inside a child KeyInfo element (lines 4-45). These EncryptedKey elements both contain a CarriedKeyName which is referenced by a KeyName "foobarkey" in the EncryptedData.

In general, there can be as many recipients as you like, identified either by the Recipient attribute or KeyName, provided each recipient is able to identiy their particular EncryptedKey. In this case, bob wants the second element identified by the KeyName "bob@smime.example" (line 32) Bob's RSA key is the same as given in the earlier example.

Bob's wrapped key is the second EncryptedKey/CipherData/CipherValue (lines 36-40).
qsIPCYkqgCSDv+xxNf0swqJiDZiVTsPrMdPcPFeaZW+yK3KqeHYHZubrTMV0Cj5b
gezvKe/fq+OdIZVvxIDR/nJy0M/Jm6GiVnOmm2FzzP9YnsARubF2piwGGT5bo4a0
wkoH+bBBcZEMPG1LHWBUThBn+pz6ApV/ogLB4q5f5bkiqKSi4rZktT8fxxJJvqdg
lrYmLNSM+QS51YP35xtBwMups8BTHNQ/n+YOoz0/X3xBMIgCc0K0W14LG9qgXsgR
AVtxezJkiOq8q+jj12vNyBLqQoR3MnTaOM9kmHcwHFkCoG4HBgDTQJWOd2oIrHGi
2TfIvBsPHXk6STZKEj7u4A==
This time we have two parameters for the rsa-oaep algorithm inside the EncryptionMethod element (lines 27-30). The DigestMethod is sha256 (line 29) and the MGF is mgf1sha256 (line 28). It is recommended that the hash function be the same for both the digest method and the MGF, like this example.

Decrypting the wrapped key using RSA-OEAP with the the two parameters and Bob's RSA private key, we obtain the 16-byte (128-bit) CEK.

F45F70F9645F73B3CB88DBD17EBA881B

Code to decrypt key material:
Function to decrypt key material using RSA-OAEP
Decrypt root-oaep-256-gcm-x2.xml

The encrypted content is the CipherValue (line 47) which can be split into IV|CT|TAG parts.
e2kl8SXHPvyy/qbzY2Rk46+6vWtTLgt4rSL+1IMkdJqBQvpqaMPFeKa4k4yxsa4XauwZZYdOIfwj13sFvMA=

7B6925F125C73EFCB2FEA6F3
636464E3AFBABD6B532E0B78AD22FED48324749A8142FA6A68C3C578A6B8938CB1B1
AE176AEC1965874E21FC23D77B05BCC0
Decrypting this using the AES-128-GCM algorithm and the CEK from above, we obtain the decrypted element.
<encryptme>hello world</encryptme>

[Go to top]

Using prefixed names

You'll notice in the above examples that almost every line needs to have its default xmlns declared. Here is an example using fully-qualified prefixed names.

  <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" 
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
    xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
    xmlns:xenc11="http://www.w3.org/2009/xmlenc11#"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation=
    "http://www.w3.org/2001/04/xmlenc# xenc-schema-local.xsd 
     http://www.w3.org/2009/xmlenc11# xenc-schema-11-local.xsd">
    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes128-gcm" />
    <ds:KeyInfo>
      <ds:KeyName>foobarkey</ds:KeyName>
      <xenc:EncryptedKey>
        <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep">
          <xenc11:MGF Algorithm="http://www.w3.org/2009/xmlenc11#mgf1sha256" />
          <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        </xenc:EncryptionMethod>
        <ds:KeyInfo>
          <ds:KeyName>bob@smime.example</ds:KeyName>
        </ds:KeyInfo>
        <xenc:CipherData>
          <xenc:CipherValue>
            qsIPCYkqgCSDv+xxNf0swqJiDZiVTsPrMdPcPFeaZW+yK3KqeHYHZubrTMV0Cj5b
            gezvKe/fq+OdIZVvxIDR/nJy0M/Jm6GiVnOmm2FzzP9YnsARubF2piwGGT5bo4a0
            wkoH+bBBcZEMPG1LHWBUThBn+pz6ApV/ogLB4q5f5bkiqKSi4rZktT8fxxJJvqdg
            lrYmLNSM+QS51YP35xtBwMups8BTHNQ/n+YOoz0/X3xBMIgCc0K0W14LG9qgXsgR
            AVtxezJkiOq8q+jj12vNyBLqQoR3MnTaOM9kmHcwHFkCoG4HBgDTQJWOd2oIrHGi
            2TfIvBsPHXk6STZKEj7u4A==
          </xenc:CipherValue>
        </xenc:CipherData>
        <xenc:CarriedKeyName>foobarkey</xenc:CarriedKeyName>
      </xenc:EncryptedKey>
    </ds:KeyInfo>
    <xenc:CipherData>
      <xenc:CipherValue>
        e2kl8SXHPvyy/qbzY2Rk46+6vWtTLgt4rSL+1IMkdJqBQvpqaMPFeKa4k4yxsa4X
        auwZZYdOIfwj13sFvMA=
      </xenc:CipherValue>
    </xenc:CipherData>
  </xenc:EncryptedData>

Don't you just love the simplicity of XML namespaces!

[Go to top]

The two algorithm identifiers for RSA-OAEP

There are two algorithm identifiers for RSA-OAEP. The original one from 2001 and a more versatile one introduced in 2009 (there was some confusion over the parameters for RSA-OAEP back in the day).
http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p
http://www.w3.org/2009/xmlenc11#rsa-oaep

The rsa-oaep-mgf1p identifier defines the mask generation function (MGF) as the fixed value of MGF1 with SHA1. The rsa-oaep identifier allows the optional xenc11:MGF element to define a different mask generation function using different digest functions. If the MGF element is omitted, the default mask generation function is MGF1 with SHA1. This is explained at the xmlenc-core site https://www.w3.org/TR/xmlenc-core1/#sec-RSA-OAEP.

It is recommended to use at least SHA-256 for the RSA-OAEP DigestMethod parameter and the corresponding mask generation function MGF1 with SHA256.

<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep">
  <xenc11:MGF Algorithm="http://www.w3.org/2009/xmlenc11#mgf1sha256" />
  <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
</xenc:EncryptionMethod>
but using SHA-1 for the MGF mask function is still OK
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#rsa-oaep-mgf1p">
  <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
</xenc:EncryptionMethod>
There is also an optional PSourceAlgorithm parameter, but this is rarely used in practice and is often unsupported (well, we don't!).

Code and example files

Example files used above: xmlenc-examples.zip.

Example code using CryptoSys PKI

See our companion page Using CryptoSys PKI to encrypt and decrypt using XMLENC. It gives code samples showing how to use CryptoSys PKI Pro to carry out the encryption and decryption operations required for the example XML documents.

Extracting information from XMLENC documents using xmlsq

See Using xmlsq and CryptoSys PKI to decrypt XMLENC documents.

References

Glossary of acronyms

CBC
Cipher Block Chaining. A confidentiality mode of operation for symmetric key block cipher algorithms.
CEK
Content-encryption key. A cryptographic key used to encrypt content.
GCM
Galois/Counter Mode. An algorithm for authenticated encryption.
IV
Initialization Vector (or Value). An input parameter that sets the starting state of a cryptographic algorithm or mode.
KEK
Key-encryption key. A cryptographic key used to encrypt other keys.
MGF
Mask Generation Function. Used in RSA-OAEP.
OAEP
Optimal Asymmetric Encryption Padding. The recommended encoding method to use with RSA encryption.

Contact us

To contact us or comment on this page, please send us a message.

This page first published 7 December 2020. Last updated 7 December 2020

[Go to top]