supercop

Basic CLI for supercop
git clone git://git.finwo.net/app/supercop
Log | Files | Refs | README | LICENSE

commit 6e1abcffdecc6029cd9b55c4868ca6bead7017fd
parent 32031d22bc7f035cded00343c7ff5d4b4fd7b242
Author: Robin Bron <finwo@pm.me>
Date:   Wed, 15 Sep 2021 18:19:36 +0200

Basic key generation

Diffstat:
A.gitignore | 3+++
AMakefile | 48++++++++++++++++++++++++++++++++++++++++++++++++
Aencoding.md | 18++++++++++++++++++
Apatch/ed25519/00-single-file-compile.patch | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main.c | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 356 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,3 @@ +*.o +lib/ +/supercop diff --git a/Makefile b/Makefile @@ -0,0 +1,48 @@ +# Ourselves +CFLAGS?= +CFLAGS+=-O2 -mtune=native -march=native -pipe -Wall +INCLUDES?= +INCLUDES+=-Isrc +SRC:=$(wildcard src/*.c) + +# lib/argparse +INCLUDES+=-Ilib/argparse +SRC+=lib/argparse/argparse.c + +# lib/ed25519 +INCLUDES+=-Ilib/ed25519/src +# SRC+=lib/ed25519/src/add_scalar.c +SRC+=lib/ed25519/src/fe.c +SRC+=lib/ed25519/src/ge.c +SRC+=lib/ed25519/src/key_exchange.c +SRC+=lib/ed25519/src/keypair.c +SRC+=lib/ed25519/src/sc.c +SRC+=lib/ed25519/src/seed.c +SRC+=lib/ed25519/src/sha512.c +SRC+=lib/ed25519/src/sign.c +SRC+=lib/ed25519/src/verify.c + +# Map SRC into OBJ +OBJ:=$(patsubst %.c,%.o,$(SRC)) + +.PHONY: default +default: supercop + +supercop: lib/argparse lib/ed25519 $(OBJ) + $(CC) $(CFLAGS) $(INCLUDES) -o $@ $(OBJ) + +%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +lib/argparse: + mkdir -p lib/argparse + curl -sL https://github.com/cofyc/argparse/archive/refs/heads/master.tar.gz | tar xzv -C lib/argparse --strip-components=1 + +lib/ed25519: + mkdir -p lib/ed25519 + curl -sL https://github.com/orlp/ed25519/archive/refs/heads/master.tar.gz | tar xzv -C lib/ed25519 --strip-components=1 + bash -c 'cd lib/ed25519 && patch -p1 < ../../patch/ed25519/00-single-file-compile.patch' + +.PHONY: clean +clean: + rm -rf $(OBJ) diff --git a/encoding.md b/encoding.md @@ -0,0 +1,18 @@ +# Key encodings + +Keys can (or will) be encoded in multiple formats. This file shows a list of +encodings supported by this program. + +The first byte of a key-file must ALWAYS start with the version identifier +(byte sequence prefix), allowing a different prefix to identify a different type +of key encoding. + +## 0x00 + +Plain, binary, ed25519. + +Not text-safe. Starts with a 0x00 byte, followed by 32 bytes of the raw public +key, then followed by 64 bytes of the raw private key. + +Intended as the first format supported and to be deprecated later. Meant to be +simple to code, not to be safe or flexible. diff --git a/patch/ed25519/00-single-file-compile.patch b/patch/ed25519/00-single-file-compile.patch @@ -0,0 +1,156 @@ +diff --git a/src/sc.c b/src/sc.c +index ca5bad2..3d2ab56 100644 +--- a/src/sc.c ++++ b/src/sc.c +@@ -1,7 +1,7 @@ + #include "fixedint.h" + #include "sc.h" + +-static uint64_t load_3(const unsigned char *in) { ++static uint64_t sc_load_3(const unsigned char *in) { + uint64_t result; + + result = (uint64_t) in[0]; +@@ -11,7 +11,7 @@ static uint64_t load_3(const unsigned char *in) { + return result; + } + +-static uint64_t load_4(const unsigned char *in) { ++static uint64_t sc_load_4(const unsigned char *in) { + uint64_t result; + + result = (uint64_t) in[0]; +@@ -33,30 +33,30 @@ Output: + */ + + void sc_reduce(unsigned char *s) { +- int64_t s0 = 2097151 & load_3(s); +- int64_t s1 = 2097151 & (load_4(s + 2) >> 5); +- int64_t s2 = 2097151 & (load_3(s + 5) >> 2); +- int64_t s3 = 2097151 & (load_4(s + 7) >> 7); +- int64_t s4 = 2097151 & (load_4(s + 10) >> 4); +- int64_t s5 = 2097151 & (load_3(s + 13) >> 1); +- int64_t s6 = 2097151 & (load_4(s + 15) >> 6); +- int64_t s7 = 2097151 & (load_3(s + 18) >> 3); +- int64_t s8 = 2097151 & load_3(s + 21); +- int64_t s9 = 2097151 & (load_4(s + 23) >> 5); +- int64_t s10 = 2097151 & (load_3(s + 26) >> 2); +- int64_t s11 = 2097151 & (load_4(s + 28) >> 7); +- int64_t s12 = 2097151 & (load_4(s + 31) >> 4); +- int64_t s13 = 2097151 & (load_3(s + 34) >> 1); +- int64_t s14 = 2097151 & (load_4(s + 36) >> 6); +- int64_t s15 = 2097151 & (load_3(s + 39) >> 3); +- int64_t s16 = 2097151 & load_3(s + 42); +- int64_t s17 = 2097151 & (load_4(s + 44) >> 5); +- int64_t s18 = 2097151 & (load_3(s + 47) >> 2); +- int64_t s19 = 2097151 & (load_4(s + 49) >> 7); +- int64_t s20 = 2097151 & (load_4(s + 52) >> 4); +- int64_t s21 = 2097151 & (load_3(s + 55) >> 1); +- int64_t s22 = 2097151 & (load_4(s + 57) >> 6); +- int64_t s23 = (load_4(s + 60) >> 3); ++ int64_t s0 = 2097151 & sc_load_3(s); ++ int64_t s1 = 2097151 & (sc_load_4(s + 2) >> 5); ++ int64_t s2 = 2097151 & (sc_load_3(s + 5) >> 2); ++ int64_t s3 = 2097151 & (sc_load_4(s + 7) >> 7); ++ int64_t s4 = 2097151 & (sc_load_4(s + 10) >> 4); ++ int64_t s5 = 2097151 & (sc_load_3(s + 13) >> 1); ++ int64_t s6 = 2097151 & (sc_load_4(s + 15) >> 6); ++ int64_t s7 = 2097151 & (sc_load_3(s + 18) >> 3); ++ int64_t s8 = 2097151 & sc_load_3(s + 21); ++ int64_t s9 = 2097151 & (sc_load_4(s + 23) >> 5); ++ int64_t s10 = 2097151 & (sc_load_3(s + 26) >> 2); ++ int64_t s11 = 2097151 & (sc_load_4(s + 28) >> 7); ++ int64_t s12 = 2097151 & (sc_load_4(s + 31) >> 4); ++ int64_t s13 = 2097151 & (sc_load_3(s + 34) >> 1); ++ int64_t s14 = 2097151 & (sc_load_4(s + 36) >> 6); ++ int64_t s15 = 2097151 & (sc_load_3(s + 39) >> 3); ++ int64_t s16 = 2097151 & sc_load_3(s + 42); ++ int64_t s17 = 2097151 & (sc_load_4(s + 44) >> 5); ++ int64_t s18 = 2097151 & (sc_load_3(s + 47) >> 2); ++ int64_t s19 = 2097151 & (sc_load_4(s + 49) >> 7); ++ int64_t s20 = 2097151 & (sc_load_4(s + 52) >> 4); ++ int64_t s21 = 2097151 & (sc_load_3(s + 55) >> 1); ++ int64_t s22 = 2097151 & (sc_load_4(s + 57) >> 6); ++ int64_t s23 = (sc_load_4(s + 60) >> 3); + int64_t carry0; + int64_t carry1; + int64_t carry2; +@@ -360,42 +360,42 @@ Output: + */ + + void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) { +- int64_t a0 = 2097151 & load_3(a); +- int64_t a1 = 2097151 & (load_4(a + 2) >> 5); +- int64_t a2 = 2097151 & (load_3(a + 5) >> 2); +- int64_t a3 = 2097151 & (load_4(a + 7) >> 7); +- int64_t a4 = 2097151 & (load_4(a + 10) >> 4); +- int64_t a5 = 2097151 & (load_3(a + 13) >> 1); +- int64_t a6 = 2097151 & (load_4(a + 15) >> 6); +- int64_t a7 = 2097151 & (load_3(a + 18) >> 3); +- int64_t a8 = 2097151 & load_3(a + 21); +- int64_t a9 = 2097151 & (load_4(a + 23) >> 5); +- int64_t a10 = 2097151 & (load_3(a + 26) >> 2); +- int64_t a11 = (load_4(a + 28) >> 7); +- int64_t b0 = 2097151 & load_3(b); +- int64_t b1 = 2097151 & (load_4(b + 2) >> 5); +- int64_t b2 = 2097151 & (load_3(b + 5) >> 2); +- int64_t b3 = 2097151 & (load_4(b + 7) >> 7); +- int64_t b4 = 2097151 & (load_4(b + 10) >> 4); +- int64_t b5 = 2097151 & (load_3(b + 13) >> 1); +- int64_t b6 = 2097151 & (load_4(b + 15) >> 6); +- int64_t b7 = 2097151 & (load_3(b + 18) >> 3); +- int64_t b8 = 2097151 & load_3(b + 21); +- int64_t b9 = 2097151 & (load_4(b + 23) >> 5); +- int64_t b10 = 2097151 & (load_3(b + 26) >> 2); +- int64_t b11 = (load_4(b + 28) >> 7); +- int64_t c0 = 2097151 & load_3(c); +- int64_t c1 = 2097151 & (load_4(c + 2) >> 5); +- int64_t c2 = 2097151 & (load_3(c + 5) >> 2); +- int64_t c3 = 2097151 & (load_4(c + 7) >> 7); +- int64_t c4 = 2097151 & (load_4(c + 10) >> 4); +- int64_t c5 = 2097151 & (load_3(c + 13) >> 1); +- int64_t c6 = 2097151 & (load_4(c + 15) >> 6); +- int64_t c7 = 2097151 & (load_3(c + 18) >> 3); +- int64_t c8 = 2097151 & load_3(c + 21); +- int64_t c9 = 2097151 & (load_4(c + 23) >> 5); +- int64_t c10 = 2097151 & (load_3(c + 26) >> 2); +- int64_t c11 = (load_4(c + 28) >> 7); ++ int64_t a0 = 2097151 & sc_load_3(a); ++ int64_t a1 = 2097151 & (sc_load_4(a + 2) >> 5); ++ int64_t a2 = 2097151 & (sc_load_3(a + 5) >> 2); ++ int64_t a3 = 2097151 & (sc_load_4(a + 7) >> 7); ++ int64_t a4 = 2097151 & (sc_load_4(a + 10) >> 4); ++ int64_t a5 = 2097151 & (sc_load_3(a + 13) >> 1); ++ int64_t a6 = 2097151 & (sc_load_4(a + 15) >> 6); ++ int64_t a7 = 2097151 & (sc_load_3(a + 18) >> 3); ++ int64_t a8 = 2097151 & sc_load_3(a + 21); ++ int64_t a9 = 2097151 & (sc_load_4(a + 23) >> 5); ++ int64_t a10 = 2097151 & (sc_load_3(a + 26) >> 2); ++ int64_t a11 = (sc_load_4(a + 28) >> 7); ++ int64_t b0 = 2097151 & sc_load_3(b); ++ int64_t b1 = 2097151 & (sc_load_4(b + 2) >> 5); ++ int64_t b2 = 2097151 & (sc_load_3(b + 5) >> 2); ++ int64_t b3 = 2097151 & (sc_load_4(b + 7) >> 7); ++ int64_t b4 = 2097151 & (sc_load_4(b + 10) >> 4); ++ int64_t b5 = 2097151 & (sc_load_3(b + 13) >> 1); ++ int64_t b6 = 2097151 & (sc_load_4(b + 15) >> 6); ++ int64_t b7 = 2097151 & (sc_load_3(b + 18) >> 3); ++ int64_t b8 = 2097151 & sc_load_3(b + 21); ++ int64_t b9 = 2097151 & (sc_load_4(b + 23) >> 5); ++ int64_t b10 = 2097151 & (sc_load_3(b + 26) >> 2); ++ int64_t b11 = (sc_load_4(b + 28) >> 7); ++ int64_t c0 = 2097151 & sc_load_3(c); ++ int64_t c1 = 2097151 & (sc_load_4(c + 2) >> 5); ++ int64_t c2 = 2097151 & (sc_load_3(c + 5) >> 2); ++ int64_t c3 = 2097151 & (sc_load_4(c + 7) >> 7); ++ int64_t c4 = 2097151 & (sc_load_4(c + 10) >> 4); ++ int64_t c5 = 2097151 & (sc_load_3(c + 13) >> 1); ++ int64_t c6 = 2097151 & (sc_load_4(c + 15) >> 6); ++ int64_t c7 = 2097151 & (sc_load_3(c + 18) >> 3); ++ int64_t c8 = 2097151 & sc_load_3(c + 21); ++ int64_t c9 = 2097151 & (sc_load_4(c + 23) >> 5); ++ int64_t c10 = 2097151 & (sc_load_3(c + 26) >> 2); ++ int64_t c11 = (sc_load_4(c + 28) >> 7); + int64_t s0; + int64_t s1; + int64_t s2; diff --git a/src/main.c b/src/main.c @@ -0,0 +1,131 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#define COMMAND_GENERATE 1 +#define COMMAND_PUBKEY 2 +#define COMMAND_SIGN 4 +#define COMMAND_VERIFY 8 + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> + +#include "argparse.h" +#include "ed25519.h" + +static const char *const usage[] = { + "supercop <command> [options]", + NULL, +}; + +int cmd_generate(FILE *fd) { + unsigned char version = 0; + unsigned char seed[32]; + unsigned char public_key[32]; + unsigned char private_key[64]; + + if (ed25519_create_seed(seed)) { + fprintf(stderr, "Error while generating seed\n"); + return 1; + } + + ed25519_create_keypair(public_key, private_key, seed); + + // Hardcoded to format 0x00 + fwrite(&version, 1, 1, fd); + fwrite(public_key, 1, 32, fd); + fwrite(private_key, 1, 64, fd); + + return 0; +} + +int cmd_pubkey() { + return 0; +} + +int cmd_sign() { + return 0; +} +int cmd_verify() { + return 0; +} + +int main(int argc, const char **argv) { + const char *identityFile = NULL; + const char *verifySignature = NULL; + const char *message = NULL; + const char *messageFile = NULL; + int command = 0; + int result = 0; + + FILE *fidentity = NULL; + FILE *fmessage = NULL; + FILE *fout = NULL; + + // Setup help & argument parsing + struct argparse_option options[] = { + OPT_GROUP("Operations"), + OPT_BIT(0, "pubkey" , &command, "Generate new key" , NULL, COMMAND_GENERATE), + OPT_BIT(0, "generate", &command, "Generate new key" , NULL, COMMAND_GENERATE), + OPT_BIT(0, "sign" , &command, "Sign a message" , NULL, COMMAND_SIGN ), + OPT_BIT(0, "verify" , &command, "Verify a message signature", NULL, COMMAND_VERIFY ), + OPT_GROUP("Basic options"), + OPT_HELP(), + OPT_STRING('i', "identity-file", &identityFile , "Select identity file to use for the operation"), + OPT_STRING('m', "message" , &message , "Message to sign or verify (defaults to stdin)"), + OPT_STRING('M', "message-file" , &messageFile , "Message file to sign or verify (defaults to stdin)"), + OPT_STRING('s', "signature" , &verifySignature, "Signature to verify"), + OPT_END(), + }; + + // Setup basic information + struct argparse argparse; + argparse_init(&argparse, options, usage, 0); + argparse_describe(&argparse, "\nMinimalistic program to generate ed25519 keys and verify/sign messages", "\n (c) 2021 finwo"); + + // Actually parse the arguments + argc = argparse_parse(&argparse, argc, argv); + + // Our paths separate here + switch(command) { + case COMMAND_GENERATE: + + // Build output fd + fout = stdout; + if (identityFile) { + fout = fopen(identityFile, "w+"); + if (fout < 1) { + fprintf(stderr, "Could not open output file"); + return 1; + } + } + + // Actually generate the key file + result = cmd_generate(fout); + + // Close output fd if file + if (identityFile) { + fclose(fout); + } + + // Done + return result; + + case COMMAND_PUBKEY: + return cmd_pubkey(); + case COMMAND_VERIFY: + return cmd_verify(); + case COMMAND_SIGN: + return cmd_sign(); + default: + argparse_usage(&argparse); + return 1; + } + + return 42; +} + +#ifdef __cplusplus +} // extern "C" +#endif