How do I find the recipients and signer of an AMS message?

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.

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

3 thoughts on “How do I find the recipients and signer of an AMS message?

  1. 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?

    Like

Leave a comment