Skip to content

Commit

Permalink
Proof: generate our own key, and verify our own signatures.
Browse files Browse the repository at this point in the history
Change-Id: If805c89a3b6618d6e34e7421b20077c4f0a48cb3
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/91940
Tested-by: Michael Meeks <[email protected]>
Reviewed-by: Michael Meeks <[email protected]>
  • Loading branch information
mmeeks committed Apr 8, 2020
1 parent d7f55b4 commit 6680075
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 19 deletions.
74 changes: 65 additions & 9 deletions test/WopiProofTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <openssl/bn.h>
#include <openssl/pem.h>
#include <openssl/buffer.h>

#include <openssl/opensslv.h>

/// Delta unit-tests.
class WopiProofTests : public CPPUNIT_NS::TestFixture
Expand All @@ -31,17 +31,26 @@ class WopiProofTests : public CPPUNIT_NS::TestFixture

CPPUNIT_TEST(testCapiBlob);
CPPUNIT_TEST(testExistingProof);
CPPUNIT_TEST(testOurProof);

CPPUNIT_TEST_SUITE_END();

void testCapiBlob();
void testExistingProof();
void testOurProof();

BIGNUM *Base64ToNum(const std::string &str)
{
std::vector<unsigned char> vec = Proof::Base64ToBytes(str);
return BN_bin2bn(&vec[0], vec.size(), nullptr);
}

void verifySignature(const std::string &access,
const std::string &uri,
uint64_t ticks,
const std::string &discoveryModulus,
const std::string &discoveryExponent,
const std::string &msgProof);
};

void WopiProofTests::testCapiBlob()
Expand All @@ -55,21 +64,24 @@ void WopiProofTests::testCapiBlob()
LOK_ASSERT_EQUAL(capiEncoded, std::string("BgIAAACkAABSU0ExAAgAAAEAAQDFEthb5dkE+fGnJgsmY3IXmoFxj1cOwVYLpLNTEksnVRzbXcPfaSl/kFxn5b4QajhH1sTtXECZY6ZUyiDi1NG5ukFc9Fppgt0ywnuJqNBRWPfvLTOaVZRTtr8X8hqL+dPldOI3qFUW2zF6DEsAO9y74l3s6MqNjawCME5X0jb28TOrbXXsDfIGLEN3VBFO3wyhlRZKOmR9ZiqxQbpOz0Ltgv3HYci9OVN9c8YYV5T+fHI0Wtxg4F9lJHlB6MHPV9seVqr4ieM027NG89LhHm9BJEtceII09JgmkwLFUB/s2YGirUwZewk0efw1GL861PE7Vjdn2bIdmGSCRfFQlnPQ"));
}

void WopiProofTests::testExistingProof()
void WopiProofTests::verifySignature(const std::string &access,
const std::string &uri,
uint64_t ticks,
const std::string &discoveryModulus,
const std::string &discoveryExponent,
const std::string &msgProofStr)
{
std::vector<unsigned char> proof = Proof::GetProof(
"yZhdN1qgywcOQWhyEMVpB6NE3pvBksvcLXsrFKXNtBeDTPW%2fu62g2t%2fOCWSlb3jUGaz1zc%2fzOzbNgAredLdhQI1Q7sPPqUv2owO78olmN74DV%2fv52OZIkBG%2b8jqjwmUobcjXVIC1BG9g%2fynMN0itZklL2x27Z2imCF6xELcQUuGdkoXBj%2bI%2bTlKM", // access token
"https://contoso.com/wopi/files/vHxYyRGM8VfmSGwGYDBMIQPzuE+sSC6kw+zWZw2Nyg?access_token=yZhdN1qgywcOQWhyEMVpB6NE3pvBksvcLXsrFKXNtBeDTPW%2fu62g2t%2fOCWSlb3jUGaz1zc%2fzOzbNgAredLdhQI1Q7sPPqUv2owO78olmN74DV%2fv52OZIkBG%2b8jqjwmUobcjXVIC1BG9g%2fynMN0itZklL2x27Z2imCF6xELcQUuGdkoXBj%2bI%2bTlKM", // uri
UINT64_C(635655897610773532)); // ticks
#if OPENSSL_VERSION_NUMBER > 0x10100000L
std::vector<unsigned char> proof = Proof::GetProof(access, uri, ticks);

BIGNUM *modulus = Base64ToNum("0HOWUPFFgmSYHbLZZzdWO/HUOr8YNfx5NAl7GUytooHZ7B9QxQKTJpj0NIJ4XEskQW8e4dLzRrPbNOOJ+KpWHttXz8HoQXkkZV/gYNxaNHJ8/pRXGMZzfVM5vchhx/2C7ULPTrpBsSpmfWQ6ShaVoQzfThFUd0MsBvIN7HVtqzPx9jbSV04wAqyNjcro7F3iu9w7AEsMejHbFlWoN+J05dP5ixryF7+2U5RVmjMt7/dYUdCoiXvCMt2CaVr0XEG6udHU4iDKVKZjmUBc7cTWRzhqEL7lZ1yQfylp38Nd2xxVJ0sSU7OkC1bBDlePcYGaF3JjJgsmp/H5BNnlW9gSxQ==");
BIGNUM *exponent = Base64ToNum("AQAB");
BIGNUM *modulus = Base64ToNum(discoveryModulus);
BIGNUM *exponent = Base64ToNum(discoveryExponent);

RSA *rsa = RSA_new();
LOK_ASSERT(rsa != nullptr);
LOK_ASSERT_EQUAL(1, RSA_set0_key(rsa, modulus, exponent, nullptr));

std::vector<unsigned char> msgProof = Proof::Base64ToBytes("IflL8OWCOCmws5qnDD5kYMraMGI3o+T+hojoDREbjZSkxbbx7XIS1Av85lohPKjyksocpeVwqEYm9nVWfnq05uhDNGp2MsNyhPO9unZ6w25Rjs1hDFM0dmvYx8wlQBNZ/CFPaz3inCMaaP4PtU85YepaDccAjNc1gikdy3kSMeG1XZuaDixHvMKzF/60DMfLMBIu5xP4Nt8i8Gi2oZs4REuxi6yxOv2vQJQ5+8Wu2Olm8qZvT4FEIQT9oZAXebn/CxyvyQv+RVpoU2gb4BreXAdfKthWF67GpJyhr+ibEVDoIIolUvviycyEtjsaEBpOf6Ne/OLRNu98un7WNDzMTQ==");
std::vector<unsigned char> msgProof = Proof::Base64ToBytes(msgProofStr);

Poco::Crypto::DigestEngine digestEngine("SHA256");
digestEngine.update(proof.data(), proof.size());
Expand All @@ -81,6 +93,50 @@ void WopiProofTests::testExistingProof()
rsa));

RSA_free(rsa);
#else
(void)access; (void)uri; (void)ticks;
(void)discoveryModulus; (void)discoveryExponent;
(void)msgProofStr;
std::cerr << "OpenSSL too old to verify keys easily " << OPENSSL_VERSION_TEXT << " needs to be 1.1.0 at least\n";
#endif
}

void WopiProofTests::testExistingProof()
{
verifySignature(
"yZhdN1qgywcOQWhyEMVpB6NE3pvBksvcLXsrFKXNtBeDTPW%2fu62g2t%2fOCWSlb3jUGaz1zc%2fzOzbNgAredLdhQI1Q7sPPqUv2owO78olmN74DV%2fv52OZIkBG%2b8jqjwmUobcjXVIC1BG9g%2fynMN0itZklL2x27Z2imCF6xELcQUuGdkoXBj%2bI%2bTlKM", // access token
"https://contoso.com/wopi/files/vHxYyRGM8VfmSGwGYDBMIQPzuE+sSC6kw+zWZw2Nyg?access_token=yZhdN1qgywcOQWhyEMVpB6NE3pvBksvcLXsrFKXNtBeDTPW%2fu62g2t%2fOCWSlb3jUGaz1zc%2fzOzbNgAredLdhQI1Q7sPPqUv2owO78olmN74DV%2fv52OZIkBG%2b8jqjwmUobcjXVIC1BG9g%2fynMN0itZklL2x27Z2imCF6xELcQUuGdkoXBj%2bI%2bTlKM", // uri
UINT64_C(635655897610773532), // ticks
"0HOWUPFFgmSYHbLZZzdWO/HUOr8YNfx5NAl7GUytooHZ7B9QxQKTJpj0NIJ4XEskQW8e4dLzRrPbNOOJ+KpWHttXz8HoQXkkZV/gYNxaNHJ8/pRXGMZzfVM5vchhx/2C7ULPTrpBsSpmfWQ6ShaVoQzfThFUd0MsBvIN7HVtqzPx9jbSV04wAqyNjcro7F3iu9w7AEsMejHbFlWoN+J05dP5ixryF7+2U5RVmjMt7/dYUdCoiXvCMt2CaVr0XEG6udHU4iDKVKZjmUBc7cTWRzhqEL7lZ1yQfylp38Nd2xxVJ0sSU7OkC1bBDlePcYGaF3JjJgsmp/H5BNnlW9gSxQ==", // modulus
"AQAB", // exponent
"IflL8OWCOCmws5qnDD5kYMraMGI3o+T+hojoDREbjZSkxbbx7XIS1Av85lohPKjyksocpeVwqEYm9nVWfnq05uhDNGp2MsNyhPO9unZ6w25Rjs1hDFM0dmvYx8wlQBNZ/CFPaz3inCMaaP4PtU85YepaDccAjNc1gikdy3kSMeG1XZuaDixHvMKzF/60DMfLMBIu5xP4Nt8i8Gi2oZs4REuxi6yxOv2vQJQ5+8Wu2Olm8qZvT4FEIQT9oZAXebn/CxyvyQv+RVpoU2gb4BreXAdfKthWF67GpJyhr+ibEVDoIIolUvviycyEtjsaEBpOf6Ne/OLRNu98un7WNDzMTQ=="); // message proof
}

void WopiProofTests::testOurProof()
{
Proof gen(Proof::Type::CreateKey);

const VecOfStringPairs& discovery = gen.GetProofKeyAttributes();
int len = discovery.size();
LOK_ASSERT_EQUAL(3, len);
LOK_ASSERT_EQUAL(discovery[0].first, std::string("value"));
LOK_ASSERT_EQUAL(discovery[1].first, std::string("modulus"));
std::string modulus = discovery[1].second;
LOK_ASSERT_EQUAL(discovery[2].first, std::string("exponent"));
std::string exponent = discovery[2].second;

std::string access_token = "!££$%£^$-!---~@@{}OP";
std::string uri = "https://[email protected]:12345/blah?query_string=foo";
VecOfStringPairs pairs = gen.GetProofHeaders(access_token, uri);
len = pairs.size();
LOK_ASSERT_EQUAL(2, len);
LOK_ASSERT_EQUAL(pairs[0].first, std::string("X-WOPI-TimeStamp"));
std::string timestamp = pairs[0].second;
LOK_ASSERT_EQUAL(pairs[1].first, std::string("X-WOPI-Proof"));
std::string proof = pairs[1].second;

uint64_t ticks = std::stoull(timestamp.c_str(), nullptr, 10);
verifySignature(access_token, uri, ticks, modulus, exponent, proof);
}

CPPUNIT_TEST_SUITE_REGISTRATION(WopiProofTests);
Expand Down
34 changes: 24 additions & 10 deletions wsd/ProofKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,29 @@ std::vector<unsigned char> Proof::Base64ToBytes(const std::string &str)
return vec;
}

void Proof::initialize()
{
if (m_pKey)
{
const auto m = m_pKey->modulus();
const auto e = m_pKey->encryptionExponent();
const auto capiBlob = RSA2CapiBlob(m, e);

m_aAttribs.emplace_back("value", BytesToBase64(capiBlob));
m_aAttribs.emplace_back("modulus", BytesToBase64(m));
m_aAttribs.emplace_back("exponent", BytesToBase64(e));
}

}

Proof::Proof(Type)
: m_pKey(new Poco::Crypto::RSAKey(
Poco::Crypto::RSAKey::KeyLength::KL_2048,
Poco::Crypto::RSAKey::Exponent::EXP_LARGE))
{
initialize();
}

Proof::Proof()
: m_pKey([]() -> Poco::Crypto::RSAKey* {
const auto keyPath = ProofKeyPath();
Expand Down Expand Up @@ -138,16 +161,7 @@ Proof::Proof()
return nullptr;
}())
{
if (m_pKey)
{
const auto m = m_pKey->modulus();
const auto e = m_pKey->encryptionExponent();
const auto capiBlob = RSA2CapiBlob(m, e);

m_aAttribs.emplace_back("value", BytesToBase64(capiBlob));
m_aAttribs.emplace_back("modulus", BytesToBase64(m));
m_aAttribs.emplace_back("exponent", BytesToBase64(e));
}
initialize();
}

std::string Proof::ProofKeyPath()
Expand Down
3 changes: 3 additions & 0 deletions wsd/ProofKey.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class WopiProofTests;

class Proof {
friend class WopiProofTests;
void initialize();
enum Type { CreateKey };
Proof(Type);
public:
Proof();
VecOfStringPairs GetProofHeaders(const std::string& access_token, const std::string& uri) const;
Expand Down

0 comments on commit 6680075

Please sign in to comment.