P7S File Documentation
Summary
A .p7s file is a PKCS #7 / S/MIME digital signature: a small attachment that carries a message’s cryptographic signature and the signer’s certificate, not the message text. When an email is signed but not encrypted, S/MIME clients attach it as smime.p7s, and the recipient’s mail program uses it to confirm the message was not altered and came from the certificate holder. Double-clicking it shows binary or Base64 data, because it holds a signature object, not readable content. Its MIME type is application/pkcs7-signature.
Technical details
| Feature | Value |
|---|---|
| Full name | PKCS #7 / S/MIME Digital Signature (smime.p7s) |
| File extension | .p7s |
| MIME type | application/pkcs7-signature |
| Format type | Detached (or wrapped) cryptographic signature; a CMS/PKCS #7 SignedData object |
| Category | Encoded / security files |
| Developer | RSA Security (PKCS #7 v1.5); standardized as CMS by the IETF |
| Introduced | PKCS #7 v1.5 in 1993; S/MIME v2 (RFC 2311) in 1998 |
| Standard / Spec | RFC 5652 (CMS), RFC 8551 (S/MIME 4.0); PKCS #7 v1.5 |
| Open standard | Yes |
| Byte order | Not applicable (ASN.1 is a self-describing tag-length-value stream) |
| Encoding | ASN.1, usually DER (binary); sometimes PEM (Base64 text) |
| Magic number | DER form begins 30 82 (SEQUENCE + 2-byte length); PEM form begins -----BEGIN PKCS7----- |
| Contains | The signature value plus the signer’s X.509 certificate and chain; not the signed content |
| In email | Attached as smime.p7s on a signed (not encrypted) message |
| Related extensions | .p7m, .p7b, .p7c, .cer, .pem, .asc |
| Specification URL | RFC 5652 — Cryptographic Message Syntax |
What is a P7S file?
A .p7s file is a PKCS #7 / S/MIME digital signature. Technically it is a CMS (Cryptographic Message Syntax) SignedData object, the structure defined in RFC 5652. The file carries a cryptographic signature over some content, along with the certificate (and often the full certificate chain) of whoever produced that signature. It does not carry the content itself. That single fact explains almost everything confusing about the format: a p7s is proof about a message, kept separate from the message.
Most people meet it as an email attachment named smime.p7s. When someone sends a signed but unencrypted message, their mail client sends the readable message as usual and attaches this small file. The recipient’s S/MIME-capable client reads it to answer two questions: was the message changed in transit, and did it really come from the address on the certificate. If both check out, the client shows a signed-mail indicator. The same detached-signature format is also used outside email to sign documents and files, which is why government e-invoicing and national e-signature systems often hand you a .p7s sitting next to the file it signs.
The SignedData structure: ContentInfo, certificates and signerInfos
The outermost wrapper is a CMS ContentInfo, an ASN.1 SEQUENCE whose contentType is the object identifier for signedData and whose content is the SignedData structure itself. RFC 5652 defines SignedData with a fixed set of fields, in this order:
SignedData ::= SEQUENCE {
version CMSVersion,
digestAlgorithms SET OF DigestAlgorithmIdentifier,
encapContentInfo EncapsulatedContentInfo,
certificates [0] IMPLICIT CertificateSet OPTIONAL,
crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
signerInfos SET OF SignerInfo }
The version is a small integer chosen by rules in the spec (it depends on which options are present). digestAlgorithms lists the hash algorithms used, for example SHA-256, so a verifier knows what to compute before it has parsed each signer. encapContentInfo describes the content that was signed and, in principle, can carry that content inline; in a detached p7s it does not (see the next section). certificates is the bag that usually holds the signer’s X.509 certificate and any intermediate certificates needed to build a path to a trusted root. The optional crls field can carry revocation information. Finally, signerInfos is a SET of one or more SignerInfo structures, one per signer.
Each SignerInfo is where a specific signature lives:
SignerInfo ::= SEQUENCE {
version CMSVersion,
sid SignerIdentifier,
digestAlgorithm DigestAlgorithmIdentifier,
signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
signatureAlgorithm SignatureAlgorithmIdentifier,
signature SignatureValue,
unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
The sid (SignerIdentifier) points at the certificate that made this signature, either as an issuerAndSerialNumber pair or as a subjectKeyIdentifier. The digestAlgorithm repeats which hash this signer used. signedAttrs and signatureAlgorithm and the raw signature value are covered below. This nesting is why a p7s can hold multiple independent signatures over the same content: several SignerInfo entries, one certificate bag, one shared content reference.
Detached signatures: why the p7s has no message inside
In a detached signature, the eContent element of encapContentInfo is absent. The structure still names an eContentType (what kind of thing was signed), but the actual bytes are not embedded. The signature was computed over content that stays in a separate file, and verification feeds those external bytes back in at check time. This is exactly the arrangement used for signed email: the readable message is the MIME part you see, and smime.p7s is the detached signature over it.
The alternative is a wrapped or enveloped form, where the content is embedded inside the PKCS #7 structure. That is what a .p7m file does, and it is discussed in the comparison section below. The detached choice has a practical advantage for email: the message body stays a normal, readable MIME part that even a client with no S/MIME support can display, while the signature rides along in its own attachment. It also mirrors how detached signatures work in the OpenPGP world, where a .asc or .sig file signs a download without containing it.
Signed attributes: messageDigest, signingTime and the actual signature
When signedAttrs is present, the signature is not computed directly over the content. Instead the content is hashed, that hash is placed inside a messageDigest attribute, and the signature is computed over the DER encoding of the whole set of signed attributes. This indirection is what lets a signer bind extra facts to the content. Three attributes are typical:
- content-type – the type of content that was signed, which must match
eContentTypeso an attacker cannot re-label what was signed. - messageDigest – the hash of the actual content. At verification time the tool re-hashes the content and checks it equals this value; a mismatch means the content changed.
- signingTime – the claimed time of signing. This is asserted by the signer, so on its own it is not trusted time; profiles like CAdES add trusted timestamps for that.
The signatureAlgorithm names the public-key algorithm, commonly RSA (PKCS #1) or ECDSA, and the signature field holds the resulting value. So the full chain of trust in a SignerInfo is: hash the content → put that hash in messageDigest → sign the encoded signed attributes with the signer’s private key → store the result in signature. A verifier reverses it using the public key from the certificate named by sid.
DER and PEM encodings
The whole structure is ASN.1, and ASN.1 needs a concrete encoding on disk. A p7s is almost always DER (Distinguished Encoding Rules), a canonical binary form where every value is a tag byte, a length, and the content. That is why a DER p7s begins with 0x30 (the SEQUENCE tag) followed by 0x82, which introduces a two-byte length for the structure that follows. There is no human-readable header; the file is a self-describing byte stream.
The same object can also be carried as PEM, which is the DER bytes Base64-encoded and wrapped between -----BEGIN PKCS7----- and -----END PKCS7----- lines. PEM is text-safe for pasting into config files or transporting through systems that mangle binary, at the cost of roughly a third more size. The relationship is identical to the one between a binary .cer certificate and its .pem text form: same data, different wrapper. Tools convert between them with the -inform and -outform flags shown below.
How an S/MIME client verifies a signed email
When a signed message arrives, the mail client parses the multipart/signed MIME structure: the first part is the message content, the second is the application/pkcs7-signature attachment, the p7s. Verification proceeds roughly in these steps. The client extracts the signer’s certificate from the SignedData certificates bag. It re-hashes the exact bytes of the signed content and compares that hash against the messageDigest signed attribute. It then verifies the signature value over the signed attributes using the public key in the certificate. Finally it builds and checks the certificate chain: does a path lead from the signer’s certificate up to a root the machine trusts, is the certificate within its validity dates, and (where checked) has it not been revoked.
All four checks must pass for a clean signed indicator. You can perform the same verification by hand with OpenSSL, which is useful for a p7s that signs a file rather than an email:
# Verify a detached signature against its content
openssl smime -verify -inform DER -in smime.p7s \
-content message.txt -noverify
# Inspect the certificates carried inside the p7s
openssl pkcs7 -inform DER -in smime.p7s -print_certs -text
The -noverify flag above skips the trust-chain check so you can confirm the signature math alone; drop it and supply a -CAfile to also validate the chain.
P7S vs P7M vs P7B
The PKCS #7 family reuses the same ASN.1 machinery for different jobs, and the extensions mark the intent. A .p7s is a detached signature: the content stays separate, the file holds the signature plus certificates. A .p7m is enveloped or wrapped: the content is embedded inside the PKCS #7 structure, so the file is self-contained (this form is also used for encrypted S/MIME messages). A .p7b or .p7c is a certificate-only bundle, a SignedData with an empty content and no signers, used purely to ship a set of certificates such as a chain for import into a keystore.
The practical tell is what you receive alongside the file. A p7s usually arrives next to the thing it signs (an invoice plus its .p7s, or a message plus smime.p7s). A p7m arrives alone, because it already contains its content. A p7b arrives when someone needs to hand you certificates, for instance to install an intermediate CA. The same underlying format also signs documents in other containers, and a signed PDF embeds equivalent CMS SignedData inside the document rather than in a separate file.
Trust, not just validity: what a signature does and does not prove
Because this is a security format, three points matter more than any parsing detail. First, signed is not encrypted. A signed email with a smime.p7s attachment is still sent in the clear; anyone who can read the traffic can read the message. The signature protects integrity and origin, not confidentiality. Confidentiality needs encryption (the enveloped p7m form), which is a separate operation.
Second, a valid signature is not a statement that the content is safe. Verification proves two things only: the content was not altered after signing, and it was signed by the holder of a particular certificate. It does not prove the content is honest or harmless. Someone who legitimately holds a valid certificate can sign a phishing message or a malicious attachment, and it will verify as a good signature. Treat “valid signature” as “confirmed sender identity,” not as “trustworthy message.”
Third, a signature is only as strong as its trust chain. A green “valid” badge means little if the signing certificate is self-signed or chains to a root you have no reason to trust. The meaningful check is whether the certificate leads to a trusted authority, is still within its validity period, and has not been revoked, and whether the identity on it is the one you actually expected. The p7s file itself contains no executable code; the risk is never the file running, it is a human over-trusting a “signed” label.
One more note for anyone handling long-lived signatures: the ETSI TS 101 733 CAdES (CMS Advanced Electronic Signatures) profile builds on CMS to add attributes like trusted signing-time (timestamps), signer certificate references, and data needed for long-term validation. A plain p7s verifies today; a CAdES-profiled signature is designed to stay verifiable years later, after certificates expire.
FAQ
What is smime.p7s in an email? It is the S/MIME digital signature attached to a signed message. It holds the signature and the sender’s certificate, and the mail client uses it to confirm the message was not altered and came from that certificate holder. It is not part of the message you need to read.
What is the difference between .p7s and .p7m? A p7s is a detached signature: the signed content stays in a separate file. A p7m is wrapped: the content is embedded inside the PKCS #7 structure (and p7m is also used for encrypted messages), so it is self-contained.
Why does opening smime.p7s show gibberish? Because it is a DER-encoded ASN.1 signature object, not text. Double-clicking it displays raw binary (or Base64, in PEM form). There is nothing to read; it is meant to be processed by a mail client or a tool like OpenSSL.
Does a valid signature mean the email is safe? No. A valid signature proves the sender’s identity and that the message was unchanged. It does not prove the content is safe or honest, and it only means anything if the certificate chains to an authority you trust.
References
- RFC 5652 — Cryptographic Message Syntax (CMS)
- RFC 8551 — S/MIME 4.0 Message Specification
- OpenSSL — smime and pkcs7 command reference
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.