[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