How to encrypt E-Mails with S/MIME

1

I am considering to encrypt some of my mails using S/MIME v3.1, since my devices should support it.

Now I wonder if there is a (command line) tool that could do that for me? I tried to google it, but I did not found something promissing.

user60589

Posted 2016-08-29T16:58:50.300

Reputation: 113

Most people use an email client with an add-on if they are going to send and recieve encrypted emails, this allows them to read the encrypted emails within the preview pane, that they might receive. – Ramhound – 2016-08-29T17:02:22.440

Answers

2

Yes, OpenSSL (openssl smime or openssl cms) can do that:

man smime:

DESCRIPTION

The smime command handles S/MIME mail. It can encrypt, decrypt, sign and verify S/MIME messages.

man cms:

DESCRIPTION

The cms command handles S/MIME v3.1 mail. It can encrypt, decrypt, sign and verify, compress and uncompress S/MIME messages.

Law29

Posted 2016-08-29T16:58:50.300

Reputation: 406

But the man says it chokes on some messages and doesn't like v3. – user60589 – 2016-08-29T17:40:45.267

@user60589 - Sounds like you have a different problem. You asked if it was possible, it is indeed possible, OpenSSL was only a suggestion out of many (us listing every single possible suggestion won't happen). – Ramhound – 2016-08-29T17:52:41.283

@user60589 It appears GNUtls can be used too for S/MIME, but I don't think it's command-line, it seems rather integrated: http://www.claws-mail.org/faq/index.php/S/MIME_howto

– Law29 – 2016-08-29T18:19:52.027

Maybe just maybe one could use mutt in command-line mode, but I've never tried. I have used OpenSSL, though. – Law29 – 2016-08-29T18:22:13.160

2v3 might be openssl cms. – user1686 – 2016-08-29T19:24:32.953

@grawity Well that goes to show that you should reread all the manpages one in a while! Pity that it's a lot of reading... Editing my answer. – Law29 – 2016-08-29T20:40:38.140

0

Here's a script to encrypt pre-existing emails, but you do need access to them as files in MH format. As a bonus, it uses GPG instead of S/MIME if the second argument is a GPG key ID. If the second argument is a path to a file ending in .pem, then the script assumes that the second argument is a pem-format X509 certificate for which the corresponding private key will eventually be used to decrypt the email.

#!/usr/bin/awk -f

## Encrypt emails in MH format.

## 1st argument is email file to encrypt.
## 2nd argument is PGP key identifier, or for S/MIME, certificate file.

BEGIN {
        ## If second argument ends with .pem, assume that S/MIME output
        ## is required, otherwise assume PGP/MIME.
        if (ARGC == 3 && ARGV[2] ~ /\.pem$/) S = 1 ## S/MIME, not PGP

        if (S == 1) {
                Encrypt = "openssl smime -encrypt -aes256 -outform pem " ARGV[2]
                Encrypt = Encrypt "|sed '/^-----BEGIN PKCS7-----/d;"
                Encrypt = Encrypt "/^-----END PKCS7-----/d'"}
        else {
                Encrypt = "gpg2 --armor --encrypt -r " ARGV[2]
                Random = "openssl rand -base64 30"}

        for (i=2;i < ARGC;i++) delete ARGV[i]        ## Just one input file.
}

{
        sub(/\r$/,"",$0)}

##==========================================================

BlankCount > 0 {           ## Everything from the 1st blank line onwards:
        print $0 | Encrypt ## Pipe opened on 1st matching line; stays open.
        next}

##----------------------------------------------------------

$0 ~ /^[^ \t]/ {        ## Any line starting with a non-whitespace character.
        CurrentBlank = 0
        if (Started == 0) Started = 1}

##----------------------------------------------------------

$0 ~ /^[ \t]*$/ {        ## Blank line NOT at the top of the file.
        if (CurrentBlank == 0 && Started == 1) BlankCount++
        CurrentBlank = 1

        ## New Content-Type and Content-Transfer-Encoding headers to go at the
        ## end of the header-block, i.e. before the first blank line:
        if (BlankCount == 1) {
                if (S == 1) {
                        H = "Content-Type: application/pkcs7-mime;"
                        H = H " name=\"smime.p7m\"; smime-type=enveloped-data\n"
                        H = H "Content-Transfer-Encoding: base64\n"
                        H = H "Content-Disposition: attachment;"
                        H = H " filename=\"smime.p7m\"\n"
                        H = H "Content-Description: S/MIME Encrypted Message"}
                else {
                        Random | getline Boundary
                        Boundary = "Encrypt_/" Boundary

                        H = "Content-Type: multipart/encrypted;"
                        H = H "\n boundary=\"" Boundary "\";"
                        H = H "\n protocol=\"application/pgp-encrypted\"\n\n"

                        H = H "--" Boundary "\n"
                        H = H "Content-Type: application/pgp-encrypted\n\n"

                        H = H "Version: 1\n\n"

                        H = H "--" Boundary "\n"
                        H = H "Content-Type: application/octet-stream\n"}

                print H

                printf("%s\n", ContentType) | Encrypt
                printf("%s\n\n", TransferEncoding) | Encrypt}}

##----------------------------------------------------------

## Save original Content-Type and Content-Transfer-Encoding to put in
## encrypted part:

tolower($0) ~ /^content-type[ \t]*:/ {
        ContentType = $0
        sub(/[^:][^:]*: */,"",ContentType)
        ContentType = "Content-Type: " ContentType
        ContentTypeLineNumber = FNR
        next}
tolower($0) ~ /^content-transfer-encoding[ \t]*:/ {
        TransferEncoding = $0
        TransferEncoding = "Content-Transfer-Encoding: " TransferEncoding
        sub(/[^:][^:]*: */,"",TransferEncoding)
        TransferEncodingLineNumber = FNR
        next}

$0 ~ /^[ \t][ \t]*[^ \t]/ {        ## Non-blank line starting with space or tab
        CurrentBlank = 0
        if (BlankCount == 0 && FNR > 1) {
                ## This must be a continuation line in the header
                if (FNR - 1 == ContentTypeLineNumber) {
                        ContentTypeLineNumber = FNR
                        ContentType = ContentType "\n" $0
                        next}
                if (FNR - 1 == TransferEncodingLineNumber) {
                        TransferEncodingLineNumber = FNR
                        TransferEncoding = TransferEncoding "\n" $0
                        next}}}

##----------------------------------------------------------

Started == 1 {                ## All header lines other than Type and Encoding.
        print $0}

END {
        close(Encrypt)
        if (S == 1) print ""
        else printf("\n--%s--\n", Boundary)}

##----------------------------------------------------------

user162479

Posted 2016-08-29T16:58:50.300

Reputation: