Browse Source

Created simple CLI to cryptographic signing

master
Macoy Madson 1 year ago
parent
commit
6979c89d7d
  1. 5
      .gitignore
  2. 12
      src/Cryptography.cake
  3. 235
      src/CryptographyCLI.cake
  4. 17
      test/BuildStandaloneExecutables.sh

5
.gitignore

@ -75,4 +75,7 @@ test/TestSerialize.cakedata
test/TestDynamicArraySerialize.cakedata
test/TestDictionarySerialize.cakedata
test/TestDictionarySerializeStrDict.cakedata
test/MultiReads.cakedata
test/MultiReads.cakedata
test/cryptography-cli*
PublicAndSecretKeys.bin

12
src/Cryptography.cake

@ -1,14 +1,16 @@
;; Cryptography.cake: Cryptographic functions for signing, encryption, etc.
(add-c-search-directory-module "cakelisp_cache/LibSodiumInstallDir/include")
(c-import "sodium.h")
(add-cakelisp-search-directory "Dependencies/cakelisp/runtime")
(import "CHelpers.cake" "BuildTools.cake" "Dependencies.cake")
(export-and-evaluate
(add-c-search-directory-module "cakelisp_cache/LibSodiumInstallDir/include")
(c-import "sodium.h"))
(defun cryptography-initialize (&return bool)
(return (>= (sodium_init) 0)))
(comptime-cond
('auto-test
(add-cakelisp-search-directory "Dependencies/cakelisp/runtime")
(import "CHelpers.cake")
(c-import "<stdio.h>")
(defun test--cryptography (&return int)
(unless (cryptography-initialize)
@ -49,7 +51,7 @@
(defun-comptime build-libsodium (manager (& ModuleManager) module (* Module) &return bool)
(var libsodium-archive (* (const char))
(comptime-cond ('Windows "Dependencies/libsodium/onig_s.lib")
(comptime-cond ('Windows "Dependencies/libsodium/libsodium.lib")
('Unix "cakelisp_cache/LibSodiumInstallDir/lib/libsodium.a")))
;; Already built?
;; We could enhance this by checking for modifications, but that's pretty rare

235
src/CryptographyCLI.cake

@ -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")

17
test/BuildStandaloneExecutables.sh

@ -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…
Cancel
Save