aboutsummaryrefslogtreecommitdiff
path: root/src/base/QXmppHash.cpp
diff options
context:
space:
mode:
authorLinus Jahn <lnj@kaidan.im>2022-09-05 17:18:20 +0200
committerLinus Jahn <lnj@kaidan.im>2022-09-06 00:46:56 +0200
commit649d56de33f7dd495f3935f3b02a43b5bd2a2069 (patch)
tree98a48ff9bcb93ac7487a75d73b4afdd59015ce55 /src/base/QXmppHash.cpp
parenta9dc4915371087e2d706fad95d4fccf11745ba63 (diff)
downloadqxmpp-649d56de33f7dd495f3935f3b02a43b5bd2a2069.tar.gz
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.
Diffstat (limited to 'src/base/QXmppHash.cpp')
-rw-r--r--src/base/QXmppHash.cpp222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/base/QXmppHash.cpp b/src/base/QXmppHash.cpp
new file mode 100644
index 00000000..c246d200
--- /dev/null
+++ b/src/base/QXmppHash.cpp
@@ -0,0 +1,222 @@
+// SPDX-FileCopyrightText: 2022 Linus Jahn <lnj@kaidan.im>
+//
+// 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;
+}