Restore compatibility with pre-5.9 Keccak calculation

Commit 12c5264d9add1826d543c36d893db77262195fc6 fixed the calculation of
SHA-3 in QCryptographicHash: we were previously calculating Keccak.
Unfortunately, turns out that replacing the algorithm wasn't the best
idea: there are people who need to compare with the result obtained from
a previous version of Qt and stored somewhere. This commit restores the
enum values 7 through 10 to mean Keccak and moves SHA-3 to 12 through
15. The "Sha3_nnn" enums will switch between the two according to the
QT_SHA3_KECCAK_COMPAT macro.

[ChangeLog][Important Behavior Changes] This version of Qt restores
compatibility with pre-5.9.0 calculation of QCryptographicHash
algorithms that were labelled "Sha3_nnn": that is, applications compiled
with old versions of Qt will continue using the Keccak algorithm.
Applications recompiled with this version will use SHA-3, unless
QT_SHA3_KECCAK_COMPAT is #define'd prior to #include
<QCryptographicHash>.

[ChangeLog][Binary Compatibility Note] This version of Qt changes the
values assigned to enumerations QCryptographicHash::Sha3_nnn.
Applications compiled with this version and using those enumerations
will not work with Qt 5.9.0 and 5.9.1, unless QT_SHA3_KECCAK_COMPAT is
defined.

Task-number: QTBUG-62025
Discussed-at: http://lists.qt-project.org/pipermail/development/2017-September/030818.html
Change-Id: I6e1fe42ae4b742a7b811fffd14e418fc04f096c3
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Thiago Macieira 2017-09-13 19:20:46 -07:00
parent bcd81a9e2d
commit 92ca09147f
4 changed files with 106 additions and 27 deletions

View File

@ -181,13 +181,18 @@ public:
#endif #endif
}; };
#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
void sha3Finish(int bitCount); enum class Sha3Variant
{
Sha3,
Keccak
};
void sha3Finish(int bitCount, Sha3Variant sha3Variant);
#endif #endif
QByteArray result; QByteArray result;
}; };
#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
void QCryptographicHashPrivate::sha3Finish(int bitCount) void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant)
{ {
/* /*
FIPS 202 §6.1 defines SHA-3 in terms of calculating the Keccak function FIPS 202 §6.1 defines SHA-3 in terms of calculating the Keccak function
@ -214,7 +219,15 @@ void QCryptographicHashPrivate::sha3Finish(int bitCount)
result.resize(bitCount / 8); result.resize(bitCount / 8);
SHA3Context copy = sha3Context; SHA3Context copy = sha3Context;
switch (sha3Variant) {
case Sha3Variant::Sha3:
sha3Update(&copy, reinterpret_cast<const BitSequence *>(&sha3FinalSuffix), 2); sha3Update(&copy, reinterpret_cast<const BitSequence *>(&sha3FinalSuffix), 2);
break;
case Sha3Variant::Keccak:
break;
}
sha3Final(&copy, reinterpret_cast<BitSequence *>(result.data())); sha3Final(&copy, reinterpret_cast<BitSequence *>(result.data()));
} }
#endif #endif
@ -239,6 +252,12 @@ void QCryptographicHashPrivate::sha3Finish(int bitCount)
/*! /*!
\enum QCryptographicHash::Algorithm \enum QCryptographicHash::Algorithm
\note In Qt versions before 5.9, when asked to generate a SHA3 hash sum,
QCryptographicHash actually calculated Keccak. If you need compatibility with
SHA-3 hashes produced by those versions of Qt, use the \c{Keccak_}
enumerators. Alternatively, if source compatibility is required, define the
macro \c QT_SHA3_KECCAK_COMPAT.
\value Md4 Generate an MD4 hash sum \value Md4 Generate an MD4 hash sum
\value Md5 Generate an MD5 hash sum \value Md5 Generate an MD5 hash sum
\value Sha1 Generate an SHA-1 hash sum \value Sha1 Generate an SHA-1 hash sum
@ -250,6 +269,14 @@ void QCryptographicHashPrivate::sha3Finish(int bitCount)
\value Sha3_256 Generate an SHA3-256 hash sum. Introduced in Qt 5.1 \value Sha3_256 Generate an SHA3-256 hash sum. Introduced in Qt 5.1
\value Sha3_384 Generate an SHA3-384 hash sum. Introduced in Qt 5.1 \value Sha3_384 Generate an SHA3-384 hash sum. Introduced in Qt 5.1
\value Sha3_512 Generate an SHA3-512 hash sum. Introduced in Qt 5.1 \value Sha3_512 Generate an SHA3-512 hash sum. Introduced in Qt 5.1
\value Keccak_224 Generate a Keccak-224 hash sum. Introduced in Qt 5.9.2
\value Keccak_256 Generate a Keccak-256 hash sum. Introduced in Qt 5.9.2
\value Keccak_384 Generate a Keccak-384 hash sum. Introduced in Qt 5.9.2
\value Keccak_512 Generate a Keccak-512 hash sum. Introduced in Qt 5.9.2
\omitvalue RealSha3_224
\omitvalue RealSha3_256
\omitvalue RealSha3_384
\omitvalue RealSha3_512
*/ */
/*! /*!
@ -303,16 +330,20 @@ void QCryptographicHash::reset()
case Sha512: case Sha512:
SHA512Reset(&d->sha512Context); SHA512Reset(&d->sha512Context);
break; break;
case Sha3_224: case RealSha3_224:
case Keccak_224:
sha3Init(&d->sha3Context, 224); sha3Init(&d->sha3Context, 224);
break; break;
case Sha3_256: case RealSha3_256:
case Keccak_256:
sha3Init(&d->sha3Context, 256); sha3Init(&d->sha3Context, 256);
break; break;
case Sha3_384: case RealSha3_384:
case Keccak_384:
sha3Init(&d->sha3Context, 384); sha3Init(&d->sha3Context, 384);
break; break;
case Sha3_512: case RealSha3_512:
case Keccak_512:
sha3Init(&d->sha3Context, 512); sha3Init(&d->sha3Context, 512);
break; break;
#endif #endif
@ -354,16 +385,20 @@ void QCryptographicHash::addData(const char *data, int length)
case Sha512: case Sha512:
SHA512Input(&d->sha512Context, reinterpret_cast<const unsigned char *>(data), length); SHA512Input(&d->sha512Context, reinterpret_cast<const unsigned char *>(data), length);
break; break;
case Sha3_224: case RealSha3_224:
case Keccak_224:
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8); sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8);
break; break;
case Sha3_256: case RealSha3_256:
case Keccak_256:
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8); sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8);
break; break;
case Sha3_384: case RealSha3_384:
case Keccak_384:
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8); sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8);
break; break;
case Sha3_512: case RealSha3_512:
case Keccak_512:
sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8); sha3Update(&d->sha3Context, reinterpret_cast<const BitSequence *>(data), length*8);
break; break;
#endif #endif
@ -462,20 +497,36 @@ QByteArray QCryptographicHash::result() const
SHA512Result(&copy, reinterpret_cast<unsigned char *>(d->result.data())); SHA512Result(&copy, reinterpret_cast<unsigned char *>(d->result.data()));
break; break;
} }
case Sha3_224: { case RealSha3_224: {
d->sha3Finish(224); d->sha3Finish(224, QCryptographicHashPrivate::Sha3Variant::Sha3);
break; break;
} }
case Sha3_256: { case RealSha3_256: {
d->sha3Finish(256); d->sha3Finish(256, QCryptographicHashPrivate::Sha3Variant::Sha3);
break; break;
} }
case Sha3_384: { case RealSha3_384: {
d->sha3Finish(384); d->sha3Finish(384, QCryptographicHashPrivate::Sha3Variant::Sha3);
break; break;
} }
case Sha3_512: { case RealSha3_512: {
d->sha3Finish(512); d->sha3Finish(512, QCryptographicHashPrivate::Sha3Variant::Sha3);
break;
}
case Keccak_224: {
d->sha3Finish(224, QCryptographicHashPrivate::Sha3Variant::Keccak);
break;
}
case Keccak_256: {
d->sha3Finish(256, QCryptographicHashPrivate::Sha3Variant::Keccak);
break;
}
case Keccak_384: {
d->sha3Finish(384, QCryptographicHashPrivate::Sha3Variant::Keccak);
break;
}
case Keccak_512: {
d->sha3Finish(512, QCryptographicHashPrivate::Sha3Variant::Keccak);
break; break;
} }
#endif #endif

View File

@ -65,10 +65,26 @@ public:
Sha256, Sha256,
Sha384, Sha384,
Sha512, Sha512,
Sha3_224,
Sha3_256, Keccak_224 = 7,
Sha3_384, Keccak_256,
Sha3_512 Keccak_384,
Keccak_512,
RealSha3_224 = 11,
RealSha3_256,
RealSha3_384,
RealSha3_512,
# ifndef QT_SHA3_KECCAK_COMPAT
Sha3_224 = RealSha3_224,
Sha3_256 = RealSha3_256,
Sha3_384 = RealSha3_384,
Sha3_512 = RealSha3_512
# else
Sha3_224 = Keccak_224,
Sha3_256 = Keccak_256,
Sha3_384 = Keccak_384,
Sha3_512 = Keccak_512
# endif
#endif #endif
}; };
Q_ENUM(Algorithm) Q_ENUM(Algorithm)

View File

@ -99,13 +99,17 @@ static int qt_hash_block_size(QCryptographicHash::Algorithm method)
return SHA384_Message_Block_Size; return SHA384_Message_Block_Size;
case QCryptographicHash::Sha512: case QCryptographicHash::Sha512:
return SHA512_Message_Block_Size; return SHA512_Message_Block_Size;
case QCryptographicHash::Sha3_224: case QCryptographicHash::RealSha3_224:
case QCryptographicHash::Keccak_224:
return 144; return 144;
case QCryptographicHash::Sha3_256: case QCryptographicHash::RealSha3_256:
case QCryptographicHash::Keccak_256:
return 136; return 136;
case QCryptographicHash::Sha3_384: case QCryptographicHash::RealSha3_384:
case QCryptographicHash::Keccak_384:
return 104; return 104;
case QCryptographicHash::Sha3_512: case QCryptographicHash::RealSha3_512:
case QCryptographicHash::Keccak_512:
return 72; return 72;
} }
return 0; return 0;

View File

@ -79,6 +79,14 @@ const char *algoname(int i)
return "sha3_384-"; return "sha3_384-";
case QCryptographicHash::Sha3_512: case QCryptographicHash::Sha3_512:
return "sha3_512-"; return "sha3_512-";
case QCryptographicHash::Keccak_224:
return "keccak_224-";
case QCryptographicHash::Keccak_256:
return "keccak_256-";
case QCryptographicHash::Keccak_384:
return "keccak_384-";
case QCryptographicHash::Keccak_512:
return "keccak_512-";
} }
Q_UNREACHABLE(); Q_UNREACHABLE();
return 0; return 0;