[Libreoffice-commits] online.git: wsd/ProofKey.cpp

Mike Kaganski (via logerrit) logerrit at kemper.freedesktop.org
Tue Jan 21 18:28:50 UTC 2020


 wsd/ProofKey.cpp |  101 +++++++++++++++++++++++++++++++++----------------------
 1 file changed, 61 insertions(+), 40 deletions(-)

New commits:
commit 0c0510cccf57688d6e7c8f7f17ee890095d1d931
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Tue Jan 21 18:35:01 2020 +0300
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Tue Jan 21 19:28:32 2020 +0100

    Implement proper proof-key value attribute
    
    Change-Id: I3f2ad960ce6d3dad4d0b064492355b5643f345c8
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/87148
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/wsd/ProofKey.cpp b/wsd/ProofKey.cpp
index 118724def..3fe2af455 100644
--- a/wsd/ProofKey.cpp
+++ b/wsd/ProofKey.cpp
@@ -12,10 +12,12 @@
 #include "ProofKey.hpp"
 #include "LOOLWSD.hpp"
 
+#include <algorithm>
 #include <cassert>
 #include <chrono>
 #include <cstdlib>
 #include <memory>
+#include <vector>
 
 #include <Poco/Base64Decoder.h>
 #include <Poco/Base64Encoder.h>
@@ -40,6 +42,58 @@
 
 namespace{
 
+std::vector<unsigned char> getBytesLE(const unsigned char* bytesInSystemOrder, const size_t n)
+{
+    std::vector<unsigned char> ret(n);
+#if !defined __BYTE_ORDER__
+    static_assert(false, "Byte order is not detected on this platform!");
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+    std::copy_n(bytesInSystemOrder, n, ret.begin());
+#else
+    std::copy_n(bytesInSystemOrder, n, ret.rbegin());
+#endif
+    return ret;
+}
+
+// Returns a number as vector of bytes (little-endian)
+template <typename T>
+std::vector<unsigned char> getBytesLE(const T& x)
+{
+    return getBytesLE(reinterpret_cast<const unsigned char*>(&x), sizeof(x));
+}
+
+// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-mqqb/ade9efde-3ec8-4e47-9ae9-34b64d8081bb
+std::vector<unsigned char> RSA2CapiBlob(const std::vector<unsigned char>& modulus,
+                                        const std::vector<unsigned char>& exponent)
+{
+    std::vector<unsigned char> capiBlob = {
+        0x06, 0x02, 0x00, 0x00,
+        0x00, 0xA4, 0x00, 0x00,
+        0x52, 0x53, 0x41, 0x31,
+    };
+    // modulus size in bits - 4 bytes (little-endian)
+    const auto bitLen = getBytesLE<std::uint32_t>(modulus.size() * 8);
+    capiBlob.reserve(capiBlob.size() + bitLen.size() + exponent.size() + modulus.size());
+    std::copy(bitLen.begin(), bitLen.end(), std::back_inserter(capiBlob));
+    // exponent - 4 bytes (little-endian)
+    std::copy(exponent.rbegin(), exponent.rend(), std::back_inserter(capiBlob));
+    // modulus (little-endian)
+    std::copy(modulus.rbegin(), modulus.rend(), std::back_inserter(capiBlob));
+    return capiBlob;
+}
+
+std::string BytesToBase64(const std::vector<unsigned char>& bytes)
+{
+    std::ostringstream oss;
+    // The signature generated contains CRLF line endings.
+    // Use a line ending converter to remove these CRLF
+    Poco::OutputLineEndingConverter lineEndingConv(oss, "");
+    Poco::Base64Encoder encoder(lineEndingConv);
+    encoder << std::string(bytes.begin(), bytes.end());
+    encoder.close();
+    return oss.str();
+}
+
 class Proof {
 public:
     Proof();
@@ -84,46 +138,13 @@ Proof::Proof()
 {
     if (m_pKey)
     {
-        {
-            // TODO: This is definitely not correct at the moment. The proof key must be
-            // base64-encoded blob in "unmanaged Microsoft Cryptographic API (CAPI)" format
-            // (as .Net's RSACryptoServiceProvider::ExportCspBlob returns).
-            std::ostringstream oss;
-            Poco::OutputLineEndingConverter lineEndingConv(oss, "");
-            m_pKey->save(&lineEndingConv);
-            std::string sKey = oss.str();
-            const std::string sBegin = "-----BEGIN RSA PUBLIC KEY-----";
-            const std::string sEnd = "-----END RSA PUBLIC KEY-----";
-            auto pos = sKey.find(sBegin);
-            if (pos != std::string::npos)
-                sKey = sKey.substr(pos + sBegin.length());
-            pos = sKey.find(sEnd);
-            if (pos != std::string::npos)
-                sKey = sKey.substr(0, pos);
-            m_aAttribs.emplace_back("value", sKey);
-        }
-        {
-            std::ostringstream oss;
-            // The signature generated contains CRLF line endings.
-            // Use a line ending converter to remove these CRLF
-            Poco::OutputLineEndingConverter lineEndingConv(oss, "");
-            Poco::Base64Encoder encoder(lineEndingConv);
-            const auto m = m_pKey->modulus();
-            encoder << std::string(m.begin(), m.end());
-            encoder.close();
-            m_aAttribs.emplace_back("modulus", oss.str());
-        }
-        {
-            std::ostringstream oss;
-            // The signature generated contains CRLF line endings.
-            // Use a line ending converter to remove these CRLF
-            Poco::OutputLineEndingConverter lineEndingConv(oss, "");
-            Poco::Base64Encoder encoder(lineEndingConv);
-            const auto e = m_pKey->encryptionExponent();
-            encoder << std::string(e.begin(), e.end());
-            encoder.close();
-            m_aAttribs.emplace_back("exponent", oss.str());
-        }
+        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));
     }
 }
 


More information about the Libreoffice-commits mailing list