-
Notifications
You must be signed in to change notification settings - Fork 198
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement XEP-0300: Use of Cryptographic Hash Functions in XMPP
Parsing and serialization for XEP-0300 https://xmpp.org/extensions/xep-0300.html in version 1.0.
- Loading branch information
Showing
6 changed files
with
304 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
// SPDX-FileCopyrightText: 2022 Linus Jahn <[email protected]> | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
#include "QXmppHash.h" | ||
|
||
#include "QXmppConstants_p.h" | ||
|
||
#include <QDomElement> | ||
#include <QXmlStreamWriter> | ||
|
||
using namespace QXmpp; | ||
|
||
/// | ||
/// \enum QXmpp::HashAlgorithm | ||
/// | ||
/// One of the hash algorithms specified by the IANA registry or \xep{0300, Use | ||
/// of Cryptographic Hash Functions in XMPP}. | ||
/// | ||
/// \since QXmpp 1.5 | ||
/// | ||
|
||
static QString algorithmToString(HashAlgorithm algorithm) | ||
{ | ||
switch (algorithm) { | ||
case HashAlgorithm::Unknown: | ||
return {}; | ||
case HashAlgorithm::Md2: | ||
return QStringLiteral("md2"); | ||
case HashAlgorithm::Md5: | ||
return QStringLiteral("md5"); | ||
case HashAlgorithm::Shake128: | ||
return QStringLiteral("shake128"); | ||
case HashAlgorithm::Shake256: | ||
return QStringLiteral("shake256"); | ||
case HashAlgorithm::Sha1: | ||
return QStringLiteral("sha-1"); | ||
case HashAlgorithm::Sha224: | ||
return QStringLiteral("sha-224"); | ||
case HashAlgorithm::Sha256: | ||
return QStringLiteral("sha-256"); | ||
case HashAlgorithm::Sha384: | ||
return QStringLiteral("sha-384"); | ||
case HashAlgorithm::Sha512: | ||
return QStringLiteral("sha-512"); | ||
case HashAlgorithm::Sha3_256: | ||
return QStringLiteral("sha3-256"); | ||
case HashAlgorithm::Sha3_512: | ||
return QStringLiteral("sha3-512"); | ||
case HashAlgorithm::Blake2b_256: | ||
return QStringLiteral("blake2b-256"); | ||
case HashAlgorithm::Blake2b_512: | ||
return QStringLiteral("blake2b-512"); | ||
} | ||
Q_UNREACHABLE(); | ||
} | ||
|
||
static HashAlgorithm hashAlgorithmFromString(const QString &str) | ||
{ | ||
if (str == "md2") { | ||
return HashAlgorithm::Md2; | ||
} | ||
if (str == "md5") { | ||
return HashAlgorithm::Md5; | ||
} | ||
if (str == "shake128") { | ||
return HashAlgorithm::Shake128; | ||
} | ||
if (str == "shake256") { | ||
return HashAlgorithm::Shake256; | ||
} | ||
if (str == "sha-1") { | ||
return HashAlgorithm::Sha1; | ||
} | ||
if (str == "sha-224") { | ||
return HashAlgorithm::Sha224; | ||
} | ||
if (str == "sha-256") { | ||
return HashAlgorithm::Sha256; | ||
} | ||
if (str == "sha-384") { | ||
return HashAlgorithm::Sha384; | ||
} | ||
if (str == "sha-512") { | ||
return HashAlgorithm::Sha512; | ||
} | ||
if (str == "sha3-256") { | ||
return HashAlgorithm::Sha3_256; | ||
} | ||
if (str == "sha3-512") { | ||
return HashAlgorithm::Sha3_512; | ||
} | ||
if (str == "blake2b-256") { | ||
return HashAlgorithm::Blake2b_256; | ||
} | ||
if (str == "blake2b-512") { | ||
return HashAlgorithm::Blake2b_512; | ||
} | ||
return HashAlgorithm::Unknown; | ||
} | ||
|
||
/// | ||
/// \class QXmppHash | ||
/// | ||
/// Contains a hash value and its algorithm. | ||
/// | ||
/// \since QXmpp 1.5 | ||
/// | ||
|
||
QXmppHash::QXmppHash() = default; | ||
|
||
/// \cond | ||
bool QXmppHash::parse(const QDomElement &el) | ||
{ | ||
if (el.tagName() == "hash" && el.namespaceURI() == ns_hashes) { | ||
m_algorithm = hashAlgorithmFromString(el.attribute("algo")); | ||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) | ||
if (auto hashResult = QByteArray::fromBase64Encoding(el.text().toUtf8())) { | ||
m_hash = std::move(*hashResult); | ||
} else { | ||
return false; | ||
} | ||
#else | ||
m_hash = QByteArray::fromBase64(el.text().toUtf8()); | ||
#endif | ||
} | ||
return false; | ||
} | ||
|
||
void QXmppHash::toXml(QXmlStreamWriter *writer) const | ||
{ | ||
writer->writeDefaultNamespace(ns_hashes); | ||
writer->writeStartElement("hash"); | ||
writer->writeAttribute("algo", algorithmToString(m_algorithm)); | ||
writer->writeCharacters(m_hash.toBase64()); | ||
writer->writeEndElement(); | ||
} | ||
/// \endcond | ||
|
||
/// | ||
/// \class QXmppHashUsed | ||
/// | ||
/// Annotates the used hashing algorithm. | ||
/// | ||
/// \since QXmpp 1.5 | ||
/// | ||
|
||
QXmppHashUsed::QXmppHashUsed() = default; | ||
|
||
/// | ||
/// Creates an object that tells other XMPP entities to use this hash algorithm. | ||
/// | ||
QXmppHashUsed::QXmppHashUsed(QXmpp::HashAlgorithm algorithm) | ||
: m_algorithm(algorithm) | ||
{ | ||
} | ||
|
||
/// \cond | ||
bool QXmppHashUsed::parse(const QDomElement &el) | ||
{ | ||
if (el.tagName() == "hash-used" && el.namespaceURI() == ns_hashes) { | ||
m_algorithm = hashAlgorithmFromString(el.attribute("algo")); | ||
} | ||
return false; | ||
} | ||
|
||
void QXmppHashUsed::toXml(QXmlStreamWriter *writer) const | ||
{ | ||
writer->writeDefaultNamespace(ns_hashes); | ||
writer->writeStartElement("hash-used"); | ||
writer->writeAttribute("algo", algorithmToString(m_algorithm)); | ||
writer->writeEndElement(); | ||
} | ||
/// \endcond | ||
|
||
/// | ||
/// Returns the algorithm used to create the hash. | ||
/// | ||
HashAlgorithm QXmppHash::algorithm() const | ||
{ | ||
return m_algorithm; | ||
} | ||
|
||
/// | ||
/// Sets the algorithm that was used to create the hashed data | ||
/// | ||
void QXmppHash::setAlgorithm(QXmpp::HashAlgorithm algorithm) | ||
{ | ||
m_algorithm = algorithm; | ||
} | ||
|
||
/// | ||
/// Returns the binary data of the hash. | ||
/// | ||
QByteArray QXmppHash::hash() const | ||
{ | ||
return m_hash; | ||
} | ||
|
||
/// | ||
/// Sets the hashed data. | ||
/// | ||
void QXmppHash::setHash(const QByteArray &data) | ||
{ | ||
m_hash = data; | ||
} | ||
|
||
/// | ||
/// Returns the algorithm that is supposed to be used for hashing. | ||
/// | ||
HashAlgorithm QXmppHashUsed::algorithm() const | ||
{ | ||
return m_algorithm; | ||
} | ||
|
||
/// | ||
/// Sets the algorithm that was used to create the hashed data | ||
/// | ||
void QXmppHashUsed::setAlgorithm(QXmpp::HashAlgorithm algorithm) | ||
{ | ||
m_algorithm = algorithm; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// SPDX-FileCopyrightText: 2022 Linus Jahn <[email protected]> | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
#ifndef QXMPPHASH_H | ||
#define QXMPPHASH_H | ||
|
||
#include "QXmppGlobal.h" | ||
|
||
#include <QByteArray> | ||
|
||
class QDomElement; | ||
class QXmlStreamWriter; | ||
|
||
namespace QXmpp { | ||
|
||
enum class HashAlgorithm : uint32_t { | ||
Unknown, | ||
Md2, | ||
Md5, | ||
Shake128, | ||
Shake256, | ||
Sha1, | ||
Sha224, | ||
Sha256, | ||
Sha384, | ||
Sha512, | ||
Sha3_256, | ||
Sha3_512, | ||
Blake2b_256, | ||
Blake2b_512, | ||
}; | ||
|
||
} | ||
|
||
class QXMPP_EXPORT QXmppHash | ||
{ | ||
public: | ||
QXmppHash(); | ||
|
||
/// \cond | ||
bool parse(const QDomElement &el); | ||
void toXml(QXmlStreamWriter *writer) const; | ||
/// \endcond | ||
|
||
QXmpp::HashAlgorithm algorithm() const; | ||
void setAlgorithm(QXmpp::HashAlgorithm algorithm); | ||
|
||
QByteArray hash() const; | ||
void setHash(const QByteArray &data); | ||
|
||
private: | ||
QXmpp::HashAlgorithm m_algorithm = QXmpp::HashAlgorithm::Unknown; | ||
QByteArray m_hash; | ||
}; | ||
|
||
class QXMPP_EXPORT QXmppHashUsed | ||
{ | ||
public: | ||
QXmppHashUsed(); | ||
QXmppHashUsed(QXmpp::HashAlgorithm algorithm); | ||
|
||
/// \cond | ||
bool parse(const QDomElement &el); | ||
void toXml(QXmlStreamWriter *writer) const; | ||
/// \endcond | ||
|
||
QXmpp::HashAlgorithm algorithm() const; | ||
void setAlgorithm(QXmpp::HashAlgorithm algorithm); | ||
|
||
private: | ||
QXmpp::HashAlgorithm m_algorithm = QXmpp::HashAlgorithm::Unknown; | ||
}; | ||
|
||
#endif // QXMPPHASH_H |