[Libreoffice-commits] core.git: Branch 'private/thb/gpg4libre2' - 5 commits - comphelper/Library_comphelper.mk comphelper/source offapi/com package/inc package/source sfx2/source xmlsecurity/source

Thorsten Behrens thorsten.behrens at cib.de
Fri Nov 24 00:44:03 UTC 2017


Rebased ref, commits from common ancestor:
commit fe67612f8d40dd76b7bec105e8abd1704885a50c
Author: Thorsten Behrens <thorsten.behrens at cib.de>
Date:   Thu Nov 23 22:18:09 2017 +0100

    gpg4libre: find keymanager executable on Windows
    
    Change-Id: If93c06ad90d708b0fbaf476bda6fdb902bd77b1e

diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index ba726e04d0a5..42ca15d05faf 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -468,9 +468,17 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, Button*, void)
 
 IMPL_STATIC_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, Button*, void)
 {
-    const OUString aGUIServers[] = {  OUString("kleopatra"), OUString("seahorse"),  OUString("gpa"), OUString("kgpg") };
-    // FIXME: the same for Windows + registry search for gpg4win
+#ifdef _WIN32
+    // FIXME: call GpgME::dirInfo("bindir") somewhere in
+    // SecurityEnvironmentGpg or whatnot
+    // FIXME: perhaps poke GpgME for uiserver, and hope it returns something useful?
+    const OUString aGUIServers[] = { OUString("kleopatra.exe"), OUString("launch-gpa.exe"), OUString("gpa.exe"),
+                                     OUString("bin\\kleopatra.exe"), OUString("bin\\launch-gpa.exe"), OUString("bin\\gpa.exe") };
+    const char* cPath = "C:\\Program Files (x86)\\GNU\\GnuPG";
+#else
+    const OUString aGUIServers[] = { OUString("kleopatra"), OUString("seahorse"),  OUString("gpa"), OUString("kgpg") };
     const char* cPath = getenv("PATH");
+#endif
 
     if (cPath)
     {
commit f7eb83dda30a81e12e4220f231882a3a1ad4f9af
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date:   Mon Aug 21 09:24:32 2017 +0200

    demo hack: list all certificates
    
    Change-Id: Ibc678cf9c0c8a0a8e8198516b8cbdebcc977c185

diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.cxx b/xmlsecurity/source/gpg/SecurityEnvironment.cxx
index 2bbcf8ddf79b..ba21794097d5 100644
--- a/xmlsecurity/source/gpg/SecurityEnvironment.cxx
+++ b/xmlsecurity/source/gpg/SecurityEnvironment.cxx
@@ -119,7 +119,7 @@ Reference< XCertificate > SecurityEnvironmentGpg::getCertificate( const OUString
     if(xmlSecBase64Decode(strKeyId, const_cast<xmlSecByte*>(strKeyId), xmlStrlen(strKeyId)) < 0)
         throw RuntimeException("Base64 decode failed");
 
-    m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
+    m_ctx->addKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
     GpgME::Error err = m_ctx->startKeyListing("", false);
     while (!err) {
         GpgME::Key k = m_ctx->nextKey(err);
commit c40ea03a18d875f031c7662f64516eaad9e68b99
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date:   Sun Aug 20 03:43:20 2017 +0200

    gpg4libre: pass down OpenPGP encryption info to package code
    
    Change-Id: Ie67c9927efdad4a027b14ed6a37a188b85eaf077

diff --git a/package/inc/PackageConstants.hxx b/package/inc/PackageConstants.hxx
index df7bebcf6bd4..78736736d05a 100644
--- a/package/inc/PackageConstants.hxx
+++ b/package/inc/PackageConstants.hxx
@@ -34,6 +34,10 @@ const sal_Int32 n_ConstDigestDecrypt = 1056; // 1024 + 32
 #define PKG_MNFST_VERSION     1 //Version
 #define PKG_MNFST_MEDIATYPE   2 //MediaType
 
+#define PKG_MNFST_KEYID       3 //PGP Key ID
+#define PKG_MNFST_KEYPACKET   4 //PGP Key packet
+#define PKG_MNFST_CIPHERVAL   5 //PGP session key cipher value
+
 #define PKG_MNFST_INIVECTOR   3 //InitialisationVector
 #define PKG_MNFST_SALT        4 //Salt
 #define PKG_MNFST_ITERATION   5 //IterationCount
@@ -44,13 +48,15 @@ const sal_Int32 n_ConstDigestDecrypt = 1056; // 1024 + 32
 #define PKG_MNFST_DIGESTALG  10 //DigestAlgorithm
 #define PKG_MNFST_DERKEYSIZE 11 //DerivedKeySize
 
-#define PKG_SIZE_NOENCR_MNFST 3
-#define PKG_SIZE_ENCR_MNFST   12
+#define PKG_SIZE_NOENCR_MNFST    3
+#define PKG_SIZE_GPG_ENCR_MNFST  6
+#define PKG_SIZE_ENCR_MNFST      12
 
 // the properties related constants
 #define ENCRYPTION_KEY_PROPERTY "EncryptionKey"
 #define STORAGE_ENCRYPTION_KEYS_PROPERTY "StorageEncryptionKeys"
 #define ENCRYPTION_ALGORITHMS_PROPERTY "EncryptionAlgorithms"
+#define ENCRYPTION_GPG_PROPERTIES "EncryptionGpGProperties"
 #define HAS_ENCRYPTED_ENTRIES_PROPERTY "HasEncryptedEntries"
 #define HAS_NONENCRYPTED_ENTRIES_PROPERTY "HasNonEncryptedEntries"
 #define IS_INCONSISTENT_PROPERTY "IsInconsistent"
diff --git a/package/inc/ZipPackage.hxx b/package/inc/ZipPackage.hxx
index 61b0fc883575..6409769d175a 100644
--- a/package/inc/ZipPackage.hxx
+++ b/package/inc/ZipPackage.hxx
@@ -72,6 +72,7 @@ class ZipPackage final : public cppu::WeakImplHelper
 
     css::uno::Sequence< css::beans::NamedValue > m_aStorageEncryptionKeys;
     css::uno::Sequence< sal_Int8 > m_aEncryptionKey;
+    css::uno::Sequence< css::beans::NamedValue > m_aGpgProps;
 
     FolderHash        m_aRecent;
     OUString   m_aURL;
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index 9bdd03d7cfd1..a93cf0d730b5 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -1195,7 +1195,9 @@ uno::Reference< io::XInputStream > ZipPackage::writeTempFile()
 
         if ( m_nFormat == embed::StorageFormats::PACKAGE )
         {
-            uno::Sequence < PropertyValue > aPropSeq( PKG_SIZE_NOENCR_MNFST );
+            static bool bGpgEncrypt = true;
+            uno::Sequence < PropertyValue > aPropSeq(
+                bGpgEncrypt ? PKG_SIZE_ENCR_MNFST : PKG_SIZE_GPG_ENCR_MNFST );
             aPropSeq [PKG_MNFST_MEDIATYPE].Name = sMediaType;
             aPropSeq [PKG_MNFST_MEDIATYPE].Value <<= m_xRootFolder->GetMediaType();
             aPropSeq [PKG_MNFST_VERSION].Name = sVersion;
@@ -1203,6 +1205,14 @@ uno::Reference< io::XInputStream > ZipPackage::writeTempFile()
             aPropSeq [PKG_MNFST_FULLPATH].Name = sFullPath;
             aPropSeq [PKG_MNFST_FULLPATH].Value <<= OUString("/");
 
+            if( bGpgEncrypt )
+            {
+                for ( sal_Int32 nInd = 0; nInd < m_aGpgProps.getLength(); nInd++ )
+                {
+                    aPropSeq[PKG_MNFST_KEYID+nInd].Name = m_aGpgProps[nInd].Name;
+                    aPropSeq[PKG_MNFST_KEYID+nInd].Value = m_aGpgProps[nInd].Value;
+                }
+            }
             aManList.push_back( aPropSeq );
         }
 
@@ -1738,6 +1748,17 @@ void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const
             }
         }
     }
+    else if ( aPropertyName == ENCRYPTION_GPG_PROPERTIES )
+    {
+        uno::Sequence< beans::NamedValue > aGpgProps;
+        if ( m_pZipFile || !( aValue >>= aGpgProps ) || aGpgProps.getLength() == 0 )
+        {
+            // the algorithms can not be changed if the file has a persistence based on the algorithms ( m_pZipFile )
+            throw IllegalArgumentException(THROW_WHERE "unexpected algorithms list is provided.", uno::Reference< uno::XInterface >(), 2 );
+        }
+
+        m_aGpgProps = aGpgProps;
+    }
     else
         throw UnknownPropertyException(THROW_WHERE );
 }
diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index 160dfa8d310f..bad3fcaca1fd 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -518,6 +518,9 @@ bool ZipPackageStream::saveChild(
     const OUString sStartKeyAlgProperty  ("StartKeyAlgorithm");
     const OUString sDigestAlgProperty    ("DigestAlgorithm");
     const OUString sDerivedKeySizeProperty  ("DerivedKeySize");
+    const OUString sPgpKeyIDProperty        ( "KeyId" );
+    const OUString sPgpKeyPacketProperty    ( "KeyPacket" );
+    const OUString sCipherValueProperty     ( "CipherValue" );
 
     uno::Sequence < beans::PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST);
 
@@ -662,7 +665,8 @@ bool ZipPackageStream::saveChild(
 
             // last property is digest, which is inserted later if we didn't have
             // a magic header
-            aPropSet.realloc(PKG_SIZE_ENCR_MNFST);
+            static bool bGpgEncrypt = true;
+            aPropSet.realloc(bGpgEncrypt ? PKG_SIZE_ENCR_MNFST : PKG_SIZE_GPG_ENCR_MNFST);
 
             aPropSet[PKG_MNFST_INIVECTOR].Name = sInitialisationVectorProperty;
             aPropSet[PKG_MNFST_INIVECTOR].Value <<= m_xBaseEncryptionData->m_aInitVector;
@@ -670,6 +674,15 @@ bool ZipPackageStream::saveChild(
             aPropSet[PKG_MNFST_SALT].Value <<= m_xBaseEncryptionData->m_aSalt;
             aPropSet[PKG_MNFST_ITERATION].Name = sIterationCountProperty;
             aPropSet[PKG_MNFST_ITERATION].Value <<= m_xBaseEncryptionData->m_nIterationCount;
+            if( bGpgEncrypt )
+            {
+                aPropSet[PKG_MNFST_KEYID].Name = sPgpKeyIDProperty;
+                aPropSet[PKG_MNFST_KEYID].Value <<= m_xBaseEncryptionData->m_aSalt;
+                aPropSet[PKG_MNFST_KEYPACKET].Name = sPgpKeyPacketProperty;
+                aPropSet[PKG_MNFST_KEYPACKET].Value <<= m_xBaseEncryptionData->m_aSalt;
+                aPropSet[PKG_MNFST_CIPHERVAL].Name = sCipherValueProperty;
+                aPropSet[PKG_MNFST_CIPHERVAL].Value <<= m_xBaseEncryptionData->m_aSalt;
+            }
 
             // Need to store the uncompressed size in the manifest
             OSL_ENSURE( m_nOwnStreamOrigSize >= 0, "The stream size was not correctly initialized!" );
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index da74a0a5d075..333f9331fb44 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -389,7 +389,17 @@ void SfxObjectShell::SetupStorage( const uno::Reference< embed::XStorage >& xSto
                     catch( uno::Exception& )
                     {
                     }
+                }
 
+                // if gpg -> force AES
+                if ( true )
+                {
+                    aEncryptionAlgs[0].Value <<= xml::crypto::DigestID::SHA256;
+                    aEncryptionAlgs[1].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING;
+                    aEncryptionAlgs[2].Value <<= xml::crypto::DigestID::SHA256_1K;
+                }
+                else if ( nDefVersion >= SvtSaveOptions::ODFVER_012 )
+                {
                     if ( !bUseSHA1InODF12 && nDefVersion != SvtSaveOptions::ODFVER_012_EXT_COMPAT )
                     {
                         aEncryptionAlgs[0].Value <<= xml::crypto::DigestID::SHA256;
commit 7bf0f3fbcfcdbe781e2722479ea3a320513d81c1
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date:   Sun Aug 20 03:38:05 2017 +0200

    comphelper: add storage helper for GPG encryption data
    
    gpg4libre needs to pass down slightly different meta data
    to package / zip storage.
    
    Change-Id: Idba9ad7a821cb33070cf5e5a0f79ae55db99b276

diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk
index 6f8b9d07a83a..546afcfcec98 100644
--- a/comphelper/Library_comphelper.mk
+++ b/comphelper/Library_comphelper.mk
@@ -37,6 +37,7 @@ $(eval $(call gb_Library_add_defs,comphelper,\
 ))
 
 $(eval $(call gb_Library_use_externals,comphelper,\
+	gpgmepp \
     boost_headers \
     icuuc \
     icu_headers \
@@ -62,6 +63,7 @@ $(eval $(call gb_Library_use_libraries,comphelper,\
     cppuhelper \
     sal \
     salhelper \
+	sax \
     ucbhelper \
 	i18nlangtag \
 ))
diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx
index 166955d3b226..09753dd30484 100644
--- a/comphelper/source/misc/storagehelper.cxx
+++ b/comphelper/source/misc/storagehelper.cxx
@@ -19,6 +19,7 @@
 
 #include <com/sun/star/embed/ElementModes.hpp>
 #include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
+#include <com/sun/star/embed/XEncryptionProtectedStorage.hpp>
 #include <com/sun/star/embed/XStorage.hpp>
 #include <com/sun/star/embed/XTransactedObject.hpp>
 #include <com/sun/star/embed/StorageFactory.hpp>
@@ -43,6 +44,7 @@
 #include <rtl/random.h>
 #include <osl/time.h>
 #include <osl/diagnose.h>
+#include <sax/tools/converter.hxx>
 
 #include <ucbhelper/content.hxx>
 
@@ -51,6 +53,11 @@
 #include <comphelper/documentconstants.hxx>
 #include <comphelper/storagehelper.hxx>
 
+#include <gpgme.h>
+#include <context.h>
+#include <key.h>
+#include <data.h>
+
 using namespace ::com::sun::star;
 
 namespace comphelper {
@@ -194,11 +201,21 @@ void OStorageHelper::SetCommonStorageEncryptionData(
             const uno::Reference< embed::XStorage >& xStorage,
             const uno::Sequence< beans::NamedValue >& aEncryptionData )
 {
-    uno::Reference< embed::XEncryptionProtectedSource2 > xEncrSet( xStorage, uno::UNO_QUERY );
+    uno::Reference< embed::XEncryptionProtectedStorage > xEncrSet( xStorage, uno::UNO_QUERY );
     if ( !xEncrSet.is() )
         throw io::IOException(); // TODO
 
-    xEncrSet->setEncryptionData( aEncryptionData );
+    if ( aEncryptionData.getLength() == 2 &&
+         aEncryptionData[0].Name == "GpgInfos" &&
+         aEncryptionData[1].Name == "EncryptionKey" )
+    {
+        xEncrSet->setGpgProperties(
+            aEncryptionData[0].Value.get< uno::Sequence< beans::NamedValue > >() );
+        xEncrSet->setEncryptionData(
+            aEncryptionData[1].Value.get< uno::Sequence< beans::NamedValue > >() );
+    }
+    else
+        xEncrSet->setEncryptionData( aEncryptionData );
 }
 
 
diff --git a/offapi/com/sun/star/embed/XEncryptionProtectedStorage.idl b/offapi/com/sun/star/embed/XEncryptionProtectedStorage.idl
index 5ddcc6831844..5ed2524daf81 100644
--- a/offapi/com/sun/star/embed/XEncryptionProtectedStorage.idl
+++ b/offapi/com/sun/star/embed/XEncryptionProtectedStorage.idl
@@ -84,6 +84,11 @@ interface XEncryptionProtectedStorage: XEncryptionProtectedSource2
     /** allows to get the encryption algorithms of the object.
      */
     sequence< ::com::sun::star::beans::NamedValue > getEncryptionAlgorithms();
+
+    /** set OpenPGP-specific encryption properties
+     */
+    void setGpgProperties( [in] sequence< ::com::sun::star::beans::NamedValue > aProps )
+        raises( ::com::sun::star::lang::IllegalArgumentException );
 };
 
 
diff --git a/package/source/xstor/xstorage.cxx b/package/source/xstor/xstorage.cxx
index 9291eb53cbc7..95750f6d0e73 100644
--- a/package/source/xstor/xstorage.cxx
+++ b/package/source/xstor/xstorage.cxx
@@ -4205,6 +4205,66 @@ void SAL_CALL OStorage::setEncryptionAlgorithms( const uno::Sequence< beans::Nam
     }
 }
 
+void SAL_CALL OStorage::setGpgProperties( const uno::Sequence< beans::NamedValue >& aProps )
+{
+    ::osl::MutexGuard aGuard( m_pData->m_xSharedMutex->GetMutex() );
+
+    if ( !m_pImpl )
+    {
+        SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
+        throw lang::DisposedException( THROW_WHERE );
+    }
+
+    if ( m_pData->m_nStorageType != embed::StorageFormats::PACKAGE )
+        throw uno::RuntimeException( THROW_WHERE ); // the interface must be visible only for package storage
+
+    if ( !aProps.getLength() )
+        throw uno::RuntimeException( THROW_WHERE "Unexpected empty encryption algorithms list!" );
+
+    SAL_WARN_IF( !m_pData->m_bIsRoot, "package.xstor", "setEncryptionAlgorithms() method is not available for nonroot storages!" );
+    if ( m_pData->m_bIsRoot )
+    {
+        try {
+            m_pImpl->ReadContents();
+        }
+        catch ( const uno::RuntimeException& aRuntimeException )
+        {
+            SAL_INFO("package.xstor", "Rethrow: " << aRuntimeException.Message);
+            throw;
+        }
+        catch ( const uno::Exception& aException )
+        {
+            SAL_INFO("package.xstor", "Rethrow: " << aException.Message);
+
+            uno::Any aCaught( ::cppu::getCaughtException() );
+            throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
+                                                static_cast< OWeakObject* >( this ),
+                                                aCaught );
+        }
+
+        uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
+        try
+        {
+            xPackPropSet->setPropertyValue( ENCRYPTION_GPG_PROPERTIES,
+                                            uno::makeAny( aProps ) );
+        }
+        catch ( const uno::RuntimeException& aRuntimeException )
+        {
+            SAL_INFO("package.xstor", "Rethrow: " << aRuntimeException.Message);
+            throw;
+        }
+        catch( const uno::Exception& aException )
+        {
+            SAL_INFO("package.xstor", "Rethrow: " << aException.Message);
+
+            uno::Any aCaught( ::cppu::getCaughtException() );
+            throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
+                                                static_cast< OWeakObject* >( this ),
+                                                aCaught );
+        }
+    }
+}
+
 uno::Sequence< beans::NamedValue > SAL_CALL OStorage::getEncryptionAlgorithms()
 {
     ::osl::MutexGuard aGuard( m_pData->m_xSharedMutex->GetMutex() );
diff --git a/package/source/xstor/xstorage.hxx b/package/source/xstor/xstorage.hxx
index 532088359184..89157fb0051e 100644
--- a/package/source/xstor/xstorage.hxx
+++ b/package/source/xstor/xstorage.hxx
@@ -459,6 +459,7 @@ public:
     //  XEncryptionProtectedStorage
 
     virtual void SAL_CALL setEncryptionAlgorithms( const css::uno::Sequence< css::beans::NamedValue >& aAlgorithms ) override;
+    virtual void SAL_CALL setGpgProperties( const css::uno::Sequence< css::beans::NamedValue >& aAlgorithms ) override;
 
     virtual css::uno::Sequence< css::beans::NamedValue > SAL_CALL getEncryptionAlgorithms() override;
 
commit 106d49950e9c0be45f0e6568472cd156da9b0697
Author: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Date:   Fri Aug 18 21:34:11 2017 +0200

    add manifest entries for gpg encruption
    
    Change-Id: I71bd7e2c6c73d997fa1ed5bb36fdc2873daca10c

diff --git a/package/source/manifest/ManifestDefines.hxx b/package/source/manifest/ManifestDefines.hxx
index 968aed648e6a..42ff1ceeadbc 100644
--- a/package/source/manifest/ManifestDefines.hxx
+++ b/package/source/manifest/ManifestDefines.hxx
@@ -24,8 +24,10 @@
 #define MANIFEST_NSPREFIX "manifest:"
 #define ELEMENT_MANIFEST "manifest:manifest"
 #define ATTRIBUTE_XMLNS "xmlns:manifest"
+#define ATTRIBUTE_XMLNS_LOEXT "xmlns:loext"
 #define MANIFEST_NAMESPACE "http://openoffice.org/2001/manifest"
 #define MANIFEST_OASIS_NAMESPACE "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"
+#define MANIFEST_LOEXT_NAMESPACE "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 #define MANIFEST_DOCTYPE "<!DOCTYPE manifest:manifest PUBLIC \"-//OpenOffice.org//DTD Manifest 1.0//EN\" \"Manifest.dtd\">"
 #define ATTRIBUTE_CDATA "CDATA"
 
@@ -34,6 +36,15 @@
 #define ATTRIBUTE_VERSION "manifest:version"
 #define ATTRIBUTE_MEDIA_TYPE "manifest:media-type"
 #define ATTRIBUTE_SIZE "manifest:size"
+#define ELEMENT_KEYINFO "loext:KeyInfo"
+#define ELEMENT_ENCRYPTEDKEY "loext:EncryptedKey"
+#define ELEMENT_ENCRYPTIONMETHOD "loext:EncryptionMethod"
+#define ELEMENT_PGPDATA "loext:PGPData"
+#define ELEMENT_PGPKEYID "loext:PGPKeyID"
+#define ELEMENT_PGPKEYPACKET "loext:PGPKeyPacket"
+#define ATTRIBUTE_ALGORITHM "loext:Algorithm"
+#define ELEMENT_CIPHERDATA "loext:CipherData"
+#define ELEMENT_CIPHERVALUE "loext:CipherValue"
 
 #define ELEMENT_ENCRYPTION_DATA "manifest:encryption-data"
 #define ATTRIBUTE_CHECKSUM_TYPE "manifest:checksum-type"
diff --git a/package/source/manifest/ManifestExport.cxx b/package/source/manifest/ManifestExport.cxx
index 60a5128e945d..bc8479196669 100644
--- a/package/source/manifest/ManifestExport.cxx
+++ b/package/source/manifest/ManifestExport.cxx
@@ -66,11 +66,23 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
     const OUString sChecksumTypeAttribute    ( ATTRIBUTE_CHECKSUM_TYPE );
     const OUString sChecksumAttribute    ( ATTRIBUTE_CHECKSUM);
 
+    const OUString sKeyInfoElement              ( ELEMENT_KEYINFO );
+    const OUString sEncryptedKeyElement         ( ELEMENT_ENCRYPTEDKEY );
+    const OUString sEncryptionMethodElement     ( ELEMENT_ENCRYPTIONMETHOD );
+    const OUString sPgpDataElement              ( ELEMENT_PGPDATA );
+    const OUString sPgpKeyIDElement             ( ELEMENT_PGPKEYID );
+    const OUString sPGPKeyPacketElement         ( ELEMENT_PGPKEYPACKET );
+    const OUString sAlgorithmAttribute          ( ATTRIBUTE_ALGORITHM );
+    const OUString sCipherDataElement           ( ELEMENT_CIPHERDATA );
+    const OUString sCipherValueElement          ( ELEMENT_CIPHERVALUE );
+    const OUString sPgpKeyIDProperty            ( "KeyId" );
+    const OUString sPgpKeyPacketProperty        ( "KeyPacket" );
+    const OUString sCipherValueProperty         ( "CipherValue" );
     const OUString sFullPathProperty     ( "FullPath" );
     const OUString sVersionProperty  ( "Version" );
     const OUString sMediaTypeProperty    ( "MediaType" );
     const OUString sIterationCountProperty   ( "IterationCount" );
-    const OUString  sDerivedKeySizeProperty  ( "DerivedKeySize" );
+    const OUString sDerivedKeySizeProperty  ( "DerivedKeySize" );
     const OUString sSaltProperty         ( "Salt" );
     const OUString sInitialisationVectorProperty( "InitialisationVector" );
     const OUString sSizeProperty         ( "Size" );
@@ -159,14 +171,19 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
         {
             // oasis format
             pRootAttrList->AddAttribute ( ATTRIBUTE_XMLNS,
-                                        sCdataAttribute,
-                                        MANIFEST_OASIS_NAMESPACE );
+                                          sCdataAttribute,
+                                          MANIFEST_OASIS_NAMESPACE );
             bAcceptNonemptyVersion = true;
             if ( aDocVersion.compareTo( ODFVER_012_TEXT ) >= 0 )
             {
-                // this is ODF12 generation, let encrypted streams contain start-key-generation entry
+                // this is ODF12 or later generation, let encrypted
+                // streams contain start-key-generation entry
                 bStoreStartKeyGeneration = true;
                 pRootAttrList->AddAttribute ( sVersionAttribute, sCdataAttribute, aDocVersion );
+                // plus gpg4libre extensions - loext NS for that
+                pRootAttrList->AddAttribute ( ATTRIBUTE_XMLNS_LOEXT,
+                                              sCdataAttribute,
+                                              MANIFEST_LOEXT_NAMESPACE );
             }
         }
         else
@@ -174,8 +191,8 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
             // even if it is no SO6 format the namespace must be specified
             // thus SO6 format is used as default one
             pRootAttrList->AddAttribute ( ATTRIBUTE_XMLNS,
-                                        sCdataAttribute,
-                                        MANIFEST_NAMESPACE );
+                                          sCdataAttribute,
+                                          MANIFEST_NAMESPACE );
 
             bProvideDTD = true;
         }
@@ -192,12 +209,102 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
     }
     xHandler->startElement( sManifestElement, xRootAttrList );
 
+    if (nManLength > 0)
+    {
+        const beans::PropertyValue *pValue = pSequence[0].getConstArray();
+        OUString aString;
+        const uno::Any *pPgpKeyIDProperty = nullptr, *pPgpKeyPacketProperty = nullptr,
+            *pCipherValueProperty = nullptr;
+        for (sal_uInt32 j = 0, nNum = pSequence[0].getLength(); j < nNum; j++, pValue++)
+        {
+            if (pValue->Name == sPgpKeyIDProperty )
+                pPgpKeyIDProperty = &pValue->Value;
+            else if (pValue->Name == sPgpKeyPacketProperty )
+                pPgpKeyPacketProperty = &pValue->Value;
+            else if (pValue->Name == sCipherValueProperty )
+                pCipherValueProperty = &pValue->Value;
+        }
+
+        if ( pPgpKeyIDProperty && pPgpKeyPacketProperty && pCipherValueProperty )
+        {
+            // TODO make this work for multiple recipients
+            // ==== OpenPGP - encryped session data
+            ::comphelper::AttributeList * pNewAttrList = new ::comphelper::AttributeList;
+            uno::Reference < xml::sax::XAttributeList > xNewAttrList (pNewAttrList);
+            OUStringBuffer aBuffer;
+            uno::Sequence < sal_Int8 > aSequence;
+
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            // ==== KeyInfo & children
+            xHandler->startElement( sKeyInfoElement, nullptr );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+            xHandler->startElement( sEncryptedKeyElement, nullptr );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            // TODO this should rather be configurable
+            pNewAttrList->AddAttribute ( sAlgorithmAttribute, sCdataAttribute,
+                                         "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" );
+            xHandler->startElement( sEncryptionMethodElement, xNewAttrList );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+            xHandler->endElement( sEncryptionMethodElement );
+
+            xHandler->startElement( sKeyInfoElement, nullptr );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            xHandler->startElement( sPgpDataElement, nullptr );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            xHandler->startElement( sPgpKeyIDElement, nullptr );
+            *pPgpKeyIDProperty >>= aSequence;
+            ::sax::Converter::encodeBase64(aBuffer, aSequence);
+            xHandler->characters( aBuffer.makeStringAndClear() );
+            xHandler->endElement( sPgpKeyIDElement );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            xHandler->startElement( sPGPKeyPacketElement, nullptr );
+            *pPgpKeyPacketProperty >>= aSequence;
+            ::sax::Converter::encodeBase64(aBuffer, aSequence);
+            xHandler->characters( aBuffer.makeStringAndClear() );
+            xHandler->endElement( sPGPKeyPacketElement );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            xHandler->endElement( sPgpDataElement );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            xHandler->endElement( sKeyInfoElement );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            xHandler->startElement( sCipherDataElement, nullptr );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            xHandler->startElement( sCipherValueElement, nullptr );
+            *pCipherValueProperty >>= aSequence;
+            ::sax::Converter::encodeBase64(aBuffer, aSequence);
+            xHandler->characters( aBuffer.makeStringAndClear() );
+            xHandler->endElement( sCipherValueElement );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            xHandler->endElement( sCipherDataElement );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            xHandler->endElement( sEncryptedKeyElement );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+
+            xHandler->endElement( sKeyInfoElement );
+            xHandler->ignorableWhitespace ( sWhiteSpace );
+        }
+    }
+
     for (sal_uInt32 i = 0 ; i < nManLength ; i++)
     {
         ::comphelper::AttributeList *pAttrList = new ::comphelper::AttributeList;
         const beans::PropertyValue *pValue = pSequence[i].getConstArray();
         OUString aString;
-        const uno::Any *pVector = nullptr, *pSalt = nullptr, *pIterationCount = nullptr, *pDigest = nullptr, *pDigestAlg = nullptr, *pEncryptAlg = nullptr, *pStartKeyAlg = nullptr, *pDerivedKeySize = nullptr;
+        const uno::Any *pVector = nullptr, *pSalt = nullptr,
+            *pIterationCount = nullptr, *pDigest = nullptr,
+            *pDigestAlg = nullptr, *pEncryptAlg = nullptr,
+            *pStartKeyAlg = nullptr, *pDerivedKeySize = nullptr;
         for (sal_uInt32 j = 0, nNum = pSequence[i].getLength(); j < nNum; j++, pValue++)
         {
             if (pValue->Name == sMediaTypeProperty )


More information about the Libreoffice-commits mailing list