4 changed files with 263 additions and 6 deletions
@ -0,0 +1,235 @@ |
|||
(add-cakelisp-search-directory "Dependencies/cakelisp/runtime") |
|||
(import "CHelpers.cake" "FileUtilities.cake" |
|||
"Cryptography.cake") |
|||
|
|||
(c-import "<string.h>") |
|||
|
|||
(var s-keys-filename (* (const char)) "PublicAndSecretKeys.bin") |
|||
|
|||
;; |
|||
;; Command registration |
|||
;; |
|||
|
|||
(defmacro defcommand (command-name symbol arguments array &rest body any) |
|||
|
|||
(get-or-create-comptime-var command-table (<> (in std vector) (* (const Token)))) |
|||
(call-on-ptr push_back command-table command-name) |
|||
|
|||
(tokenize-push output |
|||
(defun (token-splice command-name) (token-splice arguments) |
|||
(token-splice-rest body tokens))) |
|||
(return true)) |
|||
|
|||
(defun-comptime create-command-lookup-table (environment (& EvaluatorEnvironment) &return bool) |
|||
(get-or-create-comptime-var command-table-already-created bool false) |
|||
(when (deref command-table-already-created) |
|||
(return true)) |
|||
(set (deref command-table-already-created) true) |
|||
|
|||
(get-or-create-comptime-var command-table (<> (in std vector) (* (const Token)))) |
|||
|
|||
(var command-data (* (<> std::vector Token)) (new (<> std::vector Token))) |
|||
(call-on push_back (field environment comptimeTokens) command-data) |
|||
|
|||
(for-in command-name (* (const Token)) (deref command-table) |
|||
(var command-name-string Token (deref command-name)) |
|||
(set (field command-name-string type) TokenType_String) |
|||
|
|||
(tokenize-push (deref command-data) |
|||
(array (token-splice-addr command-name-string) |
|||
(token-splice command-name)))) |
|||
|
|||
(var command-table-tokens (* (<> std::vector Token)) (new (<> std::vector Token))) |
|||
(call-on push_back (field environment comptimeTokens) command-table-tokens) |
|||
(tokenize-push (deref command-table-tokens) |
|||
(var command-table ([] command-metadata) |
|||
(array (token-splice-array (deref command-data))))) |
|||
|
|||
(return (ClearAndEvaluateAtSplicePoint environment "command-lookup-table" command-table-tokens))) |
|||
|
|||
(add-compile-time-hook post-references-resolved |
|||
create-command-lookup-table) |
|||
|
|||
(def-function-signature command-function (num-arguments int arguments ([] (* (const char))) &return int)) |
|||
|
|||
(defstruct-local command-metadata |
|||
name (* (const char)) |
|||
command command-function) |
|||
|
|||
(splice-point command-lookup-table) |
|||
|
|||
;; |
|||
;; Commands |
|||
;; |
|||
|
|||
(defun-local print-keys (public-key (* (unsigned char)) |
|||
secret-key (* (unsigned char))) |
|||
(fprintf stderr "Public key:\n") |
|||
(each-in-range crypto_sign_PUBLICKEYBYTES i |
|||
(fprintf stderr "%02x " (at i public-key))) |
|||
(fprintf stderr "\nSecret key:\n") |
|||
(each-in-range crypto_sign_SECRETKEYBYTES i |
|||
(fprintf stderr "%02x " (at i secret-key))) |
|||
(fprintf stderr "\n")) |
|||
|
|||
(defcommand generate-keys (num-arguments int arguments ([] (* (const char))) &return int) |
|||
(fprintf stderr "Generating public and secret keys\n") |
|||
(var public-key ([] crypto_sign_PUBLICKEYBYTES (unsigned char))) |
|||
(var secret-key ([] crypto_sign_SECRETKEYBYTES (unsigned char))) |
|||
(crypto_sign_keypair public-key secret-key) |
|||
(print-keys public-key secret-key) |
|||
|
|||
(var out-file (* FILE) (fopen s-keys-filename "wb")) |
|||
(unless out-file |
|||
(fprintf stderr "Failed to open key file '%s'.\n" s-keys-filename) |
|||
(return 1)) |
|||
(fwrite public-key (sizeof public-key) 1 out-file) |
|||
(fwrite secret-key (sizeof secret-key) 1 out-file) |
|||
(fclose out-file) |
|||
(fprintf stderr "Keys saved to %s\n" s-keys-filename) |
|||
(return 0)) |
|||
|
|||
(defun-local load-keys-from-file (filename (* (const char)) |
|||
public-key-out (* (unsigned char)) |
|||
secret-key-out (* (unsigned char)) |
|||
&return bool) |
|||
(var in-file (* FILE) (fopen filename "rb")) |
|||
(unless in-file |
|||
(fprintf stderr "Failed to open key file '%s'. You can generate new keys with the generate-keys command.\n" |
|||
s-keys-filename) |
|||
(return false)) |
|||
(fread public-key-out crypto_sign_PUBLICKEYBYTES 1 in-file) |
|||
(fread secret-key-out crypto_sign_SECRETKEYBYTES 1 in-file) |
|||
(fclose in-file) |
|||
(return true)) |
|||
|
|||
(defcommand list-keys (num-arguments int arguments ([] (* (const char))) &return int) |
|||
(var public-key ([] crypto_sign_PUBLICKEYBYTES (unsigned char))) |
|||
(var secret-key ([] crypto_sign_SECRETKEYBYTES (unsigned char))) |
|||
(unless (load-keys-from-file s-keys-filename public-key secret-key) |
|||
(return 1)) |
|||
(print-keys public-key secret-key) |
|||
(return 0)) |
|||
|
|||
(defcommand create-signed-file (num-arguments int arguments ([] (* (const char))) &return int) |
|||
(unless (= 2 num-arguments) |
|||
(fprintf stderr "Command create-signed-file expects two arguments: [input file] [output file]\n") |
|||
(return 1)) |
|||
|
|||
(var input-filename (* (const char)) (at 0 arguments)) |
|||
(var output-filename (* (const char)) (at 1 arguments)) |
|||
|
|||
(var public-key ([] crypto_sign_PUBLICKEYBYTES (unsigned char))) |
|||
(var secret-key ([] crypto_sign_SECRETKEYBYTES (unsigned char))) |
|||
(unless (load-keys-from-file s-keys-filename public-key secret-key) |
|||
(fprintf stderr "Generate keys with generate-keys first before trying to create a signed file.\n") |
|||
(return 1)) |
|||
(fprintf stderr "Signing file %s with the following keys:\n" input-filename) |
|||
(print-keys public-key secret-key) |
|||
|
|||
(var input-file (* FILE) (fopen input-filename "rb")) |
|||
(unless input-file |
|||
(fprintf stderr "error: Failed to open input file %s.\n" input-filename) |
|||
(return 1)) |
|||
(var input-file-size size_t) |
|||
(var-cast-to file-contents (* (unsigned char)) |
|||
(read-file-into-memory-ex input-file 0 (addr input-file-size))) |
|||
(fclose input-file) |
|||
|
|||
(var-cast-to signed-contents (* (unsigned char)) (malloc (+ input-file-size crypto_sign_BYTES))) |
|||
(var signed-contents-length (unsigned (long long))) |
|||
(crypto_sign signed-contents (addr signed-contents-length) |
|||
file-contents input-file-size secret-key) |
|||
|
|||
(var output-file (* FILE) (fopen output-filename "wb")) |
|||
(unless output-file |
|||
(fprintf stderr "error: Failed to open output file %s.\n" output-filename) |
|||
(free signed-contents) |
|||
(free file-contents) |
|||
(return 1)) |
|||
(fwrite signed-contents signed-contents-length 1 output-file) |
|||
(fclose output-file) |
|||
|
|||
(fprintf stderr "The file %s has been signed and written to %s.\n" |
|||
input-filename output-filename) |
|||
|
|||
(free signed-contents) |
|||
(free file-contents) |
|||
(return 0)) |
|||
|
|||
(defcommand verify-signed-file (num-arguments int arguments ([] (* (const char))) &return int) |
|||
(unless (= 1 num-arguments) |
|||
(fprintf stderr "Command create-signed-file expects one argument: [input file]\n") |
|||
(return 1)) |
|||
|
|||
(var input-filename (* (const char)) (at 0 arguments)) |
|||
|
|||
(var public-key ([] crypto_sign_PUBLICKEYBYTES (unsigned char))) |
|||
(var secret-key ([] crypto_sign_SECRETKEYBYTES (unsigned char))) |
|||
(unless (load-keys-from-file s-keys-filename public-key secret-key) |
|||
(fprintf stderr "There were no keys found to check against.\n") |
|||
(return 1)) |
|||
(fprintf stderr "Checking signed file %s against the following keys:\n" input-filename) |
|||
(print-keys public-key secret-key) |
|||
|
|||
(var input-file (* FILE) (fopen input-filename "rb")) |
|||
(unless input-file |
|||
(fprintf stderr "error: Failed to open input file %s.\n" input-filename) |
|||
(return 1)) |
|||
(var input-file-size size_t) |
|||
(var-cast-to file-contents (* (unsigned char)) |
|||
(read-file-into-memory-ex input-file 0 (addr input-file-size))) |
|||
(fclose input-file) |
|||
|
|||
;; This is a little too big but we don't care about those extra few signature bytes |
|||
(var-cast-to unsigned-message (* (unsigned char)) (malloc input-file-size)) |
|||
(var unsigned-message-length (unsigned (long long))) |
|||
(unless (= 0 (crypto_sign_open unsigned-message (addr unsigned-message-length) |
|||
file-contents input-file-size public-key)) |
|||
(fprintf stderr "\n[FAIL] This file's signature does NOT match the key.\n") |
|||
(free unsigned-message) |
|||
(free file-contents) |
|||
(return 1)) |
|||
|
|||
(fprintf stderr "\n[PASS] This file's signature matches the key.\n") |
|||
|
|||
(free unsigned-message) |
|||
(free file-contents) |
|||
(return 0)) |
|||
|
|||
;; |
|||
;; CLI |
|||
;; |
|||
|
|||
(defun-local print-help () |
|||
(fprintf stderr #"#Usage: |
|||
cryptography-cli [command] [arguments] |
|||
|
|||
Available commands: |
|||
#"#) |
|||
(each-in-array command-table i |
|||
(fprintf stderr " %s\n" |
|||
(field (at i command-table) name)))) |
|||
|
|||
(defun main (num-arguments int arguments ([] (* (const char))) &return int) |
|||
(unless (> num-arguments 1) |
|||
(fprintf stderr "Expected command.\n") |
|||
(print-help) |
|||
(return 1)) |
|||
|
|||
(var result int 1) |
|||
(var found bool false) |
|||
(each-in-array command-table i |
|||
(when (= 0 (strcmp (field (at i command-table) name) (at 1 arguments))) |
|||
(set result (call (field (at i command-table) command) |
|||
;; Trim process name and command name |
|||
(- num-arguments 2) (+ arguments 2))) |
|||
(set found true) |
|||
(break))) |
|||
(unless found |
|||
(fprintf stderr "The command '%s' was not recognized.\n" (at 1 arguments)) |
|||
(print-help) |
|||
(return 1)) |
|||
(return result)) |
|||
|
|||
(set-cakelisp-option executable-output "cryptography-cli") |
@ -0,0 +1,17 @@ |
|||
#!/bin/sh |
|||
|
|||
CAKELISP_DIR=Dependencies/cakelisp |
|||
|
|||
# Link Cakelisp if necessary |
|||
[ ! -d "$CAKELISP_DIR" ] && git clone git@github.com:makuto/cakelisp.git Dependencies/cakelisp |
|||
|
|||
# Build Cakelisp itself |
|||
echo "\n\nCakelisp\n\n" |
|||
cd $CAKELISP_DIR |
|||
./Build.sh || exit $? |
|||
|
|||
cd ../.. |
|||
|
|||
CAKELISP=./Dependencies/cakelisp/bin/cakelisp |
|||
|
|||
$CAKELISP src/Config_Linux.cake ../src/CryptographyCLI.cake --verbose-processes || exit $? |
Loading…
Reference in new issue