From 5008ab76fe7cae9b3e0cc9976a50426f4911eaac Mon Sep 17 00:00:00 2001 From: Ernest Wilkerson Date: Wed, 2 Jun 2021 15:59:26 -0700 Subject: [PATCH 1/2] Add the ability create issuing authority instances without specifying a private key. Useful for validation-only scenarios. --- license++/issuing-authority.h | 8 +++++-- src/issuing-authority.cc | 44 ++++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/license++/issuing-authority.h b/license++/issuing-authority.h index f6cd126..261a0d6 100644 --- a/license++/issuing-authority.h +++ b/license++/issuing-authority.h @@ -23,7 +23,10 @@ class IssuingAuthority { public: IssuingAuthority(const std::string& id, const std::string& name, - const std::string& keypair, unsigned int maxValidity, + const std::string& keyPair, unsigned int maxValidity, + bool active = true); + IssuingAuthority(const std::string& id, const std::string& name, + const std::string& privateKey, const std::string& publicKey, unsigned int maxValidity, bool active = true); IssuingAuthority(const IssuingAuthority&); @@ -82,7 +85,8 @@ class IssuingAuthority private: std::string m_id; std::string m_name; - std::string m_keypair; + std::string m_privateKey; + std::string m_publicKey; bool m_active; unsigned int m_maxValidity; }; diff --git a/src/issuing-authority.cc b/src/issuing-authority.cc index 292d9a2..1312548 100644 --- a/src/issuing-authority.cc +++ b/src/issuing-authority.cc @@ -23,12 +23,28 @@ using namespace licensepp; IssuingAuthority::IssuingAuthority(const std::string& id, const std::string& name, - const std::string& keypair, + const std::string& keyPair, + unsigned int maxValidity, + bool active) : IssuingAuthority::IssuingAuthority(id, name, "", "", maxValidity) { + const auto separatorPos = keyPair.find(":"); + if (separatorPos == std::string::npos) { + throw LicenseException("Issuing authority could not be loaded. Invalid keypair"); + } + + m_privateKey = Base64::decode(keyPair.substr(0, separatorPos)); + m_publicKey = Base64::decode(keyPair.substr(separatorPos + 1)); +} + +IssuingAuthority::IssuingAuthority(const std::string& id, + const std::string& name, + const std::string& privateKey, + const std::string& publicKey, unsigned int maxValidity, bool active) : m_id(id), m_name(name), - m_keypair(keypair), + m_privateKey(privateKey), + m_publicKey(publicKey), m_active(active), m_maxValidity(maxValidity) { @@ -42,7 +58,8 @@ IssuingAuthority::IssuingAuthority(const std::string& id, IssuingAuthority::IssuingAuthority(const IssuingAuthority& other): m_id(other.m_id), m_name(other.m_name), - m_keypair(other.m_keypair), + m_privateKey(other.m_privateKey), + m_publicKey(other.m_publicKey), m_active(other.m_active), m_maxValidity(other.m_maxValidity) { @@ -52,7 +69,8 @@ IssuingAuthority& IssuingAuthority::operator=(IssuingAuthority other) { std::swap(m_id, other.m_id); std::swap(m_name, other.m_name); - std::swap(m_keypair, other.m_keypair); + std::swap(m_privateKey, other.m_privateKey); + std::swap(m_publicKey, other.m_publicKey); std::swap(m_active, other.m_active); std::swap(m_maxValidity, other.m_maxValidity); @@ -100,13 +118,8 @@ License IssuingAuthority::issue(const std::string& licensee, throw LicenseException("Failed to issue the license; " + std::string(e.what())); } } - // issuing authority signs this license - auto separatorPos = m_keypair.find(":"); - if (separatorPos == std::string::npos) { - throw LicenseException("Issuing authority could not be loaded. Invalid keypair"); - } - - const RSA::PrivateKey key = RSA::loadPrivateKey(Base64::decode(m_keypair.substr(0, separatorPos)), secret); + + const RSA::PrivateKey key = RSA::loadPrivateKey(m_privateKey, secret); try { license.setAuthoritySignature(RSA::sign(license.raw(), key, secret)); @@ -128,14 +141,7 @@ bool IssuingAuthority::validate(const License* license, { bool result = false; try { - - // issuing authority signs this license - auto separatorPos = m_keypair.find(":"); - if (separatorPos == std::string::npos) { - throw LicenseException("Issuing authority could not be loaded. Invalid keypair"); - } - - RSA::PublicKey key = RSA::loadPublicKey(Base64::decode(m_keypair.substr(separatorPos + 1))); + RSA::PublicKey key = RSA::loadPublicKey(m_publicKey); result = RSA::verify(license->raw(), license->authoritySignature(), key); if (!result) { From ef821e58000e9173c563529d038bf81468931ad4 Mon Sep 17 00:00:00 2001 From: Ernest Wilkerson Date: Wed, 2 Jun 2021 20:16:15 -0700 Subject: [PATCH 2/2] Expect Base64 input in all cases. Handle empty base 64 encoding/decoding --- src/crypto/base64.cc | 2 ++ src/issuing-authority.cc | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/crypto/base64.cc b/src/crypto/base64.cc index 013c65a..95bf76d 100644 --- a/src/crypto/base64.cc +++ b/src/crypto/base64.cc @@ -15,10 +15,12 @@ using namespace licensepp; std::string Base64::decode(const std::string& encoded) { + if (encoded.empty()) return encoded; return Ripe::base64Decode(encoded); } std::string Base64::encode(const std::string& raw) { + if (raw.empty()) return raw; return Ripe::base64Encode(raw); } diff --git a/src/issuing-authority.cc b/src/issuing-authority.cc index 1312548..98e1ffc 100644 --- a/src/issuing-authority.cc +++ b/src/issuing-authority.cc @@ -43,8 +43,8 @@ IssuingAuthority::IssuingAuthority(const std::string& id, bool active) : m_id(id), m_name(name), - m_privateKey(privateKey), - m_publicKey(publicKey), + m_privateKey(Base64::decode(privateKey)), + m_publicKey(Base64::decode(publicKey)), m_active(active), m_maxValidity(maxValidity) {