Botan

Scrypt Hashing Algo
SHA-256, SHA-384, and SHA-3 hash digests

$ git clone https://github.com/randombit/botan.git

//https://github.com/randombit/botan/blob/master/doc/building.rst
$ ./configure.py
$ make
$ make install

#include <botan/hex.h>
#include <botan/pwdhash.h>
#include <botan/system_rng.h>
#include <array>
#include <iostream>
int main() {
    const std::string pbkdf_algo = "Argon2i";
    auto pbkdf_runtime = std::chrono::milliseconds(300);
    const size_t output_hash = 32;
    const size_t max_pbkdf_mb = 128;

    auto pwd_fam = Botan::PasswordHashFamily::create_or_throw(pbkdf_algo);

    auto pwdhash = pwd_fam->tune(output_hash, pbkdf_runtime, max_pbkdf_mb);

    std::cout << "Using params " << pwdhash->to_string() << '\n';

    std::array<uint8_t, 32> salt;
    Botan::system_rng().randomize(salt);

    const std::string password = "tell no one";

    std::array<uint8_t, output_hash> key;
    pwdhash->hash(key, password, salt);

    std::cout << Botan::hex_encode(key) << '\n';

    return 0;
}
$ g++ argon2.cpp -I/home/amit/botan/build/include/public/ -L/usr/local/lib/ -lbotan-3 -std=c++20
$ ./a.out
Using params Scrypt(65536,8,1)
EF3EE990AD3FCA2A107025A6A9029D265AC9B367FA687AE5CF5154F2E8CD56C7
    

Openssl

Build for x86

Static, shared libs
Static Libraray Shared Library

$ git clone https://github.com/openssl/openssl.git
$ cd openssl
$ ./config no-shared
$ make
$ ls -ltr *.a
-rw-r--r-- 1 amit amit 10962728 May 14 00:09 libcrypto.a
-rw-r--r-- 1 amit amit  2029566 May 14 00:11 libssl.a      
          

$ git clone https://github.com/openssl/openssl.git
$ cd openssl
$ ./config
$ make  
          

Link Code
sha3-512 Scrypt

#include <iostream>
#include <openssl/evp.h>
#include <iomanip>

using namespace std;
std::string computeSHA3_512(const std::string& message) {
    EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
    const EVP_MD *md = EVP_sha3_512();

    if (mdctx == NULL) {
        throw std::runtime_error("Error creating EVP_MD_CTX");
    }
    if (1 != EVP_DigestInit_ex(mdctx, md, NULL)) {
        EVP_MD_CTX_free(mdctx);
        throw std::runtime_error("Error initializing digest");
    }
    if (1 != EVP_DigestUpdate(mdctx, message.c_str(), message.size())) {
        EVP_MD_CTX_free(mdctx);
        throw std::runtime_error("Error updating digest");
    }
    unsigned char hash[EVP_MAX_MD_SIZE];
    unsigned int hash_len;
    if (1 != EVP_DigestFinal_ex(mdctx, hash, &hash_len)) {
        EVP_MD_CTX_free(mdctx);
        throw std::runtime_error("Error finalizing digest");
    }
    EVP_MD_CTX_free(mdctx);
    std::ostringstream hex_stream;
    hex_stream << std::hex << std::setfill('0');
    for (unsigned int i = 0; i < hash_len; ++i) {
        hex_stream << std::setw(2) << static_cast<int>(hash[i]);
    }

    return hex_stream.str();
}
int main() {
  std::string message = "Hello, OpenSSL!";
  try {
      std::string hash = computeSHA3_512(message);
      std::cout << "SHA3-512 hash: " << hash << std::endl;
  } catch (const std::runtime_error& e) {
      std::cerr << "Error: " << e.what() << std::endl;
      return 1;
  }
  return 0;
}
$ g++ sha3-512_openssl.cpp -I/home/amit/openssl/include 
-L/home/amit/openssl -l:libssl.a -l:libcrypto.a
SHA3-512 hash: 1238451fd09cfd35f94cb224a7b7f15901429c0e
2f71667c1668e8ad5467ff6d4f48ec7761aceec4d1ac8fcd2be4d9f
621fab1f734cea9ccbfbb76188ce0cdd6
          

#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <iostream>
#include <vector>
#include <iomanip>

void deriveScryptKey(const std::string& password, const std::string& salt, int N, int r, int p, size_t key_length, std::vector& derived_key) {
    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL);
    if (!pctx) {
        throw std::runtime_error("Error creating EVP_PKEY_CTX");
    }

    if (EVP_PKEY_derive_init(pctx) <= 0) {
        EVP_PKEY_CTX_free(pctx);
        throw std::runtime_error("Error initializing PKEY context");
    }

    if (EVP_PKEY_CTX_set1_pbe_pass(pctx, password.c_str(), password.size()) <= 0 ||
            EVP_PKEY_CTX_set1_scrypt_salt(
              pctx, reinterpret_cast(salt.c_str()), salt.size()) <= 0 ||
            EVP_PKEY_CTX_set_scrypt_N(pctx, N) <= 0 ||
            EVP_PKEY_CTX_set_scrypt_r(pctx, r) <= 0 ||
            EVP_PKEY_CTX_set_scrypt_p(pctx, p) <= 0 ||
            EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, 1024 * 1024 * 1024) <= 0) {
        EVP_PKEY_CTX_free(pctx);
        throw std::runtime_error("Error setting Scrypt parameters");
    }

    derived_key.resize(key_length);

    size_t outlen = derived_key.size();
    if (EVP_PKEY_derive(pctx, derived_key.data(), &outlen) <= 0) {
        EVP_PKEY_CTX_free(pctx);
        throw std::runtime_error("Error deriving Scrypt key");
    }

    EVP_PKEY_CTX_free(pctx);
}
int main() {
  std::string password = "password";
  std::string salt = "salt";
  int N = 1 << 12;
  int r = 8;
  int p = 1;
  size_t key_length = 64;

  std::vector<unsigned char> derived_key;

  try {
      deriveScryptKey(password, salt, N, r, p, key_length, derived_key);

      std::cout << "Derived key: ";
      for (unsigned char c : derived_key) {
          std::cout << std::hex << 
          std::setfill('0') << std::setw(2) << static_cast(c);
      }
      std::cout << std::endl;
  } catch (const std::runtime_error& e) {
      std::cerr << "Error: " << e.what() << std::endl;
      return 1;
  }

  return 0;
}
$ g++ scrypt_openssl.cpp -I/home/amit/openssl/include 
-L/home/amit/openssl -l:libssl.a -l:libcrypto.a
Derived key: e1d96c45c39931fbecda7a37cd6f64e0f43f12dcecce9d66cd3e279ffe603516f
356033201f31c656f8966840b9ff3098d48565b8c55c738b3a1b21cca23093e
          

Cross Complile for ARM

What is cross compile?
Cross-compiling means the process of compiling source code on one architecture (the host=x86) to generate binaries that can run on a different architecture (the target=ARM)
Cross-compilation involves using a cross-compiler toolchain. Toolchain contains(compilers, linkers, and other build tools) for target architecture.