diff --git a/code/build/buildfile b/code/build/buildfile index 4893e5f..96428a0 100644 --- a/code/build/buildfile +++ b/code/build/buildfile @@ -11,6 +11,8 @@ import intf_libs =+ libcode-seafire-routing%lib{code-seafire-routing} import intf_libs =+ libcode-seafire-representation%lib{code-seafire-representation} import intf_libs =+ libcode-seafire-resources%lib{code-seafire-resources} +import impl_libs =+ libssl%lib{ssl} + ./: lib{code-build}: libul{code-build} libul{code-build}: {hxx ixx txx cxx}{** -**.test... -version} \ diff --git a/code/build/security/base64.cxx b/code/build/security/base64.cxx new file mode 100644 index 0000000..f41a935 --- /dev/null +++ b/code/build/security/base64.cxx @@ -0,0 +1,75 @@ +#include + +#include +#include +#include + +#include + +namespace code::build::security::base64 +{ + + string + encode(string const& input) + { + BIO* base64{}; + BIO* bio{}; + string output; + + // fixme: add error checking. + // + try { + base64 = BIO_new(BIO_f_base64()); + bio = BIO_new(BIO_s_mem()); + bio = BIO_push(base64, bio); + + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + BIO_write(bio, input.data(), input.size()); + + BUF_MEM* buffer_ptr{}; + BIO_get_mem_ptr(bio, &buffer_ptr); + + output.resize(buffer_ptr->length); + std::memcpy(output.data(), buffer_ptr->data, output.size()); + + BIO_free_all(bio); + } + catch (...) { + BIO_free_all(bio); + throw; + } + + return output; + } + + string + decode(string const& input) + { + BIO* base64{}; + BIO* bio{}; + string output; + output.resize(input.size()); + + // fixme: add error checking. + // + try { + base64 = BIO_new(BIO_f_base64()); + bio = BIO_new_mem_buf(input.data(), input.size()); + bio = BIO_push(base64, bio); + + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + + auto output_length = BIO_read(bio, output.data(), output.size()); + output.resize(output_length); + + BIO_free_all(bio); + } + catch (...) { + BIO_free_all(bio); + throw; + } + + return output; + } + +} // namespace code::build::security::base64 diff --git a/code/build/security/base64.hxx b/code/build/security/base64.hxx new file mode 100644 index 0000000..fd9b449 --- /dev/null +++ b/code/build/security/base64.hxx @@ -0,0 +1,17 @@ +#ifndef code__build__security__base64_hxx_ +#define code__build__security__base64_hxx_ + +#include + +namespace code::build::security::base64 +{ + + string + encode(string const&); + + string + decode(string const&); + +} // namespace code::build::security::base64 + +#endif diff --git a/code/build/security/hash.cxx b/code/build/security/hash.cxx new file mode 100644 index 0000000..8b642be --- /dev/null +++ b/code/build/security/hash.cxx @@ -0,0 +1,59 @@ +#include + +#include + +namespace code::build::security::hash +{ + + namespace + { + + struct openssl_cleanup_t + { + void + operator()(void* ptr) + { + EVP_MD_CTX_free((EVP_MD_CTX*)ptr); + } + + }; + + template + using openssl_pointer_t = unique_ptr; + + } // namespace + + string + sha256(string const& input) + { + openssl_pointer_t context{EVP_MD_CTX_new()}; + + if (!context) { + throw runtime_error{"EVP_MD_CTX_new() failure"}; + } + + if (!EVP_DigestInit_ex(context.get(), EVP_sha256(), nullptr)) { + throw runtime_error{"EVP_DigestInit_ex() failure"}; + } + + if (!EVP_DigestUpdate(context.get(), input.data(), input.size())) { + throw runtime_error{"EVP_DigestUpdate() failure"}; + } + + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int length_of_hash{}; + + if (!EVP_DigestFinal_ex(context.get(), hash, &length_of_hash)) { + throw runtime_error{"EVP_DigestFinal_ex() failure"}; + } + + string output; + + for (unsigned int i{0}; i < length_of_hash; ++i) { + output.push_back(hash[i]); + } + + return output; + } + +} // namespace code::build::security::hash diff --git a/code/build/security/hash.hxx b/code/build/security/hash.hxx new file mode 100644 index 0000000..1ad1cdd --- /dev/null +++ b/code/build/security/hash.hxx @@ -0,0 +1,14 @@ +#ifndef code__build__security__hash_hxx_ +#define code__build__security__hash_hxx_ + +#include + +namespace code::build::security::hash +{ + + string + sha256(string const&); + +} // namespace code::build::security::hash + +#endif diff --git a/code/build/security/hmac.cxx b/code/build/security/hmac.cxx new file mode 100644 index 0000000..bcfbfe6 --- /dev/null +++ b/code/build/security/hmac.cxx @@ -0,0 +1,25 @@ +#include + +namespace code::build::security::hmac +{ + + string + sign(string const& plaintext, + string const& key) + { + // fixme: implement + // + return string{"signature"}; + } + + bool + verify(string const& plaintext, + string const& key, + string const& signature) + { + // fixme: implement + // + return signature == "signature"; + } + +} // namespace code::build::security::hmac diff --git a/code/build/security/hmac.hxx b/code/build/security/hmac.hxx new file mode 100644 index 0000000..e18ab74 --- /dev/null +++ b/code/build/security/hmac.hxx @@ -0,0 +1,17 @@ +#ifndef code__build__security__hmac_hxx_ +#define code__build__security__hmac_hxx_ + +#include + +namespace code::build::security::hmac +{ + + string + sign(string const&, string const&); + + bool + verify(string const&, string const&, string const&); + +} // namespace code::build::security::hmac + +#endif diff --git a/manifest b/manifest index 2578679..995fefa 100644 --- a/manifest +++ b/manifest @@ -10,6 +10,7 @@ email: ryan@helloryan.se depends: * build2 >= 0.17.0 depends: * bpkg >= 0.17.0 depends: libasio ^1.29.0 +depends: libssl ^3.3.1 depends: libcode-uri ^0.1.0- depends: libcode-json ^0.1.0- depends: libcode-seafire-common ^0.1.0-