build,logic : Key/License Generator
Generator using the Botan Cyrptography library
This commit is contained in:
committed by
Eberhard Graether
parent
743f91e882
commit
23257a3071
@@ -0,0 +1,8 @@
|
||||
add_files(
|
||||
GEN_FILES
|
||||
|
||||
Generator.cpp
|
||||
Generator.h
|
||||
License.cpp
|
||||
License.h
|
||||
)
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "Generator.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "botan_all.h"
|
||||
#include "boost/filesystem.hpp"
|
||||
|
||||
#include "License.h"
|
||||
|
||||
Generator::Generator(std::string version)
|
||||
: m_version(version)
|
||||
{
|
||||
}
|
||||
|
||||
Generator::~Generator()
|
||||
{
|
||||
}
|
||||
|
||||
void Generator::generateKeys()
|
||||
{
|
||||
m_privateKey = std::make_shared<Botan::RSA_PrivateKey>(m_rng, 2048);
|
||||
}
|
||||
|
||||
std::string Generator::getPrivateKeyFilename()
|
||||
{
|
||||
if(m_privateKeyFile.empty())
|
||||
{
|
||||
return "private-" + m_version + KEY_FILEENDING;
|
||||
}
|
||||
return m_privateKeyFile;
|
||||
}
|
||||
|
||||
std::string Generator::getPublicKeyFilename()
|
||||
{
|
||||
if(m_publicKeyFile.empty())
|
||||
{
|
||||
return "public-" + m_version + KEY_FILEENDING;
|
||||
}
|
||||
return m_publicKeyFile;
|
||||
}
|
||||
|
||||
void Generator::setVersion(std::string version)
|
||||
{
|
||||
if(!version.empty())
|
||||
{
|
||||
m_version = version;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Generator::encodeLicense(std::string user)
|
||||
{
|
||||
License license;
|
||||
|
||||
//load private key
|
||||
std::string filename = getPrivateKeyFilename();
|
||||
std::shared_ptr<Botan::Private_Key> privateKey(
|
||||
Botan::PKCS8::load_key(filename, m_rng, PRIVATE_KEY_PASSWORD));
|
||||
Botan::RSA_PrivateKey *rsaKey = dynamic_cast<Botan::RSA_PrivateKey *>(privateKey.get());
|
||||
if (!rsaKey) {
|
||||
std::cout << "The key is not a RSA key" << std::endl;
|
||||
}
|
||||
|
||||
license.create(user, m_version, rsaKey);
|
||||
license.writeToFile("license.txt");
|
||||
license.print();
|
||||
|
||||
return license.getLicenseString();
|
||||
}
|
||||
|
||||
bool Generator::verifyLicense(std::string filename)
|
||||
{
|
||||
License license;
|
||||
license.loadFromFile(filename);
|
||||
license.setVersion(m_version);
|
||||
license.loadPublicKeyFromFile(getPublicKeyFilename());
|
||||
return license.isValid();
|
||||
}
|
||||
|
||||
void Generator::setCustomPrivateKeyFile(std::string file)
|
||||
{
|
||||
if(!file.empty())
|
||||
{
|
||||
m_privateKeyFile = file;
|
||||
}
|
||||
}
|
||||
|
||||
void Generator::setCustomPublicKeyFile(std::string file)
|
||||
{
|
||||
if(!file.empty())
|
||||
{
|
||||
m_publicKeyFile = file;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Generator::getPublicKeyPEMFileAsString()
|
||||
{
|
||||
return Botan::X509::PEM_encode(*m_privateKey);
|
||||
}
|
||||
|
||||
std::string Generator::getPrivateKeyPEMFileAsString()
|
||||
{
|
||||
return Botan::PKCS8::PEM_encode(*m_privateKey, m_rng, PRIVATE_KEY_PASSWORD);
|
||||
}
|
||||
|
||||
void Generator::writeKeysToFiles()
|
||||
{
|
||||
//public key
|
||||
std::string filename = getPublicKeyFilename();
|
||||
std::cout << "publickey filename: " << filename << std::endl;
|
||||
std::ofstream pub(filename);
|
||||
pub << getPublicKeyPEMFileAsString();
|
||||
std::cout << "public key created" << std::endl;
|
||||
// private key
|
||||
filename = getPrivateKeyFilename();
|
||||
std::cout << "publickey filename: " << filename << std::endl;
|
||||
std::ofstream priv(filename);
|
||||
priv << getPrivateKeyPEMFileAsString();
|
||||
std::cout << "private key created" << std::endl;
|
||||
}
|
||||
|
||||
bool Generator::loadPrivateKeyFromFile()
|
||||
{
|
||||
boost::filesystem::exists(getPrivateKeyFilename());
|
||||
Botan::Private_Key* privateKey = Botan::PKCS8::load_key(getPrivateKeyFilename(), m_rng, PRIVATE_KEY_PASSWORD);
|
||||
Botan::RSA_PrivateKey *rsaKey = dynamic_cast<Botan::RSA_PrivateKey *>(privateKey);
|
||||
if (!rsaKey) {
|
||||
std::cout << "The key is not a RSA key" << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_privateKey = std::shared_ptr<Botan::RSA_PrivateKey>(rsaKey);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Generator::loadPrivateKeyFromString(std::string key)
|
||||
{
|
||||
Botan::DataSource_Memory in(key);
|
||||
Botan::Private_Key* privateKey= Botan::PKCS8::load_key(in, m_rng, PRIVATE_KEY_PASSWORD);
|
||||
Botan::RSA_PrivateKey *rsaKey = dynamic_cast<Botan::RSA_PrivateKey *>(privateKey);
|
||||
if (!rsaKey) {
|
||||
std::cout << "The key is not a RSA key" << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_privateKey = std::shared_ptr<Botan::RSA_PrivateKey>(rsaKey);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Botan::RSA_PrivateKey *Generator::getPrivateKey() const
|
||||
{
|
||||
return m_privateKey.get();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef KEYGEN_H
|
||||
#define KEYGEN_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "botan_all.h"
|
||||
|
||||
class Generator
|
||||
{
|
||||
public:
|
||||
Generator(std::string version = "x");
|
||||
~Generator();
|
||||
|
||||
std::string encodeLicense(std::string message);
|
||||
bool verifyLicense(std::string filename = "license.txt");
|
||||
void generateKeys();
|
||||
void writeKeysToFiles();
|
||||
void setVersion(std::string version);
|
||||
void setCustomPrivateKeyFile(std::string file);
|
||||
void setCustomPublicKeyFile(std::string file);
|
||||
|
||||
std::string getPublicKeyPEMFileAsString();
|
||||
std::string getPrivateKeyPEMFileAsString();
|
||||
bool loadPrivateKeyFromFile();
|
||||
bool loadPrivateKeyFromString(std::string key);
|
||||
|
||||
void PrintLicense();
|
||||
|
||||
Botan::RSA_PrivateKey* getPrivateKey() const;
|
||||
|
||||
private:
|
||||
std::string getPrivateKeyFilename();
|
||||
std::string getPublicKeyFilename();
|
||||
|
||||
//Botan
|
||||
Botan::AutoSeeded_RNG m_rng;
|
||||
|
||||
std::string m_version;
|
||||
std::string m_privateKeyFile;
|
||||
std::string m_publicKeyFile;
|
||||
std::string m_license;
|
||||
std::shared_ptr<Botan::RSA_PrivateKey> m_privateKey;
|
||||
|
||||
const std::string PRIVATE_KEY_PASSWORD = "BA#jk5vbklAiKL9K3k$";
|
||||
const std::string KEY_FILEENDING = ".pem";
|
||||
};
|
||||
|
||||
#endif // KEYGEN_H
|
||||
@@ -0,0 +1,319 @@
|
||||
#include "License.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <istream>
|
||||
|
||||
// #include "botan/pubkey.h"
|
||||
// #include "botan/base64.h"
|
||||
// #include "botan/passhash9.h"
|
||||
|
||||
#include "boost/filesystem.hpp"
|
||||
|
||||
// #ifdef BOTAN_HAS_RSA
|
||||
// #include "botan/rsa.h"
|
||||
// #endif
|
||||
|
||||
License::License()
|
||||
{
|
||||
}
|
||||
|
||||
License::~License()
|
||||
{
|
||||
}
|
||||
|
||||
std::string License::getHashLine()
|
||||
{
|
||||
return lines[4];
|
||||
}
|
||||
|
||||
std::string License::getMessage()
|
||||
{
|
||||
std::string message = "";
|
||||
for(int i = 1; i < 5; ++i)
|
||||
{
|
||||
message += lines[i];
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
std::string License::getSignature()
|
||||
{
|
||||
std::string signatue = "";
|
||||
for(int i = 5; i < 12; ++i)
|
||||
{
|
||||
signatue += lines[i];
|
||||
}
|
||||
return signatue;
|
||||
}
|
||||
|
||||
std::string License::getVersionLine()
|
||||
{
|
||||
return lines[3];
|
||||
}
|
||||
|
||||
void License::create(std::string user, std::string version, Botan::RSA_PrivateKey* privateKey, unsigned int type)
|
||||
{
|
||||
m_version = version;
|
||||
createMessage(user, version, type);
|
||||
|
||||
//encode message
|
||||
Botan::PK_Signer signer(*privateKey, "EMSA4(SHA-256)");
|
||||
Botan::DataSource_Memory in(getMessage());
|
||||
Botan::byte buf[4096] = {0};
|
||||
while (size_t got = in.read(buf, sizeof(buf))) {
|
||||
signer.update(buf, got);
|
||||
}
|
||||
std::string signature = Botan::base64_encode(signer.signature(m_rng));
|
||||
addSignature(signature);
|
||||
}
|
||||
|
||||
void License::createMessage(std::string user, std::string version, unsigned int type)
|
||||
{
|
||||
lines.clear();
|
||||
lines.push_back(BEGIN_LICENSE);
|
||||
lines.push_back(user);
|
||||
std::string typestring;
|
||||
switch(type)
|
||||
{
|
||||
case 0:
|
||||
default:
|
||||
typestring = "Single User License";
|
||||
|
||||
};
|
||||
lines.push_back(typestring);
|
||||
std::string versionstring = "Coati " + getVersion();
|
||||
lines.push_back(versionstring);
|
||||
std::string pass9 = Botan::generate_passhash9(versionstring, m_rng);
|
||||
lines.push_back(pass9);
|
||||
}
|
||||
|
||||
void License::writeToFile(std::string filename)
|
||||
{
|
||||
std::ofstream licenseFile(filename);
|
||||
for(std::string line : lines)
|
||||
{
|
||||
licenseFile << line << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool License::loadFromString(std::string licenseText)
|
||||
{
|
||||
lines.clear();
|
||||
std::istringstream license(licenseText);
|
||||
return load(license);
|
||||
}
|
||||
|
||||
bool License::load(std::istream& stream)
|
||||
{
|
||||
lines.clear();
|
||||
std::string line;
|
||||
if(!getline(stream, line, '\n'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(line.compare(BEGIN_LICENSE) )
|
||||
{
|
||||
std::cout << "No License Header" << std::endl;
|
||||
lines.push_back(BEGIN_LICENSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
lines.push_back(line);
|
||||
if(!getline(stream, line))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
lines.push_back(line);
|
||||
|
||||
for(int i = 0; i < 2; ++i)
|
||||
{
|
||||
if(!getline(stream, line))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
lines.push_back(line);
|
||||
}
|
||||
if(!getline(stream, line))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
lines.push_back(line);
|
||||
|
||||
//get signature
|
||||
std::string signature = "";
|
||||
for(int i = 0; i < 7; ++i)
|
||||
{
|
||||
if(!getline(stream, line))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
signature += line;
|
||||
lines.push_back(line);
|
||||
}
|
||||
|
||||
//check License ending
|
||||
getline(stream, line);
|
||||
if(line.compare(END_LICENSE))
|
||||
{
|
||||
std::cout << "No License Footer" << std::endl;
|
||||
lines.push_back(END_LICENSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
lines.push_back(line);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool License::loadFromFile(std::string filename)
|
||||
{
|
||||
lines.clear();
|
||||
std::ifstream sigfile(filename);
|
||||
return load(sigfile);
|
||||
}
|
||||
|
||||
void License::print()
|
||||
{
|
||||
std::cout << getLicenseString();
|
||||
}
|
||||
|
||||
std::string License::getOwnerLine()
|
||||
{
|
||||
return lines[1];
|
||||
}
|
||||
|
||||
std::string License::getLicenseTypeLine()
|
||||
{
|
||||
return lines[2];
|
||||
}
|
||||
|
||||
void License::addSignature(std::string signature)
|
||||
{
|
||||
if(lines.size() > 5)
|
||||
{
|
||||
std::cout << "signature already there" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (!signature.size()) {
|
||||
std::cout << "signature is empty." << std::endl;
|
||||
return;
|
||||
}
|
||||
std::stringstream ss;
|
||||
for (size_t i = 0; i < signature.size(); i++) {
|
||||
if(i % 55 == 0 && i != 0)
|
||||
{
|
||||
lines.push_back(ss.str());
|
||||
ss.str("");
|
||||
}
|
||||
ss << signature[i];
|
||||
}
|
||||
lines.push_back(ss.str());
|
||||
lines.push_back(END_LICENSE);
|
||||
}
|
||||
|
||||
bool License::isValid()
|
||||
{
|
||||
if(!m_publicKey)
|
||||
{
|
||||
std::cout << "No public key loaded" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if(Botan::check_passhash9("Coati "+ getVersion(), getHashLine()))
|
||||
{
|
||||
std::cout << "Hash from Coati "+ getVersion() + " confirmed" << std::endl;
|
||||
}
|
||||
|
||||
Botan::secure_vector<Botan::byte> sig = Botan::base64_decode(getSignature());
|
||||
|
||||
Botan::PK_Verifier verifier(*m_publicKey.get(), "EMSA4(SHA-256)");
|
||||
|
||||
Botan::DataSource_Memory in(getMessage());
|
||||
Botan::byte buf[4096] = {0};
|
||||
while(size_t got = in.read(buf, sizeof(buf)))
|
||||
{
|
||||
verifier.update(buf, got);
|
||||
}
|
||||
|
||||
const bool ok = verifier.check_signature(sig);
|
||||
return ok;
|
||||
}
|
||||
|
||||
std::string License::getPublicKeyFilename()
|
||||
{
|
||||
if(m_publicKeyFilename.empty())
|
||||
{
|
||||
return "public-" + getVersion() + KEY_FILEENDING;
|
||||
}
|
||||
return m_publicKeyFilename;
|
||||
}
|
||||
|
||||
std::string License::getVersion() {
|
||||
if(m_version.empty())
|
||||
{
|
||||
return "x";
|
||||
}
|
||||
return m_version;
|
||||
}
|
||||
|
||||
bool License::loadPublicKeyFromFile(std::string filename)
|
||||
{
|
||||
if (!filename.empty()) {
|
||||
m_publicKeyFilename = filename;
|
||||
}
|
||||
if(boost::filesystem::exists(getPublicKeyFilename()))
|
||||
{
|
||||
Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast<Botan::RSA_PublicKey *>(Botan::X509::load_key(getPublicKeyFilename()));
|
||||
if (!rsaPublicKey) {
|
||||
std::cout << "The loaded key is not a RSA key" << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_publicKey = std::shared_ptr<Botan::RSA_PublicKey>(rsaPublicKey);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool License::loadPublicKeyFromString(std::string publicKey)
|
||||
{
|
||||
Botan::DataSource_Memory in(publicKey);
|
||||
Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast<Botan::RSA_PublicKey *>(Botan::X509::load_key(in));
|
||||
if (!rsaPublicKey) {
|
||||
std::cout << "The loaded key is not a RSA key" << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_publicKey = std::shared_ptr<Botan::RSA_PublicKey>(rsaPublicKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void License::setVersion(const std::string& version)
|
||||
{
|
||||
if(!version.empty())
|
||||
{
|
||||
m_version = version;
|
||||
}
|
||||
}
|
||||
|
||||
std::string License::getLicenseString()
|
||||
{
|
||||
std::stringstream license;
|
||||
for(std::string line : lines)
|
||||
{
|
||||
license << line << std::endl;
|
||||
}
|
||||
return license.str();
|
||||
}
|
||||
|
||||
bool License::checkLocation(const std::string& location, const std::string& hash)
|
||||
{
|
||||
return Botan::check_passhash9(location, hash);
|
||||
}
|
||||
|
||||
std::string License::hashLocation(const std::string& location)
|
||||
{
|
||||
return Botan::generate_passhash9(location, m_rng);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef COATI_LICENSE_H
|
||||
#define COATI_LICENSE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//#include "botan/botan.h"
|
||||
#include "botan_all.h"
|
||||
|
||||
#ifdef BOTAN_HAS_RSA
|
||||
//#include "botan/rsa.h"
|
||||
#endif
|
||||
|
||||
class License {
|
||||
public:
|
||||
enum LicenseType
|
||||
{
|
||||
LICENSETYPE_SINGLEUSER = 0,
|
||||
};
|
||||
License();
|
||||
~License();
|
||||
|
||||
std::string getHashLine();
|
||||
std::string getMessage();
|
||||
std::string getSignature();
|
||||
std::string getVersionLine();
|
||||
std::string getOwnerLine();
|
||||
std::string getLicenseTypeLine();
|
||||
|
||||
std::string getPublicKeyFilename();
|
||||
std::string getVersion();
|
||||
|
||||
void create(std::string user, std::string version, Botan::RSA_PrivateKey* privateKey, unsigned int type = 0);
|
||||
|
||||
std::string getLicenseString();
|
||||
|
||||
void writeToFile(std::string filename);
|
||||
bool load(std::istream& stream);
|
||||
bool loadFromString(std::string licenseText);
|
||||
bool loadFromFile(std::string filename);
|
||||
|
||||
bool loadPublicKeyFromFile(std::string);
|
||||
bool loadPublicKeyFromString(std::string);
|
||||
|
||||
void setVersion(const std::string&);
|
||||
bool isValid();
|
||||
|
||||
void print();
|
||||
|
||||
std::string hashLocation(const std::string&);
|
||||
bool checkLocation(const std::string&, const std::string&);
|
||||
private:
|
||||
void createMessage(std::string user, std::string version, unsigned int type = 0);
|
||||
void addSignature(std::string);
|
||||
std::string m_version;
|
||||
std::string m_publicKeyFilename;
|
||||
std::shared_ptr<Botan::RSA_PublicKey> m_publicKey;
|
||||
std::vector<std::string> lines;
|
||||
Botan::AutoSeeded_RNG m_rng;
|
||||
|
||||
const std::string KEY_FILEENDING = ".pem";
|
||||
const std::string BEGIN_LICENSE = "-----BEGIN LICENSE-----";
|
||||
const std::string END_LICENSE = "-----END LICENSE-----";
|
||||
};
|
||||
|
||||
#endif //COATI_LICENSE_H
|
||||
@@ -0,0 +1,93 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
|
||||
#include "boost/program_options.hpp"
|
||||
|
||||
#include "Generator.h"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
bool process_command_line(int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string user;
|
||||
std::string version;
|
||||
std::string privateKey;
|
||||
std::string publicKey;
|
||||
std::string license;
|
||||
po::options_description desc("Coati Generator");
|
||||
|
||||
desc.add_options()
|
||||
("help,h", "Print this help message")
|
||||
("key,k", "Generate the private and public key")
|
||||
("generate,g", po::value<std::string>(&user), "Generate a License, USERNAME as value")
|
||||
("check,c", "Validate a License")
|
||||
("version,v", po::value<std::string>(&version), "Versionnumber of Coati")
|
||||
("public-file", po::value<std::string>(&publicKey), "Custom public key file")
|
||||
("private-file", po::value<std::string>(&privateKey), "Custom private key file")
|
||||
("license-file", po::value<std::string>(&license), "Custom license")
|
||||
;
|
||||
po::variables_map vm;
|
||||
|
||||
po::store(po::parse_command_line(argc,argv,desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
Generator keygen(version);
|
||||
|
||||
if(vm.count("help"))
|
||||
{
|
||||
std::cout << desc << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm.count("key"))
|
||||
{
|
||||
keygen.generateKeys();
|
||||
keygen.writeKeysToFiles();
|
||||
}
|
||||
|
||||
if (vm.count("public-file"))
|
||||
{
|
||||
keygen.setCustomPublicKeyFile(publicKey);
|
||||
}
|
||||
|
||||
if (vm.count("private-file"))
|
||||
{
|
||||
keygen.setCustomPrivateKeyFile(privateKey);
|
||||
}
|
||||
|
||||
if(vm.count("generate"))
|
||||
{
|
||||
// std::cout << "generate License" << std::endl;
|
||||
keygen.encodeLicense(user);
|
||||
|
||||
}
|
||||
|
||||
if(vm.count("check"))
|
||||
{
|
||||
if(keygen.verifyLicense())
|
||||
{
|
||||
std::cout << "License valid" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "License not valid" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cout << "Exception caught: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
process_command_line(argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -22,7 +22,6 @@ std::shared_ptr<Application> Application::create(
|
||||
const Version& version, ViewFactory* viewFactory, NetworkFactory* networkFactory
|
||||
){
|
||||
Version::setApplicationVersion(version);
|
||||
|
||||
loadSettings();
|
||||
|
||||
std::shared_ptr<Application> ptr(new Application());
|
||||
|
||||
@@ -160,3 +160,23 @@ int ApplicationSettings::getControlsMouseForwardButton() const
|
||||
{
|
||||
return getValue<int>("controls/mouse_forward_button", 0x10);
|
||||
}
|
||||
|
||||
std::string ApplicationSettings::getLicenseString() const
|
||||
{
|
||||
return getValue<std::string>("application/license/license:", "");
|
||||
}
|
||||
|
||||
std::string ApplicationSettings::getLicenseCheck() const
|
||||
{
|
||||
return getValue<std::string>("application/license/check", "");
|
||||
}
|
||||
|
||||
void ApplicationSettings::setLicenseString(const std::string& licenseString)
|
||||
{
|
||||
setValue<std::string>("application/license/license", licenseString);
|
||||
}
|
||||
|
||||
void ApplicationSettings::setLicenseCheck(const std::string& hash)
|
||||
{
|
||||
setValue<std::string>("application/license/check", hash);
|
||||
}
|
||||
|
||||
@@ -63,6 +63,13 @@ public:
|
||||
int getControlsMouseBackButton() const;
|
||||
int getControlsMouseForwardButton() const;
|
||||
|
||||
// license
|
||||
std::string getLicenseString() const;
|
||||
void setLicenseString(const std::string& licenseString);
|
||||
|
||||
std::string getLicenseCheck() const;
|
||||
void setLicenseCheck(const std::string& hash);
|
||||
|
||||
private:
|
||||
ApplicationSettings();
|
||||
ApplicationSettings(const ApplicationSettings&);
|
||||
|
||||
@@ -107,6 +107,8 @@ add_files(
|
||||
qt/window/QtAboutLicense.h
|
||||
qt/window/QtApplicationSettingsScreen.cpp
|
||||
qt/window/QtApplicationSettingsScreen.h
|
||||
qt/window/QtLicense.cpp
|
||||
qt/window/QtLicense.h
|
||||
qt/window/QtMainWindow.cpp
|
||||
qt/window/QtMainWindow.h
|
||||
qt/window/QtProjectSetupScreen.cpp
|
||||
|
||||
@@ -95,12 +95,7 @@ void QtAbout::setup()
|
||||
closeButton->setObjectName("closeButton");
|
||||
closeButton->move(320, 20);
|
||||
|
||||
connect(closeButton, SIGNAL(clicked()), this, SLOT(handleCloseButtonPress()));
|
||||
}
|
||||
|
||||
void QtAbout::handleCloseButtonPress()
|
||||
{
|
||||
emit finished();
|
||||
connect(closeButton, SIGNAL(clicked()), this, SLOT(handleUpdateButtonPress()));
|
||||
}
|
||||
|
||||
void QtAbout::handleCancelButtonPress()
|
||||
@@ -109,4 +104,5 @@ void QtAbout::handleCancelButtonPress()
|
||||
|
||||
void QtAbout::handleUpdateButtonPress()
|
||||
{
|
||||
emit finished();
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ public:
|
||||
virtual void setup() override;
|
||||
|
||||
private slots:
|
||||
void handleCloseButtonPress();
|
||||
|
||||
void handleCancelButtonPress();
|
||||
void handleUpdateButtonPress();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "qt/window/QtLicense.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QFormLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QLabel>
|
||||
#include <QTextBrowser>
|
||||
#include <QTextBlock>
|
||||
#include <QTextEdit>
|
||||
|
||||
#include "License.h"
|
||||
#include "PublicKey.h"
|
||||
|
||||
#include "settings/ApplicationSettings.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/file/FilePath.h"
|
||||
|
||||
QtLicense::QtLicense(QWidget *parent)
|
||||
: QtSettingsWindow(parent)
|
||||
{
|
||||
raise();
|
||||
}
|
||||
|
||||
QSize QtLicense::sizeHint() const
|
||||
{
|
||||
return QSize(600,600);
|
||||
}
|
||||
|
||||
void QtLicense::setup()
|
||||
{
|
||||
setupForm();
|
||||
|
||||
updateTitle("Enter License");
|
||||
updateDoneButton("Ok");
|
||||
}
|
||||
|
||||
void QtLicense::populateForm(QFormLayout* layout)
|
||||
{
|
||||
QLabel* licenseName = new QLabel();
|
||||
licenseName->setText( QString::fromLatin1("Enter License:"));
|
||||
QFont _font = licenseName->font();
|
||||
_font.setPixelSize(36);
|
||||
licenseName->setFont(_font);
|
||||
layout->addWidget(licenseName);
|
||||
|
||||
m_licenseText = new QTextEdit();
|
||||
m_licenseText->setMinimumHeight(300);
|
||||
layout->addWidget(m_licenseText);
|
||||
}
|
||||
|
||||
void QtLicense::handleCancelButtonPress()
|
||||
{
|
||||
emit canceled();
|
||||
}
|
||||
|
||||
void QtLicense::handleUpdateButtonPress()
|
||||
{
|
||||
License license;
|
||||
bool isLoaded = license.loadFromString(m_licenseText->toPlainText().toStdString());
|
||||
if(!isLoaded)
|
||||
{
|
||||
LOG_WARNING("Failed Loading License");
|
||||
return;
|
||||
}
|
||||
license.loadPublicKeyFromString(PublicKey);
|
||||
license.print();
|
||||
|
||||
if(license.isValid())
|
||||
{
|
||||
ApplicationSettings::getInstance()->setLicenseString(license.getLicenseString());
|
||||
FilePath p("");
|
||||
ApplicationSettings::getInstance()->setLicenseCheck(license.hashLocation(p.absolute().str()));
|
||||
ApplicationSettings::getInstance()->save();
|
||||
LOG_WARNING("License saved");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING("License is not valid");
|
||||
}
|
||||
emit finished();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef QT_LICENSE_H
|
||||
#define QT_LICENSE_H
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
#include <QtWidgets/qtextedit.h>
|
||||
|
||||
#include "qt/window/QtSettingsWindow.h"
|
||||
|
||||
class QtLicense
|
||||
: public QtSettingsWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtLicense(QWidget* parent = 0);
|
||||
QSize sizeHint() const Q_DECL_OVERRIDE;
|
||||
|
||||
virtual void setup() override;
|
||||
protected:
|
||||
virtual void populateForm(QFormLayout* layout) override;
|
||||
|
||||
private slots:
|
||||
void handleCancelButtonPress();
|
||||
void handleUpdateButtonPress();
|
||||
|
||||
private:
|
||||
QPushButton* m_cancelButton;
|
||||
QPushButton* m_updateButton;
|
||||
|
||||
QTextEdit* m_licenseText;
|
||||
|
||||
};
|
||||
|
||||
#endif //QT_LICENSE_H
|
||||
@@ -338,6 +338,20 @@ void QtMainWindow::showLicenses()
|
||||
pushWindow(m_licenseWindow.get());
|
||||
}
|
||||
|
||||
void QtMainWindow::enterLicense()
|
||||
{
|
||||
if (!m_enterLicenseWindow)
|
||||
{
|
||||
m_enterLicenseWindow = std::make_shared<QtLicense>(this);
|
||||
m_enterLicenseWindow->setup();
|
||||
|
||||
connect(m_enterLicenseWindow.get(), SIGNAL(finished()), this, SLOT(popWindow()));
|
||||
connect(m_enterLicenseWindow.get(), SIGNAL(canceled()), this, SLOT(popWindow()));
|
||||
}
|
||||
|
||||
pushWindow(m_enterLicenseWindow)
|
||||
}
|
||||
|
||||
void QtMainWindow::showStartScreen()
|
||||
{
|
||||
if (!m_startScreen)
|
||||
@@ -625,10 +639,11 @@ void QtMainWindow::setupHelpMenu()
|
||||
|
||||
menu->addAction(tr("&About"), this, SLOT(about()));
|
||||
menu->addAction(tr("Licences"), this, SLOT(showLicenses()));
|
||||
|
||||
if(!isTrial())
|
||||
{
|
||||
menu->addAction(tr("Enter License..."), this, SLOT(enterLicense()));
|
||||
menu->addAction(tr("Preferences..."), this, SLOT(openSettings()));
|
||||
//Todo: Enter License Window
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "qt/window/QtProjectSetupScreen.h"
|
||||
#include "qt/window/QtAboutLicense.h"
|
||||
#include "qt/window/QtAbout.h"
|
||||
#include "qt/window/QtLicense.h"
|
||||
|
||||
class QDockWidget;
|
||||
class View;
|
||||
@@ -94,6 +95,7 @@ public slots:
|
||||
void about();
|
||||
void openSettings();
|
||||
void showLicenses();
|
||||
void enterLicense();
|
||||
|
||||
void showStartScreen();
|
||||
void newProject();
|
||||
@@ -109,7 +111,6 @@ public slots:
|
||||
void saveProject();
|
||||
void saveAsProject();
|
||||
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
void zoomIn();
|
||||
@@ -161,6 +162,7 @@ private:
|
||||
std::shared_ptr<QtProjectSetupScreen> m_newProjectDialog;
|
||||
std::shared_ptr<QtAboutLicense> m_licenseWindow;
|
||||
std::shared_ptr<QtAbout> m_aboutWindow;
|
||||
std::shared_ptr<QtLicense> m_enterLicenseWindow;
|
||||
|
||||
std::vector<QWidget*> m_windowStack;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ add_files(
|
||||
FileManagerTestSuite.h
|
||||
FilePathTestSuite.h
|
||||
FileSystemTestSuite.h
|
||||
GeneratorTestSuite.h
|
||||
GraphTestSuite.h
|
||||
LogManagerTestSuite.h
|
||||
MatrixBaseTestSuite.h
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
#include "cxxtest/TestSuite.h"
|
||||
|
||||
#include "utility/text/TextAccess.h"
|
||||
|
||||
#include "License.h"
|
||||
#include "Generator.h"
|
||||
|
||||
#include "botan_all.h"
|
||||
|
||||
class GeneratorTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
|
||||
void test_create_Keys_with_Version_and_check()
|
||||
{
|
||||
Generator generator("v0");
|
||||
generator.generateKeys();
|
||||
|
||||
std::string privateKey = generator.getPrivateKeyPEMFileAsString();
|
||||
std::string publicKey = generator.getPublicKeyPEMFileAsString();
|
||||
|
||||
TS_ASSERT_EQUALS(privateKey.size(), 1886);
|
||||
TS_ASSERT_EQUALS(publicKey.size(), 451);
|
||||
}
|
||||
|
||||
void test_load_private_Key_from_file()
|
||||
{
|
||||
Generator generator("v2");
|
||||
generator.setCustomPrivateKeyFile("./data/GeneratorTestSuite/private-v2.pem");
|
||||
bool ok = generator.loadPrivateKeyFromFile();
|
||||
|
||||
TS_ASSERT(ok);
|
||||
}
|
||||
|
||||
void test_load_private_key_from_string()
|
||||
{
|
||||
Generator generator("v0");
|
||||
bool ok = generator.loadPrivateKeyFromString(m_privateKey);
|
||||
|
||||
TS_ASSERT(ok);
|
||||
}
|
||||
|
||||
void test_create_license_and_validate()
|
||||
{
|
||||
Generator generator("v2");
|
||||
generator.generateKeys();
|
||||
|
||||
generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString());
|
||||
License license;
|
||||
license.create("TestUser", "v2", generator.getPrivateKey());
|
||||
license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString());
|
||||
|
||||
TS_ASSERT_EQUALS(license.getOwnerLine(), "TestUser");
|
||||
TS_ASSERT_EQUALS(license.getLicenseTypeLine(), "Single User License");
|
||||
TS_ASSERT_EQUALS(license.getVersion(), "v2");
|
||||
TS_ASSERT(license.isValid());
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_privateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n"
|
||||
"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\n"
|
||||
"-----END ENCRYPTED PRIVATE KEY-----";
|
||||
std::string m_publicKey = "-----BEGIN PUBLIC KEY-----\n"
|
||||
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAugYah7LOU0ssdSnyDA8h\n"
|
||||
"nOeW2lwE+NmZGxIKnqZKYNePY7Tg0c1pI0lfgJ2WYtxbubDFNDYk6bJF6mFg3jjN\n"
|
||||
"gCdocj6pyyibIISbRst+gl/1FwI8vbIkfkJBoZtftO5mKVBbO5mmrxm32fDQs1vo\n"
|
||||
"zgVxcWx3LXW87pzdQQYRACdkLSxPd+ADs+KNv6UxlOEvucDaenX3ckl3HdcWruL8\n"
|
||||
"xdYoM7z/C+PRShSGvY3wB7Y6A5IcdBmzsTR6xayCmTzzW83dmFzjCX5DSOJLHxq7\n"
|
||||
"+Fs26xZU83P1boX7eg4TjMViTxJwsCCW/2wfsZAoF0cSYCxhrkSdMHroH7Edz1PM\n"
|
||||
"fwIDAQAB\n"
|
||||
"-----END PUBLIC KEY-----\n";
|
||||
};
|
||||
Reference in New Issue
Block a user