build,logic : Key/License Generator

Generator using the Botan Cyrptography library
This commit is contained in:
Andreas Stallinger
2016-01-18 11:42:31 +01:00
committed by Eberhard Graether
parent 743f91e882
commit 23257a3071
31 changed files with 1260 additions and 21 deletions
+8
View File
@@ -0,0 +1,8 @@
add_files(
GEN_FILES
Generator.cpp
Generator.h
License.cpp
License.h
)
+155
View File
@@ -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();
}
+48
View File
@@ -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
+319
View File
@@ -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);
}
+66
View File
@@ -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
+93
View File
@@ -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;
}
-1
View File
@@ -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());
+20
View File
@@ -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);
}
+7
View File
@@ -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&);
+2
View File
@@ -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
+2 -6
View File
@@ -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();
}
-2
View File
@@ -18,8 +18,6 @@ public:
virtual void setup() override;
private slots:
void handleCloseButtonPress();
void handleCancelButtonPress();
void handleUpdateButtonPress();
};
+83
View File
@@ -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();
}
+35
View File
@@ -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
+16 -1
View File
@@ -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
}
}
+3 -1
View File
@@ -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;
+1
View File
@@ -16,6 +16,7 @@ add_files(
FileManagerTestSuite.h
FilePathTestSuite.h
FileSystemTestSuite.h
GeneratorTestSuite.h
GraphTestSuite.h
LogManagerTestSuite.h
MatrixBaseTestSuite.h
+99
View File
@@ -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"
"MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQMWEDuADurEQ4T8kJO\n"
"AgMDDUACASAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEGNDHYI3xozW5JBg\n"
"pOLkhIMEggTQPwClVPQbk+AVqOAXndQqCs0Ad+eihbekCHt5zkRrYl6JbLq9fvfs\n"
"kGgn1j7xtFZflcZimlLaao8pLWybJfa3xGSJnlYrJsGVMlmKJw/ee3fZG7y4/Tgo\n"
"FytAIP51He4YAZ+4fOXyOoAT0+k2DBekZHeMADX7eXVpCLQXuoQpECvf2IPd/de4\n"
"QKS12FRTd7Hkq7DwYs5D7aBizftcsB6FDqwKvvrheglMHfMt3/ChV8u3F8Zuqnh5\n"
"S1NVl2b8geAnYWLEfN/V8SDu00heVHq+z2CIQrvonsTwN1c9ppgMC7/udcr4GEKU\n"
"kqn/2h1sVRdlCxHf9p2nKRdOUXbSgQi16dKnEim3j3QCLVeNeX5Z6Tkb5pJA397i\n"
"mbL0ihdUvbVcPMG9Rh8NONY+MkE4NKye+NHzWjsd+egaeA79qy/Xd4cJRG7GFy68\n"
"pBWhf/xNpkhXJNV+O/KLszZG6f/UNDPJHovTp47aetD2/EqasvuYkPpapfYuqiZh\n"
"3vtNlgL1uNIN/TjoSaut5+ifJonJnQBrMQdWLTN6I8/lZFfxZB4jLkHffLS/zTA+\n"
"tPLxBcfZiec9dJDmuJ+P55D/3E+p6CL++yw15cgBNPFHrvfatikHvQXkRJl03S6Q\n"
"FvrBmbjWKwT+iSZAvJrdkCeFO53CYA3tJ23GtG9pxBHP+VFyJSBu7MukjcCEMSbU\n"
"HduNcsIIo8/p/X/CXYxJGYIfbrqz0n4z0QkZvCtyJoexoqqjTGclWoN3//j8lenL\n"
"SbrPCwLEn1coGr6rx97LHDBjdR1WouWeGkQOyMF/dC70p4QyE3Ru0cbhsjAWeo7P\n"
"HpGgQHJllJBFM9OkymRD32NnTCtr5Vu6epfiAsi16rfg1j1H9f0hnPbfULx+Q2WM\n"
"sCzuUbKUcjRNXOhwDxQXGVrMXEjRzJKmqy2kpMFX/v38iKfqIx+pHMOs+/+ESwwp\n"
"frKZ2mUwa7DdDv6fZwPUPtZk/6HyqiDoJcoiN05IxdPt6SXGPsseQWcwTdiHhDX2\n"
"3YsTJK0O/CAf/ouqWQiZMAifTZtalTArTvTtlTE7TpAT3I0OmwNG/nI1v/orHBbZ\n"
"M7sa9mlBDMzE4rTHIYMOttNKLxkXRChjgO2JfFDLxscSMw8wsrbGTbKh7VGFgg7Q\n"
"Tj6KAGPiU7WbaXiIhO4adgYp3Bpbo15BhhO5bdaYzxBjOhYw1ShLEgBOC7MsOt3N\n"
"8oChFJB1Gls5+RU6Ef27az+RE6uSumToT1HKgYDYX1TN68WWjT7Pa0lUMtZ4Bv1f\n"
"rXMH8igPXg62kzh/hjnEtl8y2+ySAs7RnZ0vUywaKcI0Tu5tqJSLtXSfJKAPmmzE\n"
"QYsg70kpufXccznTYvLSbM99FIbC6s+cSkJ43Ku4dwbEal+9FfqK639i2X9hdsLc\n"
"bYXIb0Fguo2IbWruBeSIc8lukOKCOVjanVZhfOCev8ye/Wz+SS8zbEixWZMzMCzC\n"
"if4dF/CUHnJK32IVlqKr9XGEe8ympqwMqN0eOdJn8IB+BQGCcaF6805D3R/OG4FU\n"
"hedhIvg1cODtoi8ri41Pz7o1x9Ia0zZr7oxhQuSgHiTfRfFN0xhCFZ+sIfGNpgUs\n"
"54IZGQlI0nQHOK8h2NI0wp3uo+fDEjjVIjQxINOSBa5awSReBpBUW2I=\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";
};