diff --git a/Makefile b/Makefile index e5fe7ab..1ceacb7 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,16 @@ -all: auth-server gen-key gen-keypair +all: auth-client auth-server gen-key gen-keypair %.o: %.cc g++ -std=c++11 -c -o $@ $< +auth-client: auth-client.o crypto.o tlv.o + g++ -o auth-client auth-client.o crypto.o tlv.o -lsodium + auth-server: auth-server.o crypto.o tlv.o - g++ -o auth-server auth-server.o crypto.o tlv.o nacl/build/instance1/lib/amd64/randombytes.o nacl/build/instance1/lib/amd64/libnacl.a + g++ -o auth-server auth-server.o crypto.o tlv.o -lsodium gen-key: gen-key.o crypto.o tlv.o - g++ -o gen-key gen-key.o crypto.o tlv.o nacl/build/instance1/lib/amd64/randombytes.o nacl/build/instance1/lib/amd64/libnacl.a + g++ -o gen-key gen-key.o crypto.o tlv.o -lsodium gen-keypair: gen-keypair.o crypto.o tlv.o - g++ -o gen-keypair gen-keypair.o crypto.o tlv.o nacl/build/instance1/lib/amd64/randombytes.o nacl/build/instance1/lib/amd64/libnacl.a + g++ -o gen-keypair gen-keypair.o crypto.o tlv.o -lsodium diff --git a/auth-client.cc b/auth-client.cc new file mode 100644 index 0000000..883466a --- /dev/null +++ b/auth-client.cc @@ -0,0 +1,85 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "crypto.h" + +static const struct option long_options[] = { + {"secret_key_filename", required_argument, NULL, 's'}, + {"server_public_key_filename", required_argument, NULL, 'r'}, + {"server_address", required_argument, NULL, 'a'}, + {"server_port", required_argument, NULL, 't'}, +}; + +int main(int argc, char *argv[]) { + std::string secret_key_filename; + std::string public_key_filename; + std::string server_public_key_filename; + std::string server_address; + std::string server_port; + { + int option, option_index; + while ((option = getopt_long(argc, argv, "s:", long_options, &option_index)) != -1) { + switch (option) { + case 's': + secret_key_filename = optarg; + break; + case 'p': + public_key_filename = optarg; + break; + case 'r': + server_public_key_filename = optarg; + break; + case 'a': + server_address = optarg; + break; + case 't': + server_port = optarg; + break; + } + } + } + + std::string secret_key; + { + std::fstream secret_key_file(secret_key_filename, std::fstream::in); + if (secret_key_file.fail()) { + std::cerr << "Failed to open secret key file" << std::endl; + return 1; + } + secret_key_file >> secret_key; + } + + std::string server_public_key; + { + std::fstream server_public_key_file(server_public_key_filename, std::fstream::in); + if (server_public_key_file.fail()) { + std::cerr << "Failed to open server public key file" << std::endl; + return 1; + } + server_public_key_file >> server_public_key; + } + + int fd; + { + struct addrinfo* res; + int ret = getaddrinfo(server_address.c_str(), server_port.c_str(), NULL, &res); + if (ret) { + std::cerr << "Failed to resolve server_address: " << gai_strerror(ret) << std::endl; + return 1; + } + fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (connect(fd, (struct sockaddr*)res->ai_addr, res->ai_addrlen)) { + perror("connect"); + return 1; + } + freeaddrinfo(res); + } +} diff --git a/crypto.cc b/crypto.cc index 314dd7e..6e14baf 100644 --- a/crypto.cc +++ b/crypto.cc @@ -3,13 +3,15 @@ #include #include +#include #include +#include +#include +#include + #include "crypto.h" -#include "nacl/build/instance1/include/amd64/crypto_box.h" -#include "nacl/build/instance1/include/amd64/crypto_secretbox.h" -#include "nacl/build/instance1/include/amd64/randombytes.h" CryptoBase::CryptoBase(const int fd) : fd_(fd) {} @@ -21,13 +23,17 @@ CryptoBase::~CryptoBase() { } void CryptoBase::GenKey(std::string* key) { - char buf[crypto_secretbox_KEYBYTES]; - randombytes((unsigned char *)buf, crypto_secretbox_KEYBYTES); - *key = buf; + unsigned char buf[crypto_secretbox_KEYBYTES]; + randombytes_buf(buf, crypto_secretbox_KEYBYTES); + key->assign((char*)buf, crypto_secretbox_KEYBYTES); } void CryptoBase::GenKeyPair(std::string* secret_key, std::string* public_key) { - *public_key = crypto_box_keypair(secret_key); + unsigned char public_key_buf[crypto_box_PUBLICKEYBYTES]; + unsigned char secret_key_buf[crypto_box_PUBLICKEYBYTES]; + assert(crypto_box_keypair(public_key_buf, secret_key_buf) == 0); + public_key->assign((char*)public_key_buf, crypto_box_PUBLICKEYBYTES); + secret_key->assign((char*)secret_key_buf, crypto_box_SECRETKEYBYTES); } diff --git a/tlv.cc b/tlv.cc index 44f5441..9163db7 100644 --- a/tlv.cc +++ b/tlv.cc @@ -1,8 +1,39 @@ +#include + #include "tlv.h" +struct header { + uint16_t type; + uint16_t value_length; +}; + TLVNode::TLVNode(const uint16_t type) : type_(type) {} TLVNode::TLVNode(const uint16_t type, const std::string value) : type_(type), value_(value) {} + +void TLVNode::Encode(std::string *output) { + assert(value_.length() <= UINT16_MAX); + struct header header = { + .type = type_, + .value_length = (uint16_t)value_.length(), + }; + size_t header_start = output->length(); + output->append((char*)&header, sizeof(header)); + + if (IsContainer()) { + for (auto child : children_) { + child.Encode(output); + } + size_t total_child_length = output->length() - header_start - sizeof(header); + assert(total_child_length <= UINT16_MAX); + header.value_length = (uint16_t)total_child_length; + output->replace(header_start, sizeof(header), (char*)&header, sizeof(header)); + } +} + +bool TLVNode::IsContainer() { + return type_ & 0x8000; +} diff --git a/tlv.h b/tlv.h index 0da9304..d9a1678 100644 --- a/tlv.h +++ b/tlv.h @@ -11,6 +11,8 @@ class TLVNode { static TLVNode* Decode(const std::string& input); void Encode(std::string *output); + bool IsContainer(); + private: const uint16_t type_; const std::string value_;