Skip to content
Snippets Groups Projects
Commit 75fa0992 authored by Alexander Holodov's avatar Alexander Holodov
Browse files

supported key storage

parent 5407ceb2
Branches
No related tags found
1 merge request!1918: added c++ library
This commit is part of merge request !19. Comments created here will be created in the context of that merge request.
......@@ -19,6 +19,13 @@ const (
autoDefinition = "///{%AUTO_DEFINITION%}"
)
const autogenerated = `
/*
* Autogenerated file. DO NOT EDIT !!!!
*
*/
`
func generateCppEndPoints(templateFile string) error {
templ, err := ioutil.ReadFile(templateFile)
if err != nil {
......@@ -88,7 +95,7 @@ func generateCppEndPoints(templateFile string) error {
definition.WriteString("\n}\n\n")
}
body := string(templ)
body := autogenerated + string(templ)
body = strings.Replace(body, autoTypes, cppStructs, -1)
body = strings.Replace(body, autoDeclaration, declaration.String(), -1)
body = strings.Replace(body, autoDefinition, definition.String(), -1)
......
......@@ -3,8 +3,10 @@ project(demo)
set(CMAKE_CXX_STANDARD 14)
add_executable(demo demo.cpp vereign.hpp)
add_executable(demo demo.cpp)
FIND_PACKAGE(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIR})
target_link_libraries(demo ${CURL_LIBRARIES})
find_package(OpenSSL REQUIRED)
find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR})
target_link_libraries(demo ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES})
#include <iostream>
#include <string>
#include "secret_store.hpp"
#include "vereign.hpp"
int main(void) {
vereign::init();
const std::string pkey = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBazZzaDZoRDJDRTJkVWRJM0prNmINCnlHanRBMlpzaTh2ODVnUk5yOEhqNGFSTVBzdXJrWW5HS2hleTJibjdyeDQwMS9qVGY1ZGs5Tk5uVlpvcWFDMzcNCm81ZTVNWDRUcGRmdHBIajVnYmVtdFhQdnVrNGx0NWZibHZjdmMrV3NlVmpha0IybUdJVHQxdjhXcXFHQTVJcEYNCk53ay9ka3AwU0Q0Kzh0SVUxM3BmQ0VzWDV5N2Q2dnlyWXIrVkFERE1iLzMvRmk5MFFrNVFROGpsRnJhKytCYjgNCkxDSERxc3JnSmNKWlhRWHFja3Q2RkFKNlArT01NTmJNeE40czYvODc5R0V4a0FVUm9GM2dMd1c5RnpvdGZxTDINCkpGVnhsVjFLS0ZrV1dZZFFyaDlHWHVFLzR5UWtJQVMya3Z2UzhxdmEvbk5TOXJ2bUhkN0NpeXJkRG1XeDQzeEUNCmpRSURBUUFCDQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0NCg==";
vereign::SecretStore store("./pkey");
//store.write_string("publick_key", "pass")
const std::string pkey = store.read_string("pass");
vereign::API v("https://app.vereign.com/api");
......
{"value":"eCTA6hw/ZbKD+x9XgvIj4s6dC4Dxl8/U85r9ge6R9u5FmyKdJ9gYCv1T+ayxhwqrEIYRlc5HzUTOBg+ty6HHuyNI42ZzpLmnjxiP1Z/TbjE4T7v3cSZRNVo9LPZltqVvdKtUiHrPFTuP4ArOBKkN9PeLnp4K1CoYEpYYCYVxQ4Bi26s6FwGtHXbfHOKaKEKow6dYdfaZaEbZNZH0QnIQo3kXkXoF2Zr/A5uZEbkNfOubFLC/kUBAHdlifp1lEI56x8baVku/wnj2ewPMNsuYKzXkpK8FAkp1eP/13T5HF3VVZOkfr9A+lLiodMLBB6J5b86s0Q7i2W+ifrWma3x6E6EP2ujrriuz9fcMxC1KGpZL/T7RSEWhyHcV1m902NVBs7E/44IcVLOUUC9hKMC4sFFaib6XAXO/Ue1xWUfNoVFbaPx/IKexdBbwKqjPWrjg8YFWHlnfnUbPAKC/XCd72/EJFFd2EAClkiycFJMhjNn9vig7lUUgwb+QvD0SF14Vr4QoI3KywB3wBZgTW43ivdpfGpqUCQnV6l+4dvFmWr2Mpq+S5okgtjoxCr7TnrtqSGGopHaSlyyl1s9H/sYU9itvTOpCgtd1ufqLaD1tQKWezJUK6l5fRZjsi4g54KGZrZqgDVGB3hmL/eLWAyvcRg7/aM9RBJ9a1ytQ0088fWcjarUPaX/pAyPiOQ6qs3BaOOyV1FI//sUFZvgqVoVM6rNdg3owICZE74f0yypx3Ymh3fKRpgRtuypdhUZytBowy/aLX2hwSBs/7JcQfVELEgYTGqRrPLaCROpGbqc/7/83IS7GVMJt8w==","iterations":262144,"iv":"juFFfPAiUFg=","salt":"juFFfPAiUFjCfiJuqkyoAigxjs7jYINWuFM5c5IahNOavTfWAyzCoJW1KhDPBqKPnNsI2xQC34ajWoKM3dCm/g=="}
\ No newline at end of file
#ifndef DEMO_SECRET_STORE_HPP
#define DEMO_SECRET_STORE_HPP
#include <string>
#include <fstream>
#include <streambuf>
#include <random>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include "json.hpp"
namespace vereign {
class SecretStore {
std::string file_name;
public:
SecretStore(std::string _file_name) : file_name(_file_name){};
std::vector<unsigned char> read_value(const std::string &pass);
std::string read_string(const std::string &pass);
void write_value(const std::vector<unsigned char> &value, const std::string &pass);
void write_string(const std::string &value, const std::string &pass);
std::vector<unsigned char> decrypt(const std::string &ecnrypted, const std::string &pass);
std::string encrypt(const std::vector<unsigned char> &value, const std::string &pass);
private:
std::vector<unsigned char> crypt(AES_KEY *aes_key, const std::vector<unsigned char> &input, const std::vector<unsigned char> &iv);
const int key_length_bytes = 16;
const int salt_length_bytes = 64;
const int iterations = 1<<18;
const int iv_size = 8;
};
struct ciperparams {
std::string value;
std::string salt;
std::string iv;
int iterations;
};
void to_json(nlohmann::json &j, const ciperparams &t) {
j = nlohmann::json {
{"value", t.value},
{"salt", t.salt},
{"iv", t.iv},
{"iterations", t.iterations},
};
}
void from_json(const nlohmann::json &j, ciperparams &t) {
if (j.find("value") != j.end())
j.at("value").get_to(t.value);
if (j.find("salt") != j.end())
j.at("salt").get_to(t.salt);
if (j.find("iterations") != j.end())
j.at("iterations").get_to(t.iterations);
if (j.find("iv") != j.end())
j.at("iv").get_to(t.iv);
};
std::vector<unsigned char> SecretStore::read_value(const std::string &pass) {
std::ifstream f(file_name);
std::string str((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>());
return decrypt(str, pass);
}
std::string SecretStore::read_string(const std::string &pass) {
auto result = read_value(pass);
result.push_back(0);
return std::string((char*)result.data());
}
void SecretStore::write_value(const std::vector<unsigned char> &value, const std::string &pass) {
std::string encrypted = encrypt(value, pass);
std::ofstream out(file_name);
out << encrypted;
out.close();
}
void SecretStore::write_string(const std::string &value, const std::string &pass) {
auto arr = std::vector<unsigned char>(value.begin(), value.end());
write_value(arr, pass);
}
std::vector<unsigned char> generateRandomBytes(int size) {
std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned char> rbe;
std::vector<unsigned char> data(size);
std::generate(begin(data), end(data), std::ref(rbe));
return data;
}
std::string toHex(const std::vector<unsigned char> &data) {
std::unique_ptr<unsigned char[]> hex(new unsigned char[((data.size() + 2)/3) * 4 + 1]);
int len = EVP_EncodeBlock(hex.get(), data.data(), data.size());
if (len < 0) {
throw std::runtime_error("can't encode salt");
}
return std::string((const char*)hex.get());
}
std::vector<unsigned char> toBin(const std::string &data) {
std::unique_ptr<unsigned char[]> bin(new unsigned char[data.length()]);
auto len = EVP_DecodeBlock((unsigned char*)bin.get(), (const unsigned char*)data.c_str(), data.length());
for (auto rit=data.rbegin(); rit!=data.rend(); ++rit) {
if (*rit != '=') {
break;
}
len--;
}
if (len < 0) {
throw std::runtime_error("can't decode base64");
}
return std::vector<unsigned char>((unsigned char*)bin.get(), (unsigned char*)bin.get() + len);
}
std::string SecretStore::encrypt(const std::vector<unsigned char> &value, const std::string &pass) {
unsigned char key[key_length_bytes];
auto salt = generateRandomBytes(salt_length_bytes);
if (PKCS5_PBKDF2_HMAC_SHA1(pass.c_str(), pass.length(), salt.data(), salt.size(), iterations, key_length_bytes, key) != 1) {
throw std::runtime_error("can't crete key");
}
AES_KEY aes_key;
if (AES_set_encrypt_key(key, key_length_bytes * 8, &aes_key) < 0) {
throw std::runtime_error("can't generate key");
}
auto iv = generateRandomBytes(iv_size);
auto result = crypt(&aes_key, value, iv);
ciperparams params;
params.salt = toHex(salt);
params.iv = toHex(iv);
params.iterations = iterations;
params.value = toHex(result);
nlohmann::json j = params;
return j.dump();
}
std::vector<unsigned char> SecretStore::decrypt(const std::string &encrypted, const std::string &pass) {
nlohmann::json j = nlohmann::json::parse(encrypted);
ciperparams param = j;
unsigned char key[key_length_bytes];
auto salt = toBin(param.salt);
if (PKCS5_PBKDF2_HMAC_SHA1(pass.c_str(), pass.length(), salt.data(), salt.size(), param.iterations, key_length_bytes, key) != 1) {
throw std::runtime_error("can't crete key");
}
AES_KEY aes_key;
if (AES_set_encrypt_key(key, key_length_bytes * 8, &aes_key) < 0) {
throw std::runtime_error("can't generate key");
}
return crypt(&aes_key, toBin(param.value), toBin(param.iv));
}
std::vector<unsigned char> SecretStore::crypt(AES_KEY *aes_key, const std::vector<unsigned char> &input, const std::vector<unsigned char> &iv) {
unsigned char ivec[AES_BLOCK_SIZE] = {0};
memset(ivec, 0, sizeof(ivec));
memcpy(ivec, iv.data(), iv_size);
unsigned char ecount_buf[AES_BLOCK_SIZE];
memset(ecount_buf, 0, sizeof(ecount_buf));
unsigned int num = 0;
std::unique_ptr<unsigned char[]> output(new unsigned char[input.size()]);
AES_ctr128_encrypt(input.data(), output.get(), input.size(), aes_key, ivec, ecount_buf, &num);
return std::vector<unsigned char>((unsigned char*)output.get(), (unsigned char*)output.get() + input.size());
}
} // namespace
#endif //DEMO_SECRET_STORE_HPP
This diff is collapsed.
/*
* Autogenerated file. DO NOT EDIT !!!!
*
*/
#ifndef VEREIGN_TEMPLATE_HPP
#define VEREIGN_TEMPLATE_HPP
#include <string>
#include <curl/curl.h>
#include <vector>
......@@ -154,19 +153,12 @@ std::string API::make_http_request(const VereignAccount &a, const std::string &u
if (!a.session.empty())
list = curl_slist_append(list, ("token: " + a.session).c_str());
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
std::cout << "url = " << this->url + url << std::endl;
curl_easy_setopt(curl, CURLOPT_URL, (this->url + url).c_str());
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "vcl");
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
if (!inp.empty()) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, inp.c_str());
} else {
......@@ -187,3 +179,5 @@ std::string API::make_http_request(const VereignAccount &a, const std::string &u
} /// namespace vereign
#endif // VEREIGN_TEMPLATE_HPP
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment