test/WopiProofTests.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++------ wsd/ProofKey.cpp | 34 +++++++++++++++------- wsd/ProofKey.hpp | 3 + 3 files changed, 92 insertions(+), 19 deletions(-)
New commits: commit 668007544b89d9cb29aa8a62405de95cb7a7c02f Author: Michael Meeks <michael.me...@collabora.com> AuthorDate: Wed Apr 8 21:39:54 2020 +0100 Commit: Michael Meeks <michael.me...@collabora.com> CommitDate: Wed Apr 8 23:20:55 2020 +0200 Proof: generate our own key, and verify our own signatures. Change-Id: If805c89a3b6618d6e34e7421b20077c4f0a48cb3 Reviewed-on: https://gerrit.libreoffice.org/c/online/+/91940 Tested-by: Michael Meeks <michael.me...@collabora.com> Reviewed-by: Michael Meeks <michael.me...@collabora.com> diff --git a/test/WopiProofTests.cpp b/test/WopiProofTests.cpp index 6ad0b4268..446ec07b6 100644 --- a/test/WopiProofTests.cpp +++ b/test/WopiProofTests.cpp @@ -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 @@ -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() @@ -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()); @@ -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://u...@short.com: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); diff --git a/wsd/ProofKey.cpp b/wsd/ProofKey.cpp index b78499da0..01817ed8f 100644 --- a/wsd/ProofKey.cpp +++ b/wsd/ProofKey.cpp @@ -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(); @@ -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() diff --git a/wsd/ProofKey.hpp b/wsd/ProofKey.hpp index 6fc29eb84..9ac3c7b1c 100644 --- a/wsd/ProofKey.hpp +++ b/wsd/ProofKey.hpp @@ -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; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits