/* Copyright (C) 2021  Noisytoot

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as
   published by the Free Software Foundation, either version 3 of the
   License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>. */

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sodium.h>

#include "common.h"

int main(int argc, char *argv[]) {
  FILE *keyfile;
  char base64_sk[base64_sk_len + 1];
  unsigned char sk[crypto_sign_SECRETKEYBYTES];
  size_t sk_len;
  unsigned char message[max_message_len + 1];
  ssize_t message_len;
  unsigned char signature[crypto_sign_BYTES];
  char base64_signature[base64_signature_len];
  if (argc < 2) {
    fprintf(stderr, "usage: %s <keyfile>\n", argv[0]);
    return 1;
  }
  if ((keyfile = fopen(argv[1], "r")) == NULL) {
    fprintf(stderr, "open: %s: %s\n", argv[1], strerror(errno));
    return 1;
  }
  memset(base64_sk, 0, base64_sk_len + 1); /* sodium_base642bin expects a string */
  fread(base64_sk, base64_sk_len, 1, keyfile);
  if (sodium_init() == -1) {
    fprintf(stderr, "error: sodium_init failed\n");
    return 1;
  }
  if ((sodium_base642bin(sk, crypto_sign_SECRETKEYBYTES,
                         base64_sk, base64_sk_len,
                         base64_ignore, &sk_len,
                         NULL, base64_variant)) != 0) {
    fprintf(stderr, "error: failed to decode private key\n");
    return 1;
  }
  if (sk_len != crypto_sign_SECRETKEYBYTES) {
    fprintf(stderr, "error: key too short (got %ld bytes, expected %d bytes)\n", sk_len, crypto_sign_SECRETKEYBYTES);
    return 1;
  }
  memset(message, 0, max_message_len + 1); /* so %s can be used to print it */
  message_len = read(0, message, max_message_len);
  if (message_len == -1) {
    perror("read");
    return 1;
  }
  crypto_sign_detached(signature, NULL, message, message_len, sk);
  sodium_bin2base64(base64_signature, base64_signature_len,
                    signature, crypto_sign_BYTES, base64_variant);
  printf("%s %s\n", base64_signature, message);
  return 0;
}