cms.sh is a shell script for signing arbitrary data, with the resulting PKCS7 signature and data concatenated into a single output file. It can also verify the signed data while optionally extracting the data to a file or stdout, or extract without verifying.
In an application for secure distribution of data files, combining the signature and data in a single file can help prevent the signature from being lost or ignored, as it might be with a detached signature. A signed file can also be attached and extracted from email, independent of any SMIME signature on the mail, and does not rely on the client mail system to verify the signature.
Usage: cms.sh [config_options] [-q] -s|-v|-e|-i|-I infile [outfile|-]
-q quiet, no verbose output
-s sign, signed data is {infile_basename}.cms in current directory unless otherwise specified by outfile
-v verify, no data extracted unless otherwise specified by outfile
-e extract data to stdout unless otherwise specified by outfile
-i info, display signature date and signer certificate issuer and subject
-I display the entire pkcs7 structure
config_options:
-CAfile cafile # used for signing and verifying, default = demoCA/cacert.pem
-signer signer_cert # used for signing, default = testcert.pem
-inkey signer_key # used for signing, default = testkey.pem
temporary $sig file is created in current directory and removed at end
signed data is signature concatenated with data: cat "$sig" "$data"
signature is created using: openssl cms -sign -binary
signature is verified using: openssl cms -verify -binary
signature is extracted using: openssl cms -cmsout
data is extracted using: tail -c "+$((siglen+1))"
Notes
To create demo CA and certificate for testing:
CA.pl -newca; CA.pl -newreq; CA.pl -sign; mv newkey.pem testkey.pem; mv newcert.pem testcert.pem
To decrypt private key: openssl pkey < testkey.pem > j; mv j testkey.pem
Examples
$ echo hi > data $ ./cms.sh -s data Signing data -> data.sig Checking data.sig Verifying signature CMS Verification successful Writing cms to data.cms Removing data.sig $ ./cms.sh -q -s data $ ./cms.sh -v data.cms Extracting data.sig Verifying signature CMS Verification successful Removing data.sig $ ./cms.sh -v data.cms - Extracting data.sig Verifying signature and writing data to stdout hi CMS Verification successful Removing data.sig $ ./cms.sh -v data.cms d2 Extracting data.sig Verifying signature and writing data to d2 CMS Verification successful Removing data.sig $ cat d2 hi $ ./cms.sh -e data.cms Extracting data.sig Writing data to stdout WARNING: not checking signature hi Removing data.sig $ ./cms.sh -i data.cms UTCTIME:May 15 00:12:48 2025 GMT issuer: C=US, ST=PA, O=Demo CA, CN=Demo CA subject: C=US, ST=PA, O=Testing, CN=Test Cert $ ./cms.sh -CAfile SectigoCA.pem -signer RPcert.pem -inkey RPkey.pem -s data Signing data -> data.sig Enter pass phrase for RPkey.pem: Checking data.sig Verifying signature CMS Verification successful Writing cms to data.cms Removing data.sig $ ./cms.sh -CAfile SectigoCA.pem -v data.cms Extracting data.sig Verifying signature CMS Verification successful Removing data.sig $ ./cms.sh -i data.cms UTCTIME:May 15 00:13:57 2025 GMT issuer: C=GB, O=Sectigo Limited, CN=Sectigo Public Email Protection CA R36 subject: emailAddress=perry@misty.com $ tar cvhzf pem.tar.gz *.pem RPcert.pem RPkey.pem SectigoCA.pem testcert.pem testkey.pem $ ./cms.sh -s pem.tar.gz Signing pem.tar.gz -> pem.tar.gz.sig Checking pem.tar.gz.sig Verifying signature CMS Verification successful Writing cms to pem.tar.gz.cms Removing pem.tar.gz.sig $ ./cms.sh -v pem.tar.gz.cms - | tar tvzf - Extracting pem.tar.gz.sig Verifying signature and writing data to stdout CMS Verification successful Removing pem.tar.gz.sig -rw-r--r-- perry/perry 1989 2025-05-11 11:15 RPcert.pem -rw------- perry/perry 1854 2025-05-11 11:10 RPkey.pem -rw-r--r-- perry/perry 7238 2025-05-11 11:18 SectigoCA.pem -rw-r--r-- perry/perry 4276 2025-05-13 05:33 testcert.pem -rw-r--r-- perry/perry 1704 2025-05-13 05:34 testkey.pem $ ./cms.sh -I pem.tar.gz.cms > pem.I.txt $