diff --git a/.gitignore b/.gitignore index f290326..a0b785e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/*.html /bin /deps/**/* /obj diff --git a/README.md b/README.md new file mode 100644 index 0000000..5e0faf8 --- /dev/null +++ b/README.md @@ -0,0 +1,130 @@ +--- +title: "![CodeSign](etc/img/Logo.png)" +--- + + +Introduction +============ + +**CodeSign** is a simple file signing and verification toolkit, based on cryptographic routines from the Libcrypto (OpenSSL) library. + +At this time, CodeSign employs the RSA signature algorithm with 15360-Bit keys and the SHA-512 hash function. + +This software was created by LoRd_MuldeR [<MuldeR2@GMX.de>](mailto:MuldeR2@GMX.de). Please see for additional information. + + +Synopsis +======== + +The CodeSign suite is composed of the following tools: + +Key Generator +------------- + +The **key generator** tool is used to generate a new key-pair. It creates the *public key* and the *private key* file. The private key will be protected by the specified *password*. + +``` +Usage: + codesign_keygen.exe +``` + +File Signer +----------- + +The **file signer** tool is used to create a new signature. It creates the *signature* file for the specified *input* (original) file, using the existing *private key* protected by *password*. + +``` +Usage: + codesign_sign.exe +``` + +File Verifier +------------- + +The **file verifier** tool is used to check whether the specified *signature* file is valid *and* matches the given (possibly tampered) *input* file, using the specified *public key*. + +``` +Usage: + codesign_verify.exe +``` + +There is an alternative variant of the *file verifier* tool that uses an "embedded" public key (from the file's resources) and therefore does ***not*** need a separate *public key* file. + +``` +Usage: + codesign_verifz.exe +``` + + +Embedding the Public Key +======================== + +In order to use the **file verifier** tool with an *embedded* public key (`codesign_verifz.exe`), the *public key* must be added to the file's resource section first: + +* It is recommended to use the [Resource Hacker™](http://www.angusj.com/resourcehacker/) utility for adding resources to the executable file. Use command *"Action"* → *"Add Image or Other Binary Resource"*. + +* The *public* RSA key, in OpenSSL PEM format, shall be embedded as a resource of type `RT_RCDATA` with the name **`RSA_PUBLIC_KEY`**. + +* The SHA-512 digest of the *public* RSA key, in "raw" (binary) format, shall be embedded as a resource of type `RT_RCDATA` with the name **`CHECKSUM_SHA512`**. + + OpenSSL command to generate the required SHA-512 digest: + ``` + openssl.exe dgst -sha512 -binary -out signkey.pub.sha512 signkey.pub + ``` + + +Quick Start Guide +================= + +1. First of all, generate your RSA key-pair, if not already done: + + ``` + codesign_keygen.exe your-password-here signkey.pub signkey.key + ``` + + **Note:** This step is required only *once*. The same key-pair can be used to sign *many* files. Keep the *private* key (and the password) confidential! + +2. Sign the file to be distributed, using the previously generated private key: + + ``` + codesign_sign.exe your-password-here signkey.key my-installer.exe my-installer.exe.sig + ``` + + **Note:** The generated signature file shall be distributed alongside with the signed file. The *private key* ***must not*** be distributed under any circumstances! + +3. Verify the retrieved (e.g. downloaded) file: + + ``` + codesign_verify.exe signkey.pub my-installer.exe my-installer.exe.sig + ``` + + **Note:** This step is used to verify that the retrieved file was signed by the original author and that it was ***not*** tampered with since it was signed. + + +Passing the Password +==================== + +Passing the password directly on the command-line is **not** recommended for security reasons! + +The password can be passed to the CodeSign tools via pipe instead. Setting the password to `-` will cause the program to read the password from the standard input stream: + +* For example, the password can be read from a password file: + + ``` + codesign_keygen.exe - signkey.pub signkey.key < password.txt + ``` + +* Alternatively, the **`passentry.exe`** helper application can be used to display a simple passwort entry dialog to the user: + + ``` + passentry.exe | codesign_keygen.exe - signkey.pub signkey.key + ``` + + +License +======= + +This work has been released under the **CC0 1.0 Universal** license. + +For details, please refer to: + diff --git a/deps/build-openssl-linux.sh b/deps/build-openssl-linux.sh old mode 100644 new mode 100755 diff --git a/deps/build-openssl-mingw.sh b/deps/build-openssl-mingw.sh old mode 100644 new mode 100755 diff --git a/etc/img/Logo.png b/etc/img/Logo.png new file mode 100644 index 0000000..22b4085 Binary files /dev/null and b/etc/img/Logo.png differ diff --git a/etc/style/gh-pandoc.min.css b/etc/style/gh-pandoc.min.css new file mode 100644 index 0000000..0f22b9c --- /dev/null +++ b/etc/style/gh-pandoc.min.css @@ -0,0 +1 @@ +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.caption{margin-bottom:5em}*{box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:10pt;line-height:1.6;margin:auto;max-width:1184px;min-width:360px;padding:2rem;word-wrap:break-word}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25;margin-bottom:16px;margin-top:24px}h1{padding-bottom:.3em;font-size:2em;border-bottom:1px solid #eee}h2{padding-bottom:.3em;font-size:1.5em;border-bottom:1px solid #eee}h3{font-size:1.25em}h4{font-size:1.12em}h5{font-size:.875em}h6{font-size:.85em;color:#777}h1 tt,h1 code,h2 tt,h2 code,h3 tt,h3 code,h4 tt,h4 code,h5 tt,h5 code,h6 tt,h6 code{font-size:inherit}body>h2:first-child{margin-top:0;padding-top:0}body>h1:first-child{margin-top:0;padding-top:0}body>h1:first-child+h2{margin-top:0;padding-top:0}body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child{margin-top:0;padding-top:0}a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6{margin-top:0;padding-top:0}a{color:#4078c0;text-decoration:none}a:active,a:hover{outline:0;text-decoration:underline}sup,sub,a.footnote{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}ol,ul{margin-bottom:16px;margin-top:0;padding-left:2em}p,blockquote,table,pre{margin:15px 0}ul,ol{padding-left:2em}ul.no-list,ol.no-list{padding:0;list-style-type:none}ul ul,ul ol,ol ol,ol ul{margin-top:0;margin-bottom:0}li>p{margin-top:16px}li+li{margin-top:.25em}ol li ul:first-of-type{margin-top:0}hr{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;border:0 none;color:#ccc;height:4px;margin:16px 0;padding:0}h1+p,h2+p,h3+p,h4+p,h5+p,h6+p,ul li>:first-child,ol li>:first-child{margin-top:0}dl{padding:0}dl dt{font-size:1em;font-weight:bold;font-style:italic;padding:0;margin:15px 0 5px}dl dt:first-child{padding:0}dl dt>:first-child{margin-top:0}dl dt>:last-child{margin-bottom:0}dl dd{margin:0 0 15px;padding:0 15px}dl dd>:first-child{margin-top:0}dl dd>:last-child{margin-bottom:0}blockquote{border-left:4px solid #DDD;padding:0 15px;color:#777}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}table{border-collapse:collapse;border-spacing:0;font-size:100%;font:inherit}table th{font-weight:bold;border:1px solid #ccc;padding:6px 13px}table td{border:1px solid #ccc;padding:6px 13px}table td>p:first-child{margin-top:0}table td>p:last-child{margin-bottom:0}table tr{border-top:1px solid #ccc;background-color:#fff}table tr:nth-child(2n){background-color:#f8f8f8}img{max-width:100%}code,tt{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:10pt;background-color:rgba(0,0,0,0.04);border-radius:3px}pre>code{margin:0;padding:0;white-space:pre;border:0;background:transparent}pre{padding:16px;margin-top:0;margin-bottom:0;background-color:#f8f8f8;font-size:10pt;line-height:19px;overflow:auto;border-radius:3px}pre code,pre tt{background-color:transparent;border:0}code::before,code::after,tt::before,tt::after{letter-spacing:-0.2em;content:"\00a0"}pre code::before,pre code::after,pre tt::before,pre tt::after{content:normal}code>span.kw{color:#a71d5d;font-weight:normal}code>span.dt{color:inherit}code>span.dv{color:#0086b3}code>span.bn{color:#0086b3}code>span.fl{color:#0086b3}code>span.ch{color:#183691}code>span.st{color:#183691}code>span.co{color:#969896;font-style:normal}code>span.ot{color:#a71d5d}code>span.al{color:red}code>span.fu{color:#795da3}code>span.er{color:red;font-weight:bold}code>span.wa{color:#969896;font-weight:bold;font-style:italic}code>span.cn{color:#800}code>span.sc{color:#183691}code>span.vs{color:#183691}code>span.ss{color:#b68}code>span.va{color:#19177c}code>span.cf{color:#a71d5d;font-weight:normal}code>span.op{color:#666}code>span.pp{color:#bc7a00}code>span.at{color:#0086b3}code>span.do{color:#ba2121;font-style:italic}code>span.an{color:#969896;font-weight:bold;font-style:italic}code>span.cv{color:#969896;font-weight:bold;font-style:italic}code>span.in{color:#969896;font-weight:bold;font-style:italic}@media print{body{background:#fff}img,pre,blockquote,table,figure{page-break-inside:avoid}body{background:#fff;border:0}code{background-color:#fff;color:#333 !important;padding:0 .2em;border:1px solid #dedede}pre{background:#fff}pre code{background-color:white !important;overflow:visible}}@media screen{::selection{background:rgba(157,193,200,0.5)}h1::selection{background-color:rgba(45,156,208,0.3)}h2::selection{background-color:rgba(90,182,224,0.3)}h3::selection,h4::selection,h5::selection,h6::selection,li::selection,ol::selection{background-color:rgba(133,201,232,0.3)}code::selection{background-color:rgba(0,0,0,0.7);color:#eee}code span::selection{background-color:rgba(0,0,0,0.7) !important;color:#eee !important}a::selection{background-color:rgba(255,230,102,0.2)}.inverted a::selection{background-color:rgba(255,230,102,0.6)}td::selection,th::selection,caption::selection{background-color:rgba(180,237,95,0.5)}} \ No newline at end of file diff --git a/mk-docs.cmd b/mk-docs.cmd new file mode 100644 index 0000000..332353b --- /dev/null +++ b/mk-docs.cmd @@ -0,0 +1,12 @@ +@echo off + +if "%PANDODC_PATH%"=="" ( + set "PANDODC_PATH=c:\Program Files (x86)\Pandoc" +) + +echo on +"%PANDODC_PATH%\pandoc.exe" -o "%~dp0\README.html" --self-contained --toc --toc-depth=3 --css etc\style\gh-pandoc.min.css "%~dp0\README.md" +@echo off + +echo. +pause diff --git a/src/codesign_keygen.c b/src/codesign_keygen.c index f90aaaf..5c41113 100644 --- a/src/codesign_keygen.c +++ b/src/codesign_keygen.c @@ -12,7 +12,7 @@ #include #define RSA_EXPONENT 0x10001 -#define RSA_KEY_SIZE 8192 +#define RSA_KEY_SIZE 15360 int MAIN(int argc, CHAR_T *argv[]) { @@ -117,6 +117,12 @@ int MAIN(int argc, CHAR_T *argv[]) goto clean_up; } + if (RSA_size(rsa) != RSAKEY_MINLEN) + { + fputs("Failed!\n\nError: RSA key size differes from what was expected!\n\n", stderr); + goto clean_up; + } + fputs("Completed.\n\n", stderr); fflush(stderr); diff --git a/src/codesign_sign.c b/src/codesign_sign.c index 86f71ec..4127e8d 100644 --- a/src/codesign_sign.c +++ b/src/codesign_sign.c @@ -103,6 +103,12 @@ int MAIN(int argc, CHAR_T *argv[]) goto clean_up; } + if (RSA_size(rsa) < RSAKEY_MINLEN) + { + fputs("Error: RSA key size is smaller than the required minimum!\n\n", stderr); + goto clean_up; + } + /*-------------------------------------------------------*/ /* Get current time */ /*-------------------------------------------------------*/ diff --git a/src/codesign_verify.c b/src/codesign_verify.c index 621e1c7..d84582c 100644 --- a/src/codesign_verify.c +++ b/src/codesign_verify.c @@ -50,7 +50,7 @@ int MAIN(int argc, CHAR_T *argv[]) { print_license(); fputs("Usage:\n", stderr); - fputs(" codesign_verify.exe \n\n", stderr); + fputs(" codesign_verifz.exe \n\n", stderr); goto clean_up; } @@ -128,6 +128,12 @@ int MAIN(int argc, CHAR_T *argv[]) #endif + if (RSA_size(rsa) < RSAKEY_MINLEN) + { + fputs("Error: RSA key size is smaller than the required minimum!\n\n", stderr); + goto clean_up; + } + /*-------------------------------------------------------*/ /* Open input files */ /*-------------------------------------------------------*/ diff --git a/src/common.h b/src/common.h index 0613c6c..4b939c9 100644 --- a/src/common.h +++ b/src/common.h @@ -10,6 +10,7 @@ #include #define PASSWD_MINLEN 8 +#define RSAKEY_MINLEN 1920 void print_logo(const char *const app_name); void print_license(void);