When you have a problem trying to decrypt/get a protected message, the message can end up on the AMS dead letter queue. This blog post explains how to look into the message and find the list of recipient, and the signer of the data.
This started off as a short blog post, then as I added more background and more detailed instructions it just grew!
The sections are
- Background on the format of the protected message
- 30 second overview of ASN.1 encoding
- What does signed data look like?
- What does encrypted data look like?
- How to map Issuer+ serial number to subject
- Decrypting the data
- Using Java to look at the data
Background on the format of the protected message.
The protected message conforms to the PKCS#7 protocol as defined here.
The specification defines six formats, of which three are:
- signed data
- envelopedData where data is wrapped in an opaque envelope – it has been encrypted
- signedAndEnveloped.
These may look like the AMS classes: Integerity, Confidential, and Privacy; close – but no cigar. AMS does the signing before encryption, and so only signed data, and envelopedData are used. To see who signed a privacy message, you have to decrypt it.
I wrote a program to browse the messages on a queue, and write the protected data out to a Linux file. You can use openssl tools to explore file.
There is a PDMQ header at the front of the data. This has a variable length
- at offset 0 is “PDMQ” in ASCII.
- like other variable length MQ structures, at offset 8 is an MQLONG StrucLength. Don’t forget you may need to convert from big-endian to little-endian on some platforms.
- The data after the header is the data is ASN.1 encoded, starting with x’30’.
30 second overview of ASN.1 encoding
ASN.1 encoding takes data like “typeOfRequest,{[id1,key1],[id2,key2]} and converts it into
- a SEQUENCE (the items have an order) of typeOfRequest, keys
- where keys are a SET (because it does not matter if the order is id1, id2, or id2, id1)
- ID is an integer…
Terms like countryName C=GB map into a String of type 2.5.4.6 with length 2 and value GB.
When this is decoded it take 2.5.4.6 and says this is CountryName. You can look up the id here. There is a document with popular ones in it.
You can use openssl to format a file of ASN.1 encoded data and interpret the values. For example
openssl asn1parse -inform DER -in colin.pkj -i -offset 104 > asn1
says
- openssl asn1parse this command
- -inform DER in format is decimal encoded (not base 64)
- -in colin.pkj this is the input file
- -i says indent the output to prettify it
- -offset 104 skip over the PDMQ header
- > asn1 write the output to the file asn1
When I changed my program to skip over the PMDQ header and write out just the data, I didn’t need the -offset parameter.
I’ve also used this to display the contents of a certificate in .der format.
What does signed data look like?
The spec says signed data looks like
ContentInfo ::= SEQUENCE { contentType ContentType, content } where contentType is SignedData... SignedData ::= SEQUENCE { version Version, digestAlgorithms DigestAlgorithmIdentifiers, contentInfo ContentInfo, certificates signerInfos SignerInfos }
The start of the output of the openssl asn1parse command for an integrity message contained
0:d=0 hl=4 l=1723 cons: SEQUENCE 4:d=1 hl=2 l= 9 prim: OBJECT :pkcs7-signedData 15:d=1 hl=4 l=1708 cons: cont [ 0 ] 19:d=2 hl=4 l=1704 cons: SEQUENCE 23:d=3 hl=2 l= 1 prim: INTEGER :01 26:d=3 hl=2 l= 15 cons: SET 28:d=4 hl=2 l= 13 cons: SEQUENCE 30:d=5 hl=2 l= 9 prim: OBJECT :sha256 41:d=5 hl=2 l= 0 prim: NULL 43:d=3 hl=2 l= 20 cons: SEQUENCE 45:d=4 hl=2 l= 9 prim: OBJECT :pkcs7-data 56:d=4 hl=2 l= 7 cons: cont [ 0 ] 58:d=5 hl=2 l= 5 prim: OCTET STRING :AAAAA
The columns are
- offset from the start
- d= nesting depth, so a sequence within a set, within a sequence would be d=3
- dl= length of length field
- l= length of the field
- cons|prim. I think of these as
- cons is construction … SEQ, SET etc.
- prim is primary data
- SEQUENCE, OBJECT, INTEGER type of value
Looking at the output
- at offset 4 we have ContentType which is :pkcs7-signedData
- at offset 23 we have the SignedData version :01
- at offset 30 we have a SET of digestAlgorithms, there is one in the SEQUENCE and it has the value :sha256
- at offset 45 we have contentInfo :pkcs7-data
- at offset 58 we have the message data, the very boring AAAAA.
After the data we have signer info
SignerInfo ::= SEQUENCE { version Version, issuerAndSerialNumber IssuerAndSerialNumber, digestAlgorithm DigestAlgorithmIdentifier, authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL, digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, encryptedDigest EncryptedDigest, unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL }
Extracting the interesting fields out of the data (to make it easier to read)
- Certificate serial number: 01B0
- Issuer:
- countryName:GB,
- organizationName:SSS,
- organizationalUnitName: CA,
- commonName:SSCARSA1024
- Not before time: 210328172922Z
- Not after time: 231223172922Z
- Subject:
- countryName:GB,
- organizationName:aaaa,
- commonName: ja2
- digestAlgorithm: rsaEncryption
- X509v3 Key Usage:….
- X509v3 Subject Alternative Name…
- digestEncryptedAlgorithm: sha256WithRSAEncryption
- …
What does encrypted data look like?
The spec says
EnvelopedData ::= SEQUENCE { version Version, recipientInfos RecipientInfos, encryptedContentInfo EncryptedContentInfo } RecipientInfos ::= SET OF RecipientInfo EncryptedContentInfo ::= SEQUENCE { contentType ContentType, contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
Instead of listing the DN’s of the recipients, it listed CA certificate + serial number (which equates to the same thing). As a self signed has signed itself, there is an entry for the self signed.
4:d=1 hl=2 l= 9 prim: OBJECT :pkcs7-envelopedData 23:d=3 hl=2 l= 1 prim: INTEGER :00 42:d=8 hl=2 l= 9 cons: SEQUENCE self signed C=GB,O=AAA,CN=colinPaice, serial=606439D5 44:d=9 hl=2 l= 3 prim: OBJECT :countryName 49:d=9 hl=2 l= 2 prim: PRINTABLESTRING :GB 57:d=9 hl=2 l= 3 prim: OBJECT :organizationName 62:d=9 hl=2 l= 3 prim: PRINTABLESTRING :AAA 71:d=9 hl=2 l= 3 prim: OBJECT :commonName 76:d=9 hl=2 l= 11 prim: PRINTABLESTRING :colin paice 89:d=6 hl=2 l= 4 prim: INTEGER :606439D5 97:d=6 hl=2 l= 9 prim: OBJECT :rsaEncryption the following is the encrypted key for this user 110:d=5 hl=3 l= 128 prim: OCTET STRING [HEX DUMP]:861C...F2 241:d=4 hl=4 l= 348 cons: SEQUENCE 245:d=5 hl=2 l= 1 prim: INTEGER :00 248:d=5 hl=2 l= 68 cons: SEQUENCE This is the issuer C=GB,O=SSS,OU=CA,CN=SSCARSA1024, serial 1B0 256:d=9 hl=2 l= 3 prim: OBJECT :countryName 261:d=9 hl=2 l= 2 prim: PRINTABLESTRING :GB 269:d=9 hl=2 l= 3 prim: OBJECT :organizationName 274:d=9 hl=2 l= 3 prim: UTF8STRING :SSS 283:d=9 hl=2 l= 3 prim: OBJECT :organizationalUnitName 288:d=9 hl=2 l= 2 prim: UTF8STRING :CA 296:d=9 hl=2 l= 3 prim: OBJECT :commonName 301:d=9 hl=2 l= 11 prim: UTF8STRING :SSCARSA1024 314:d=6 hl=2 l= 2 prim: INTEGER :01B0 318:d=5 hl=2 l=13 cons: SEQUENCE 320:d=6 hl=2 l= 9 prim: OBJECT :rsaEncryption the following is the encrypted key for this user 333:d=5 hl=4 l=256 prim:OCTET STRING [HEX DUMP]:35..7BF This is for Issuer O=TEMP, OU=TEST,CN=TEMP4Certification Authority Serial = 5D 593:d=4 hl=4 l= 354 cons: SEQUENCE 597:d=5 hl=2 l= 1 prim: INTEGER :00 608:d=9 hl=2 l= 3 prim: OBJECT :organizationName 613:d=9 hl=2 l= 4 prim: PRINTABLESTRING :TEMP 623:d=9 hl=2 l= 3 prim: OBJECT :organizationalUnitName 628:d=9 hl=2 l= 4 prim: PRINTABLESTRING :TEST 638:d=9 hl=2 l= 3 prim: OBJECT :commonName 643:d=9 hl=2 l= 28 prim: PRINTABLESTRING :TEMP4Certification Authority 673:d=6 hl=2 l= 1 prim: INTEGER :5D 678:d=6 hl=2 l= 9 prim: OBJECT :rsaEncryption the following is the encrypted key for this user 691:d=5 hl=4 l= 256 prim:OCTET STRING [HEX DUMP]:6A...68 951:d=3 hl=2 l= 76 cons: SEQUENCE 953:d=4 hl=2 l= 9 prim: OBJECT :pkcs7-data 964:d=4 hl=2 l= 29 cons: SEQUENCE 966:d=5 hl=2 l= 9 prim: OBJECT :aes-128-cbc 977:d=5 hl=2 l= 16 prim: OCTET STRING [HEX DUMP]:9D...543A
There were three recipients configured for the queue (setmqspl -r option)
- CN=ja2, O=aaaa, C=GB. See offset 256 to 333, giving the Issuer, the certificate serial number, encryption type, and the hex dump of the encrypted key.
- Serial Number: 01 B0
- Issued by: CN=SSCARSA1024, OU=CA, O=SSS, C=GB
- CN=colin paice, O=AAA, C=GB See offset 44 to 110, giving the Issuer (this is self signed), the certificate serial number, encryption type, and the hex dump of thea encrypted key.
- Serial Number: 60 64 39 D5
- Issued by: CN=colin paice, O=AAA, C=GB
- CN=ADCDB,O=SSS. See offset 597 to 691, giving the Issuer, the certificate serial number, encryption type, and the hex dump of the encrypted key.
- Serial Number: 5D
- Issued by: CN=TEMP4Certification Authority, OU=TEST, O=TEMP
It was not easy to take the issuer information and map this to the Subject. I had to go through the whole of my keystore to find the information.
How to map Issuer+ serial to subject
For .jks keystores you can use
keytool -list -keystore ja2.jks -storepass zpassword -v |grep ‘Serial\|Issuer:\|Owner:’ | less
and search for the serial Issuer CN, and the serial number which follows it. For example
Owner: CN=ja2, O=aaaa, C=GB
Issuer: CN=SSCARSA1024, OU=CA, O=SSS, C=GB
Serial number: 1b0
For .CMS I used a bash shell script to extract the contents, then display the details of each label.
ks="/home/colinpaice/mq/zzserver.kdb" pw="password" z=runmqakm -cert -list -db $ks -pw $pw | awk '{print $2}' for x in $z;do runmqakm -cert -details -db $ks -pw $pw -label $x |grep 'Serial\|Issuer\|Subject' done
What encryption algorithm was used?
At offset 966 is
966:d=5 hl=2 l= 9 prim: OBJECT :aes-128-cbc
The aes128 matches the -e AES128 option on the queue.
What does privacy look like?
Just like encrypted. it has
955:d=4 hl=2 l= 9 prim: OBJECT :pkcs7-signedData
instead of
953:d=4 hl=2 l=9 prim: OBJECT:pkcs7-data
The signing data is encrypted, so cannot be viewed.
Decrypting the data
If you have a file of the data, you can use openssl cms to decrypt it. The example below uses the private key for ja2 in ja2.key.pem. ( I knew it was ja2’s key file from the information above).
openssl cms -decrypt -in colin.pkj -inform der -inkey ~/ssl/ssl2/ja2.key.pem -out colin.der
Now that it is decrypted, display the signed package
openssl asn1parse -inform DER -in colin.der -i
and I can see information about the signer: the issuer, the signer and the signing time; and the payload.
Using Java to look at the data
You can use Java to process the message, using code from bouncycastle (used by MQ).
Read the message as a byte array (data) and use
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.util.ASN1Dump;
....
ASN1InputStream ais = new ASN1InputStream(data);
ASN1Primitive obj = ais.readObject();
System.out.println(ASN1Dump.dumpAsString(obj, true));
This produces output like the ans1parse above but without the conversion of 2.5.4.6 to CountryName etc. You can either guess the meaning, or look it up here.
ObjectIdentifier(1.2.840.113549.1.7.2) Tagged [0] Sequence Integer(1) Set Sequence ObjectIdentifier(2.16.840.1.101.3.4.2.1) NULL Sequence ObjectIdentifier(1.2.840.113549.1.7.1) Tagged [0] DER Octet String[3] 424242 BBB Tagged [0] Sequence Sequence Tagged [0] Integer(2) Integer(432) Sequence ObjectIdentifier(1.2.840.113549.1.1.11) NULL Sequence Set Sequence ObjectIdentifier(2.5.4.6) PrintableString(GB) Set Sequence ObjectIdentifier(2.5.4.10) UTF8String(SSS) Set Sequence ObjectIdentifier(2.5.4.11) UTF8String(CA) Set Sequence ObjectIdentifier(2.5.4.3) UTF8String(SSCARSA1024) Sequence UTCTime(210328172922GMT+00:00) UTCTime(231223172922GMT+00:00)
Other AMS blog posts
- Overview and challenges of using end to end message encryption (AMS).
- Certificate and keyring management for AMS.
- Installing AMS on z/OS.
- What certificates do I need for AMS with a client going to z/OS?
- checkAMS: program to check your AMS defintions are consistent with z/OS keyring
- Adding more users to AMS.
- Installing AMS on midrange for end to end message protection
- Understanding setmqspl to set up AMS definitions.
- How to administer AMS policies, and use the set policy command.
- Brain check and reset, needed for AMS keystores on midrange.
- Using runamscred to encrypt the passwords in the keystore.conf file.
- How do I find the recipients and signer of an AMS message?
- I have a message on the AMS DLQ – what can I do about it? and How do I process messages on the dead letter queue (DLQ)?
Thanks for article; is there any MQ utility (or plugin to MQ explorer) that can help view messages with these AMS fields in them, in a meaningful way, with the various fields decoded?
LikeLike
Not that I know of, you could raise a requirement (RFE) on MQ. Though I could imaging that giving the fields decoded ( such as recipients CN could be considered weakening the strength of the encryption. The the MQ user community
https://community.ibm.com/community/user/integration/communities/community-home?CommunityKey=183ec850-4947-49c8-9a2e-8e7c7fc46c64
LikeLike