summaryrefslogtreecommitdiff
path: root/comphelper/source/misc/docpasswordhelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'comphelper/source/misc/docpasswordhelper.cxx')
-rw-r--r--comphelper/source/misc/docpasswordhelper.cxx152
1 files changed, 105 insertions, 47 deletions
diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx
index 71f92db48d00..084fb0d36601 100644
--- a/comphelper/source/misc/docpasswordhelper.cxx
+++ b/comphelper/source/misc/docpasswordhelper.cxx
@@ -51,7 +51,6 @@ using ::com::sun::star::task::PasswordRequestMode;
using ::com::sun::star::task::PasswordRequestMode_PASSWORD_ENTER;
using ::com::sun::star::task::PasswordRequestMode_PASSWORD_REENTER;
using ::com::sun::star::task::XInteractionHandler;
-using ::com::sun::star::task::XInteractionRequest;
using namespace ::com::sun::star;
@@ -96,10 +95,10 @@ uno::Sequence< beans::PropertyValue > DocPasswordHelper::GenerateNewModifyPasswo
uno::Sequence< sal_Int8 > aNewHash = GeneratePBKDF2Hash(aPassword, aSalt, nPBKDF2IterationCount, 16);
if ( aNewHash.hasElements() )
{
- aResult = { comphelper::makePropertyValue("algorithm-name", OUString( "PBKDF2" )),
- comphelper::makePropertyValue("salt", aSalt),
- comphelper::makePropertyValue("iteration-count", nPBKDF2IterationCount),
- comphelper::makePropertyValue("hash", aNewHash) };
+ aResult = { comphelper::makePropertyValue(u"algorithm-name"_ustr, u"PBKDF2"_ustr),
+ comphelper::makePropertyValue(u"salt"_ustr, aSalt),
+ comphelper::makePropertyValue(u"iteration-count"_ustr, nPBKDF2IterationCount),
+ comphelper::makePropertyValue(u"hash"_ustr, aNewHash) };
}
return aResult;
@@ -111,23 +110,83 @@ DocPasswordHelper::GenerateNewModifyPasswordInfoOOXML(std::u16string_view aPassw
{
uno::Sequence<beans::PropertyValue> aResult;
- uno::Sequence<sal_Int8> aSalt = GenerateRandomByteSequence(16);
- OUStringBuffer aBuffer;
- comphelper::Base64::encode(aBuffer, aSalt);
- OUString sSalt = aBuffer.toString();
+ if (!aPassword.empty())
+ {
+ uno::Sequence<sal_Int8> aSalt = GenerateRandomByteSequence(16);
+ OUStringBuffer aBuffer(22);
+ comphelper::Base64::encode(aBuffer, aSalt);
+ OUString sSalt = aBuffer.makeStringAndClear();
+
+ sal_Int32 const nIterationCount = 100000;
+ OUString sAlgorithm(u"SHA-512"_ustr);
+
+ const OUString sHash(GetOoxHashAsBase64(OUString(aPassword), sSalt, nIterationCount,
+ comphelper::Hash::IterCount::APPEND, sAlgorithm));
+
+ if (!sHash.isEmpty())
+ {
+ aResult = { comphelper::makePropertyValue(u"algorithm-name"_ustr, sAlgorithm),
+ comphelper::makePropertyValue(u"salt"_ustr, sSalt),
+ comphelper::makePropertyValue(u"iteration-count"_ustr, nIterationCount),
+ comphelper::makePropertyValue(u"hash"_ustr, sHash) };
+ }
+ }
+
+ return aResult;
+}
- sal_Int32 const nIterationCount = 100000;
- OUString sAlgorithm("SHA-512");
- const OUString sHash(GetOoxHashAsBase64(OUString(aPassword), sSalt, nIterationCount,
- comphelper::Hash::IterCount::APPEND, sAlgorithm));
+uno::Sequence< beans::PropertyValue > DocPasswordHelper::ConvertPasswordInfo( const uno::Sequence< beans::PropertyValue >& aInfo )
+{
+ uno::Sequence< beans::PropertyValue > aResult;
+ OUString sAlgorithm, sHash, sSalt, sCount;
+ sal_Int32 nAlgorithm = 0;
+
+ for ( const auto & prop : aInfo )
+ {
+ if ( prop.Name == "cryptAlgorithmSid" )
+ {
+ prop.Value >>= sAlgorithm;
+ nAlgorithm = sAlgorithm.toInt32();
+ }
+ else if ( prop.Name == "salt" )
+ prop.Value >>= sSalt;
+ else if ( prop.Name == "cryptSpinCount" )
+ prop.Value >>= sCount;
+ else if ( prop.Name == "hash" )
+ prop.Value >>= sHash;
+ }
- if (!sHash.isEmpty())
+ if (nAlgorithm == 1)
+ sAlgorithm = "MD2";
+ else if (nAlgorithm == 2)
+ sAlgorithm = "MD4";
+ else if (nAlgorithm == 3)
+ sAlgorithm = "MD5";
+ else if (nAlgorithm == 4)
+ sAlgorithm = "SHA-1";
+ else if (nAlgorithm == 5)
+ sAlgorithm = "MAC";
+ else if (nAlgorithm == 6)
+ sAlgorithm = "RIPEMD";
+ else if (nAlgorithm == 7)
+ sAlgorithm = "RIPEMD-160";
+ else if (nAlgorithm == 9)
+ sAlgorithm = "HMAC";
+ else if (nAlgorithm == 12)
+ sAlgorithm = "SHA-256";
+ else if (nAlgorithm == 13)
+ sAlgorithm = "SHA-384";
+ else if (nAlgorithm == 14)
+ sAlgorithm = "SHA-512";
+
+ if ( !sCount.isEmpty() )
{
- aResult = { comphelper::makePropertyValue("algorithm-name", sAlgorithm),
- comphelper::makePropertyValue("salt", sSalt),
- comphelper::makePropertyValue("iteration-count", nIterationCount),
- comphelper::makePropertyValue("hash", sHash) };
+ sal_Int32 nCount = sCount.toInt32();
+ aResult = { comphelper::makePropertyValue(u"algorithm-name"_ustr, sAlgorithm),
+ comphelper::makePropertyValue(u"salt"_ustr, sSalt),
+ comphelper::makePropertyValue(u"iteration-count"_ustr, nCount),
+ comphelper::makePropertyValue(u"hash"_ustr, sHash) };
}
return aResult;
@@ -194,7 +253,7 @@ bool DocPasswordHelper::IsModifyPasswordCorrect( std::u16string_view aPassword,
sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32(
- const OUString& aUString )
+ std::u16string_view aUString )
{
static const sal_uInt16 pInitialCode[] = {
0xE1F0, // 1
@@ -233,7 +292,7 @@ sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32(
};
sal_uInt32 nResult = 0;
- sal_uInt32 nLen = aUString.getLength();
+ size_t nLen = aUString.size();
if ( nLen )
{
@@ -243,7 +302,7 @@ sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32(
sal_uInt16 nHighResult = pInitialCode[nLen - 1];
sal_uInt16 nLowResult = 0;
- for ( sal_uInt32 nInd = 0; nInd < nLen; nInd++ )
+ for ( size_t nInd = 0; nInd < nLen; nInd++ )
{
// NO Encoding during conversion!
// The specification says that the low byte should be used in case it is not NULL
@@ -314,6 +373,8 @@ std::vector<unsigned char> DocPasswordHelper::GetOoxHashAsVector(
eType = comphelper::HashType::SHA512;
else if (rAlgorithmName == u"SHA-256" || rAlgorithmName == u"SHA256")
eType = comphelper::HashType::SHA256;
+ else if (rAlgorithmName == u"SHA-384" || rAlgorithmName == u"SHA384")
+ eType = comphelper::HashType::SHA384;
else if (rAlgorithmName == u"SHA-1" || rAlgorithmName == u"SHA1") // "SHA1" might be in the wild
eType = comphelper::HashType::SHA1;
else if (rAlgorithmName == u"MD5")
@@ -327,13 +388,13 @@ std::vector<unsigned char> DocPasswordHelper::GetOoxHashAsVector(
css::uno::Sequence<sal_Int8> DocPasswordHelper::GetOoxHashAsSequence(
const OUString& rPassword,
- const OUString& rSaltValue,
+ std::u16string_view rSaltValue,
sal_uInt32 nSpinCount,
comphelper::Hash::IterCount eIterCount,
std::u16string_view rAlgorithmName)
{
std::vector<unsigned char> aSaltVec;
- if (!rSaltValue.isEmpty())
+ if (!rSaltValue.empty())
{
css::uno::Sequence<sal_Int8> aSaltSeq;
comphelper::Base64::decode( aSaltSeq, rSaltValue);
@@ -347,7 +408,7 @@ css::uno::Sequence<sal_Int8> DocPasswordHelper::GetOoxHashAsSequence(
OUString DocPasswordHelper::GetOoxHashAsBase64(
const OUString& rPassword,
- const OUString& rSaltValue,
+ std::u16string_view rSaltValue,
sal_uInt32 nSpinCount,
comphelper::Hash::IterCount eIterCount,
std::u16string_view rAlgorithmName)
@@ -365,23 +426,24 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
{
uno::Sequence< sal_Int8 > aResult( nLength );
- rtlRandomPool aRandomPool = rtl_random_createPool ();
- rtl_random_getBytes ( aRandomPool, aResult.getArray(), nLength );
- rtl_random_destroyPool ( aRandomPool );
+ if (rtl_random_getBytes(nullptr, aResult.getArray(), nLength) != rtl_Random_E_None)
+ {
+ throw uno::RuntimeException(u"rtl_random_getBytes failed"_ustr);
+ }
return aResult;
}
-/*static*/ uno::Sequence< sal_Int8 > DocPasswordHelper::GenerateStd97Key( const OUString& aPassword, const uno::Sequence< sal_Int8 >& aDocId )
+/*static*/ uno::Sequence< sal_Int8 > DocPasswordHelper::GenerateStd97Key( std::u16string_view aPassword, const uno::Sequence< sal_Int8 >& aDocId )
{
uno::Sequence< sal_Int8 > aResultKey;
- if ( !aPassword.isEmpty() && aDocId.getLength() == 16 )
+ if ( !aPassword.empty() && aDocId.getLength() == 16 )
{
sal_uInt16 pPassData[16] = {};
- sal_Int32 nPassLen = std::min< sal_Int32 >( aPassword.getLength(), 15 );
- memcpy( pPassData, aPassword.getStr(), nPassLen * sizeof(pPassData[0]) );
+ sal_Int32 nPassLen = std::min< sal_Int32 >( aPassword.size(), 15 );
+ memcpy( pPassData, aPassword.data(), nPassLen * sizeof(pPassData[0]) );
aResultKey = GenerateStd97Key( pPassData, aDocId );
}
@@ -562,11 +624,10 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
if (eResult == DocPasswordVerifierResult::OK && !aPassword.isEmpty())
{
- if (std::find_if(std::cbegin(aEncData), std::cend(aEncData),
+ if (std::none_of(std::cbegin(aEncData), std::cend(aEncData),
[](const css::beans::NamedValue& val) {
return val.Name == PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
- })
- == std::cend(aEncData))
+ }))
{
// tdf#118639: We need ODF encryption data for autorecovery, where password
// will already be unavailable, so generate and append it here
@@ -584,9 +645,9 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
// 2. Add MS binary and OOXML encryption data to result
aEncData = comphelper::concatSequences(
aEncData, std::initializer_list<beans::NamedValue>{
- { "STD97EncryptionKey", css::uno::Any(aEnc97Key) },
- { "STD97UniqueID", css::uno::Any(aUniqueID) },
- { "OOXPassword", css::uno::Any(aPassword) },
+ { u"STD97EncryptionKey"_ustr, css::uno::Any(aEnc97Key) },
+ { u"STD97UniqueID"_ustr, css::uno::Any(aUniqueID) },
+ { u"OOXPassword"_ustr, css::uno::Any(aPassword) },
});
}
}
@@ -607,26 +668,23 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
GpgME::initializeLibrary();
GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
if (err)
- throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+ throw uno::RuntimeException(u"The GpgME library failed to initialize for the OpenPGP protocol."_ustr);
ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
if (ctx == nullptr)
- throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+ throw uno::RuntimeException(u"The GpgME library failed to initialize for the OpenPGP protocol."_ustr);
ctx->setArmor(false);
- const uno::Sequence < beans::NamedValue > *pSequence = rGpgProperties.getConstArray();
- const sal_Int32 nLength = rGpgProperties.getLength();
- for ( sal_Int32 i = 0; i < nLength ; i++, pSequence++ )
+ for (auto& rSequence : rGpgProperties)
{
- const beans::NamedValue *pValues = pSequence->getConstArray();
- if ( pSequence->getLength() == 3 )
+ if (rSequence.getLength() == 3)
{
// take CipherValue and try to decrypt that - stop after
// the first successful decryption
// ctx is setup now, let's decrypt the lot!
uno::Sequence < sal_Int8 > aVector;
- pValues[2].Value >>= aVector;
+ rSequence[2].Value >>= aVector;
GpgME::Data cipher(
reinterpret_cast<const char*>(aVector.getConstArray()),
@@ -653,7 +711,7 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
result = plain.seek(0,SEEK_SET);
assert(result == 0);
if( plain.read(aKeyValue.getArray(), len) != len )
- throw uno::RuntimeException("The GpgME library failed to read the encrypted value.");
+ throw uno::RuntimeException(u"The GpgME library failed to read the encrypted value."_ustr);
SAL_INFO("comphelper.crypto", "Extracted gpg session key of length: " << len);
@@ -665,7 +723,7 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
if ( aEncryptionData.hasElements() )
{
uno::Sequence< beans::NamedValue > aContainer{
- { "GpgInfos", uno::Any(rGpgProperties) }, { "EncryptionKey", uno::Any(aEncryptionData) }
+ { u"GpgInfos"_ustr, uno::Any(rGpgProperties) }, { u"EncryptionKey"_ustr, uno::Any(aEncryptionData) }
};
return aContainer;