SAP Cloud Integration: Understanding PKCS #7/CMS Splitter
SAP Cloud Integration (CPI) provides functionality to automatically split a message with PKCS#7 / CMS compliant signature.
This blog post explains what it is about that splitting, how it works and the meaning of the configuration options.
A simple tutorial helps to understand the theory in real life.
To better understand the PKCS#7 / CMS Encryptor we need to understand the PLKCS#7 and CMS standards.
I’ve tried to explain the standard and everything around it with easy words in a separate blog post, so I recommend to read through it.
The Splitter works on messages with digital signature, so I recommend reading my previous Signer blog post.
For remaining open questions I recommend the Security Glossary.
To follow this tutorial, access to a Cloud Integration tenant is required, as well as basic knowledge about creating iFlows.
First of all, we need an understanding of the PKCS #7 or CMS standard.
It started with the need of transmitting messages in a secure way.
Messages can be eMails or messages between systems, they can carry secret text content, or any other content (like images etc).
To safeguard them, there can be different measures like encryption, digest, digital signature, MAC, etc
When securing a message, it should be done according to a guideline, which specifies how the security is applied.
Furthermore, it has to be concretized how the required artifacts (certificates, digest) and metadata (algorithms) are transferred along with the message.
This guideline was developed and published in the series of “Public Key Cryptography Standards” as number 7 ( PKCS #7)
Later, it was renamed to “Cryptographic Messaging Syntax” (CMS), when handed over to IETF organization.
If no guideline (standard) would exist, a receiver would not be able to know how to decrypt the received binary message.
Fortunately, we have the standard and we have tools like CPI that are compliant with the standard and as such, can exchange secure messages with the world and everybody knows how to send or read and everybody is happy.
The CMS guideline describes how to apply the mentioned different security measures (encrypt, sign, etc) to a message.
Such measures are called “types” and one of them is the “SignedData” type.
In this case, the guideline describes e.g. that
- a digest of the content is created
- The info about the used algorithm is added to the message
- the digest is encrypted with a private key
- the info about the algorithm (used for encryption) is added to the message.
- the public key certificate is added to the message
- the info about the certificate is added to the message
- the content itself is added to the message
And so on.
However, some of the artifacts are optional, e.g. the content itself and the certificate.
Depending on the size of the content and the amount of certificates, that can help to improve performance.
If the sender choses to separate the content from the CMS-package (SignedData), we talk about “external signature” or “detached mode”.
Now coming to CPI.
If the sender didn’t chose the “detached mode”, but we want to apply it afterwards, we can use the PKCS #7 / CMS Splitter.
It will separate the content from the signature (the actual CMS-package) and thus arrange the “detached mode”
There’s one more information about it.
When signing a message using the PKCS #7 / CMS Signer in CPI, we have an option to not “include the content in Signed Data”.
This has the effect of choosing the “detached mode” as well.
However, the difference is:
- The Signer sends the content in the message body and the signature in a property
- The Splitter sends 2 messages
How does it work?
The Splitter takes an existing message as input and divides it into 2 messages.
The input message must be a CMS-based SignedData-message.
The input message must not be base64-encoded.
The input message must include the content.
The output messages are processed consecutively.
The output messages don’t contain the certificate.
The order of the 2 output messages can be configured.
The Splitter works on digital signatures.
The Splitter does refactoring.
The Splitter converts a “normal” SignedData-message to “detached mode”.
The detached mode is such that content and signature are contained in 2 consecutive messages.
2. Splitter Configuration
In this chapter we’re going to have a closer look at the meaning of the configuration options for the Splitter and see if any explanation is required.
Below screenshot shows the property sheet for PKCS#7 / CMS Splitter:
Let’s go through the configuration options and explain one by one.
2.1. “Payload File Name” and “Signature File Name”
The Splitter will divide the 1 message into 2 messages and for each message we can specify a filename or our choice.
However, this setting is only relevant for scenarios dealing with files, e.g. an SFTP receiver.
2.2. Wrap by Content Info
First of all, we should remember the “Content Info”…
What is Content Info?
It is described in the CMS spec, at the beginning.
At the end of the day, the CMS structure does nothing than:
Give info about the content.
In this context, “Content” means:
The full content of the whole CMS package, all artifacts and metadata.
As such, the first thing that the “Content Info” informs about is:
What is the content of the CMS-package?
Does the CMS package contain a digital signature? Or an encrypted message? Or a MAC ? etc
We have to distinguish 2 meanings of “content”:
As mentioned, the content of whole CMS-package.
The CMS-package contains certificates, encrypted digest, information about the algorithms, etc
And it usually contains the actual “content” that is intended to be transmitted to the receiver(s).
In the CMS-language, this is the “encapsulated content”. The original text content, or image content, that is meant to be secured according to the CMS-specification.
So, the first thing that a receiving, CMS-compliant tool will check is:
Read the root node, the “content info”, to get informed about the type of the content, the “content type”.
If the content-type is e.g. “SignedData”, then the tool knows which methods to apply in order to verify the digital signature.
What about the checkbox in CPI?
The checkbox allows to configure if this root node of the CMS structure is contained in the signature – or not.
So if we deselect this option, the resulting external signature does not contained the root node, no “content info”.
This means that the CMS-structure is broken and a CMS-tool like OpenSSL cannot process it.
As such, this option should normally be always enabled – unless we have an own CMS implementation that provides its own root, or similar.
Let us visualize the difference between the 2 modes of this setting.
I’ve used the Splitter to create signature files with and without root node.
The result can be viewed in an ASN.1 Editor.
1. Signature with root node
Below screenshot shows a normal CMS structure:
I’ve added my comments in red color.
We can see:
– The root node of the CMS structure (Content Info) informs that the CMS package contains an element of type “SignedData”.
– The version is 1
– The algorithm for signing, that was chosen in CPI, was “SHA-512”.
– The content is missing, so it is being sent in “detached mode”, this was done by the Splitter.
– although missing, the type of the content can be read as “data”
– The element “encapsulated content info” should contain subnodes with the type of the content, but also the content itself.
– The signer certificate and crls (certificate revocation lists) are missing, no prob, they are optional (like the content is optional as well).
– But we can see the info about the required signer certificate: the common name is “myowncert”.
For our convenience, let’s view the same structure with the OpenSSL output.
We’ve learned in the previous blog posts, that some OpenSSL commands support an option that prints the CMS structure to a file.
2. Signature without root node
Below screenshot shows the CMS structure of a signature where it was decided to not “Wrap by Content Info”:
We can see that it starts directly with the structure of a “SignedData” element, but the OID of the “SignedData” element itself is missing.
In this case, the OpenSSL command fails to verify (even no “false”-response) because of broken CSM structure. As such, it cannot print the CMS structure.
Below screenshot clarifies about the missing piece of the structure:
The red rectangle marks the excerpt that is contained in a message with “wrap” disabled.
2.3. Payload First
The PKCS #7 / CMS Splitter takes an incoming message and splits it into 2 messages.
Here we get the chance to configure, which of the 2 messages should be processed first.
The meaning of this setting is very simple, but let’s take the opportunity to look into the processing flow.
Below screenshot is taken from the debug view of the CPI message monitor:
We can see that in a first step, the splitter splits the 1 message into 2 messages.
Afterwards every message is processed until the end.
In the current example, the Splitter is configured to process the “Payload First”.
2.4. “Base64 Payload” and “Base64 Signature”
These settings are self-explaining:
If selected, then the resulting messages will be encoded with Base64
What is it about?
In case of digital signatures, the content is plaintext and the digital signature is binary.
Digital signatures don’t intend to hide the content, but ensure that the content is not modified.
If we don’t enable this checkbox for the signature, then the message body will be sent over the network as encrypted (binary) data.
This might cause problems, related to special characters that might get lost if transport protocol doesn’t handle properly.
When encoding with Base64, we’re on the safe side, because the character set that is used to transfer the message contains only normal characters (alphabet upper and lower case, numbers and 3 others => 64).
As Cloud Integration will always send messages over wire, enabling this setting would always make sense.
After message processing, the receiver will base64-decode the message, then continue with normal signature verification, i.e. decrypt the hash.
I’m confused: Encoding? Encryption?
Agree, it is confusing because sometimes both terms are even used synonymously.
But in fact, the difference is:
Encryption makes the data un-understandable.
Encoding just transforms the data into different format.
Decryption requires secret password or key.
Decoding is open and can be done by everybody.
(Note: explanation copied from previous blog post in plaintext)
To fully avoid misunderstanding:
The Splitter cannot process an incoming message that is base64-encoded.
This setting refers only to the outcome of the slitting.
3. Hands-On Example
Let’s go through a very simple integration flow, to try it out.
No prerequisites, no tools no adapters required.
3.1. Create Key Pair
We let CPI generate a key pair for us.
This is done in the Keystore of Cloud Integration.
Go to your CPI -> “Operations & Monitoring” -> “Manage Security” -> “Keystore”
Choose “Create” -> “Key Pair”
Enter some values of your choice, e.g. “simplecert” and press “Create”.
The alias is required later, we can take a note of it, or try to remember (or follow my description).
3.2. Create iFlow
To test the Splitter with minimum effort, we design a simple iFlow that doesn’t require external connections and defines some dummy message content on the fly.
We create an iFlow with the following elements:
- Start Timer set to “Run Once”.
- Content Modifier with arbitrary text in Message Body.
- PKCS#7 Signer with “Private Key Alias” and default settings (“Include Content” is enabled).
- PKCS#7 Splitter with default settings (no file names required).
- Datastore Write operation with arbitrary name.
After deploy and successful execution of the iFlow, we go to our Data Store and realize that there are 2 entries.
So the Splitter has done a good job.
According to our configuration, the lower entry – the first one starting from bottom – should contain the message payload, the plaintext content.
To check, we download it and view the “body” file, to see that in fact, it contains the secret text.
3.3. Optional: Verify the result messages with OpenSSL
Maybe you’ve followed my previous blog post and you’re now curious to see how OpenSSL might deal with the result of the PKCS #7 / CMS Splitter?
To try it, we download both result messages of the Data Store, extract and rename the “body” files to content.txt and signature.enc.
Both files should be located in the same folder that contains the certificate with name cert.pem (containing the public key).
So we can compose the verify command as follows:
openssl cms -verify -noverify -inform DER -content content.txt -certfile cert.pem -in signature.enc -out verified
-content: The signature file doesn’t include the content, because it was divided by the splitter. As such we specify the content via parameter. It is contained in the file that we extracted from the first message.
-certfile: The CMS-package, which is contained in the signature file, doesn’t include the certificate, so we add it via this option.
The result should be a success message on the console.
Optional: Base64 decode
If the Splitter is configured to base64-encode the messages, the following command can be used to decode:
openssl enc -base64 -d -in payload_base64.txt -out content.txt
-d indicates that decoding is desired.
If OpenSSL decoding results in an empty file, you might need to add a Line feed at the end of your encoded file.
Optional: view CMS structure
Below options print the full cms structure.
They can be simply appended to the above verification command.
In this blog post we’ve learned what the Splitter is used for and how it works.
We need to understand the PKCS #7 or CMS standard, to understand the Splitter.
A message has been signed according to the CMS specification.
This means that the message contains the original content itself, but also artifacts like the digital signature, certificates and it contains information about used algorithms etc
According to the CMS standard, such a message has the content type “SignedData”.
It is not mandatory that the original content is included in the message, e.g. in case of big size.
Separating the content from the other artifacts can be achieved with the Splitter.
The Splitter works in a way that it creates 2 messages, the original content and the digital signature (along with artifacts and metadata)
Afterwards, the 2 messages can be used for verification.
A CMS-compliant verifier should allow to pass the content and certificate as additional parameter (like OpenSSL does)