{"id":6953,"date":"2011-10-15T11:58:13","date_gmt":"2011-10-15T15:58:13","guid":{"rendered":"http:\/\/scruss.com\/blog\/?p=6953"},"modified":"2011-10-15T11:58:13","modified_gmt":"2011-10-15T15:58:13","slug":"secure-digital-qsl-cards-part-2-shell-script","status":"publish","type":"post","link":"https:\/\/scruss.com\/blog\/2011\/10\/15\/secure-digital-qsl-cards-part-2-shell-script\/","title":{"rendered":"Secure digital QSL cards, part 2: shell script"},"content":{"rendered":"<p>Following on from <a href=\"..\/..\/blog\/2011\/10\/09\/creating-secure-digital-qsl-cards-with-your-lotw-certificate\/\">Creating secure digital QSL cards with your LoTW certificate<\/a>, here&#8217;s a Bash script to generate encrypted signed PDF QSLs. You will need to edit the certificate file name, the QSL blank file name, your call sign, your LoTW password and the PDF encryption password. After doing so, please keep the script safe, as whoever has your LoTW password can pretend to be you.<\/p>\n<p>The only checks that this script doesn&#8217;t do (and probably should) are if you have pdftk and PortableSigner executables in your path. PortableSigner is rather weird the way it runs; you need to specify full paths for all files, or it dies.<\/p>\n<p>The script is called like this:<\/p>\n<pre>mkdqsl.sh callsign date utc mhz mode report<\/pre>\n<p>for example:<\/p>\n<pre>mkdqsl.sh VE3KPK 2011-10-02 2341 7.03581 CW 499<\/pre>\n<p>Code below the fold.<\/p>\n<p><!--more--><\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n#!\/bin\/bash\r\n# mkdqsl.sh - make a secure digital QSL PDF\r\n# scruss \/ VA3PID - 2011-10-14\r\n# $Id: mkdqsl.sh,v 1.2 2011\/10\/15 15:37:13 scruss Exp $\r\n\r\n##################\r\n# Things to edit #\r\n##################\r\n\r\n# Your Logbook of the World certificate file name\r\n#   (or any valid X.509 P12 or PFX file)\r\n# Needs to be in the current directory\r\nLOTW_CERTIFICATE=&quot;VA3PID.p12&quot;\r\n\r\n# Your blank QSL PDF form with the following form fields defined:\r\n#   callsign  date  utc  mhz  mode  report\r\n# Needs to be in the current directory\r\nQSL_BLANK=&quot;VA3PID-QSL-blank3.pdf&quot;\r\n\r\n# Your call sign - used only for output file naming\r\nMY_CALL=&quot;VA3PID&quot;\r\n\r\n# Super-secret passwords\r\n# Keep them safe; whoever has access can pretend to be you\r\nLOTW_PASSWORD=&quot;NotYourPassword&quot;\r\nOWNER_PASSWORD=&quot;AlsoNotYourPassword&quot;\r\n\r\n#############################\r\n# Nothing to edit past here #\r\n#############################\r\n\r\n# Check args, give usage otherwise\r\n# takes six arguments: callsign, date, utc, mhz, mode, and report\r\nif &#x5B; $# -lt 6 ]\r\nthen\r\n    echo &quot;Usage: &quot; $0 &quot; callsign date utc mhz mode report&quot;\r\n    exit\r\nfi\r\n\r\nCALLSIGN=$1 \r\nDATE=$2 \r\nUTC=$3 \r\nMHZ=$4 \r\nMODE=$5 \r\nREPORT=$6\r\n\r\n# temp files based on run variables\r\nTEMP_FDF=&quot;temp_${CALLSIGN}_$$.fdf&quot;\r\nTEMP_FILLED_PDF=&quot;temp_${CALLSIGN}_$$.pdf&quot;\r\nTEMP_ENCRYPTED_PDF=&quot;tempE_${CALLSIGN}_$$.pdf&quot;\r\nOUTFILE=&quot;${MY_CALL}-qsl-${CALLSIGN}-${DATE}-${UTC}.pdf&quot;\r\n\r\n# check existence of required input files\r\nif &#x5B; ! -f $LOTW_CERTIFICATE ]\r\nthen\r\n    echo &quot;Signing certificate &quot; $LOTW_CERTIFICATE &quot; not found.&quot;\r\n    exit\r\nfi\r\n\r\nif &#x5B; ! -f $QSL_BLANK ]\r\nthen\r\n    echo &quot;QSL blank &quot; $QSL_BLANK &quot; not found.&quot;\r\n    exit\r\nfi\r\n\r\n# make FDF file from form data\r\ncat &gt; ${TEMP_FDF} &lt;&lt;ZORKLE\r\n%FDF-1.2\r\n\r\n1 0 obj\r\n&lt;&lt;\r\n\/FDF &lt;&lt; \/Fields 2 0 R&gt;&gt;\r\n&gt;&gt;\r\nendobj\r\n2 0 obj\r\n&#x5B;&lt;&lt; \/T (callsign) \/V (${CALLSIGN}) &gt;&gt;\r\n&lt;&lt; \/T (date) \/V (${DATE}) &gt;&gt;\r\n&lt;&lt; \/T (utc) \/V (${UTC}) &gt;&gt;\r\n&lt;&lt; \/T (mhz) \/V (${MHZ}) &gt;&gt;\r\n&lt;&lt; \/T (mode) \/V (${MODE}) &gt;&gt;\r\n&lt;&lt; \/T (report) \/V (${REPORT}) &gt;&gt;\r\n]\r\nendobj\r\ntrailer\r\n&lt;&lt;\r\n\/Root 1 0 R\r\n\r\n&gt;&gt;\r\n%%EOF\r\nZORKLE\r\n\r\n# create first stage filled-in form\r\npdftk $QSL_BLANK fill_form $TEMP_FDF output $TEMP_FILLED_PDF flatten\r\n\r\n# create encrypted document using $OWNER_PASSWORD\r\npdftk $TEMP_FILLED_PDF output $TEMP_ENCRYPTED_PDF owner_pw $OWNER_PASSWORD  allow AllFeatures\r\n\r\n# sign encrypted PDF\r\n# note that PortableSigner is picky about file locations\r\nPortableSigner -n -o &quot;${PWD}\/$OUTFILE&quot;  -ownerpwd &quot;$OWNER_PASSWORD&quot; -p &quot;$LOTW_PASSWORD&quot;  -s &quot;${PWD}\/$LOTW_CERTIFICATE&quot;  -t &quot;${PWD}\/$TEMP_ENCRYPTED_PDF&quot;\r\n\r\necho Wrote to $OUTFILE\r\n\r\n# the end; clean up\r\nrm -f $TEMP_FDF $TEMP_FILLED_PDF $TEMP_ENCRYPTED_PDF\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Following on from Creating secure digital QSL cards with your LoTW certificate, here&#8217;s a Bash script to generate encrypted signed PDF QSLs. You will need to edit the certificate file name, the QSL blank file name, your call sign, your LoTW password and the PDF encryption password. After doing so, please keep the script safe, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[2290,7],"tags":[1477,2392,765,2394,1372],"class_list":["post-6953","post","type-post","status-publish","format-standard","hentry","category-amateur-radio","category-computers-suck","tag-bash","tag-lotw","tag-pdf","tag-qsl","tag-shell"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pQNZZ-1O9","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/6953","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/comments?post=6953"}],"version-history":[{"count":3,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/6953\/revisions"}],"predecessor-version":[{"id":6956,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/6953\/revisions\/6956"}],"wp:attachment":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/media?parent=6953"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/categories?post=6953"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/tags?post=6953"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}