The practical answer to this is: use a library. There are many available, and they already handle the complicated details below plus many more that exist in PKCS7/CMS in general but are not in this rather simple case. However, that is offtopic for crypto; try softwarerecs for help selecting one, and stackoverflow if you have specific problems using it.
The current version of CMS, the successor to PKCS7, is rfc5652 and I will use that as the most convenient reference, although the features used in your message haven't changed since pretty early days.
The outermost structure of any PKCS7/CMS message is defined in section 3:
ContentInfo ::= SEQUENCE {
contentType ContentType,
content [0] EXPLICIT ANY DEFINED BY contentType }
ContentType ::= OBJECT IDENTIFIER
You have OID 1 2 840 113549 1 7 2 so the content is a signed message expressed as type SignedData
from section 5.1 et seq:
SignedData ::= SEQUENCE {
version CMSVersion,
digestAlgorithms DigestAlgorithmIdentifiers,
encapContentInfo EncapsulatedContentInfo,
certificates [0] IMPLICIT CertificateSet OPTIONAL,
crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
signerInfos SignerInfos }
DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
SignerInfos ::= SET OF SignerInfo
At offset 23 you have version
1, at 26 digestAlgorithms
consisting of the AlgId for sha1 (with no parameters) which is the only digest that will be used in signing this message, and at 39 the signed content which is a nested PKCS7/CMS structure which is an Enveloped (encrypted) message; I'll treat that as a blob for now and come back to it later. You have NO CERTIFICATE(S) OR CRL(S) and at 447 a SET containing one SignerInfo
which is defined in 5.3 with some help from X.501 and X.509 via 10.2.4:
SignerInfo ::= SEQUENCE {
version CMSVersion,
sid SignerIdentifier,
digestAlgorithm DigestAlgorithmIdentifier,
signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
signatureAlgorithm SignatureAlgorithmIdentifier,
signature SignatureValue,
unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
SignerIdentifier ::= CHOICE {
issuerAndSerialNumber IssuerAndSerialNumber,
subjectKeyIdentifier [0] SubjectKeyIdentifier }
SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute
Attribute ::= SEQUENCE {
attrType OBJECT IDENTIFIER,
attrValues SET OF AttributeValue }
AttributeValue ::= ANY
SignatureValue ::= OCTET STRING
IssuerAndSerialNumber ::= SEQUENCE {
issuer Name,
serialNumber CertificateSerialNumber }
CertificateSerialNumber ::= INTEGER
At 455 you have version 1; at 460 a Distingished Name C=US,O=ABC,CN=CA that is the issuer of your signer's certificate, and is presumably an in-house or test CA; at 505 the serial number of your signer's certificate. If a CA operates properly according to standards, every certificate it issues is UNIQUELY IDENTIFIED by the combination of issuer name and serial number.
At 523 you have a single AlgId for sha1, which is the digest for this signature, at 534 the implicitly-tagged-context-0 SET of signedAttrs
with the following elements each of which is an OID plus a SET containing some value(s):
(1 2 840 113549 1 9 3) contentType with single value OID (1 2 840 113549 1 7 3) envelopedData redundantly specifying the type of content being signed
(1 2 840 113549 1 9 37 3) which is in the arc assigned to the former RSA company and by it to PKCS9, but not assigned in that arc and thus invalid, with value an OCTET STRING whose meaning is unknown
(1 2 840 113549 1 9 4) messageDigest with value an OCTET STRING containing the SHA-1 digest of the signed content encoding, according to the rules stated in section 5.4
Finally at 633 you have an AlgId for the signature algorithm (in early versions called the digest encryption algorithm) specifying RSA using the older OID which means the scheme originally defined in PKCS1v1 and now named RSASSA-PKCS1-v1_5 in PKCS1v2+ (currently rfc8017), and at 646 an OCTET STRING wrapping the actual signature value, which for RSA is a simple byte string that represents an unsigned integer computed as $s = r^e\mod n$ where the 'representative' $r$ is derived from the digest of the signedAttrs encoded as per section 5.4.
Thus to verify this signed message you need to:
- locate or obtain the certificate identified by the issuer name and serial number
- validate the certificate to check it is issued by a CA you trust, is not tampered with or forged (the certificate's signature verifies using the CA's public key), is not expired or revoked or otherwise invalid and allows use of the key for signing data and if applicable more specifically allows signing whatever kind or category of data is in this message, and is issued to a person, organization, system or other entity you believe can legimately originate or otherwise sign such data
- verify the signature on the signedAttrs encoding using the public key in the certificate, and the digest value in the messageDigest attribute against a recomputed digest of the encapContentInfo value
Turning now to the enveloped data that is the signed content, it is defined in 6.1 et seq:
EnvelopedData ::= SEQUENCE {
version CMSVersion,
originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
recipientInfos RecipientInfos,
encryptedContentInfo EncryptedContentInfo,
unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
OriginatorInfo ::= SEQUENCE {
certs [0] IMPLICIT CertificateSet OPTIONAL,
crls [1] IMPLICIT RevocationInfoChoices OPTIONAL }
RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo
EncryptedContentInfo ::= SEQUENCE {
contentType ContentType,
contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
EncryptedContent ::= OCTET STRING
UnprotectedAttributes ::= SET SIZE (1..MAX) OF Attribute
At 62 you have version 0, no originatorInfo
, and at 65 a single RecipientInfo
defined in 6.2 and for this case 6.2.1:
KeyTransRecipientInfo ::= SEQUENCE {
version CMSVersion, -- always set to 0 or 2
rid RecipientIdentifier,
keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
encryptedKey EncryptedKey }
RecipientIdentifier ::= CHOICE {
issuerAndSerialNumber IssuerAndSerialNumber,
subjectKeyIdentifier [0] SubjectKeyIdentifier }
EncryptedKey ::= OCTET STRING
At 73 you have version 0, at 73 an issuer name (same as for the signature) and at 123 a serial number (different) which together identify the certificate whose public key was used to encrypt the 'content' key (aka DEK), at 141 an AlgId for the key encryption algorithm which is RSA-OAEP as per PKCS1v2, and at 156 a BIT STRING wrapping the encrypted key value.
Finally at 417 you have encryptedContentInfo
containing at 419 an OID for the data, at 430 an AlgId identifying the data encryption algorithm using OID (1 2 840 10047 1 1) which according to http://oid-info.com is assigned by ANSI X9F to TDEA ECB, and -- NO ENCRYPTED DATA.
If there were encrypted data, decrypting it would be fairly complicated, but since there is no encrypted data, there is no decrypted data either, and an absence of any data is the same absence no matter what data would have been present if it weren't absent. Although possibly the message has been tampered with to remove the data; if so the signature verification process above will have returned failure.
As Cordy tells the Furies, "got it, and, ew"