From 5d8c328e236f57d7390d32f9ea7bd17a31e1e740 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 26 Apr 2013 22:07:58 +0200
Subject: Removing third-party hash implementations.

Using library/platform implementation instead.

Change-Id: I2457c2dad80e6fdda023a7f31c3906ff10fe09ed

diff --git a/COPYING.thirdparty b/COPYING.thirdparty
index 1ab927d..aeaf066 100644
--- a/COPYING.thirdparty
+++ b/COPYING.thirdparty
@@ -756,48 +756,3 @@ necessary.  Here is a sample; alter the names:
   Ty Coon, President of Vice
 
 That's all there is to it!
-
-
-===========
-LibTomCrypt
-===========
-
-Swiften contains adapted code from LibTomCrypt by Tom St Denis
-LibTomCrypt is free for all purposes under the public domain.
-
-
-===
-MD5
-===
-
-Swiften contains adapted code from L. Peter Deutsch's
-MD5 implementation. Original license below.
-
-Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.
-
-This software is provided 'as-is', without any express or implied
-warranty.  In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-	 claim that you wrote the original software. If you use this software
-	 in a product, an acknowledgment in the product documentation would be
-	 appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
-	 misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
-L. Peter Deutsch
-ghost@aladdin.com
-
-
-=====
-SHA-1
-=====
-
-Swiften contains adapted code from Steve Reid's SHA-1 implementation in C.
-This code is in the public domain.
\ No newline at end of file
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 32d045d..ac0fee4 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -67,7 +67,6 @@
 #include "Swiften/Disco/GetDiscoInfoRequest.h"
 #include "Swiften/Disco/ClientDiscoManager.h"
 #include "Swiften/VCards/GetVCardRequest.h"
-#include "Swiften/StringCodecs/SHA1.h"
 #include "Swiften/StringCodecs/Hexify.h"
 #include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"
 #include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"
@@ -89,6 +88,7 @@
 #include <Swift/Controllers/HighlightEditorController.h>
 #include <Swiften/Client/ClientBlockListManager.h>
 #include <Swift/Controllers/BlockListController.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 namespace Swift {
 
@@ -747,7 +747,7 @@ void MainController::handleVCardReceived(const JID& jid, VCard::ref vCard) {
 	if (!jid.equals(jid_, JID::WithoutResource) || !vCard || vCard->getPhoto().empty()) {
 		return;
 	}
-	std::string hash = Hexify::hexify(SHA1::getHash(vCard->getPhoto()));
+	std::string hash = Hexify::hexify(networkFactories_->getCryptoProvider()->getSHA1Hash(vCard->getPhoto()));
 	if (hash != vCardPhotoHash_) {
 		vCardPhotoHash_ = hash;
 		if (client_ && client_->isAvailable()) {
diff --git a/Swift/Controllers/Storages/AvatarFileStorage.cpp b/Swift/Controllers/Storages/AvatarFileStorage.cpp
index b39e586..792b77b 100644
--- a/Swift/Controllers/Storages/AvatarFileStorage.cpp
+++ b/Swift/Controllers/Storages/AvatarFileStorage.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -12,12 +12,12 @@
 
 #include <Swiften/Base/foreach.h>
 #include <Swiften/Base/String.h>
-#include <Swiften/StringCodecs/SHA1.h>
 #include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 namespace Swift {
 
-AvatarFileStorage::AvatarFileStorage(const boost::filesystem::path& avatarsDir, const boost::filesystem::path& avatarsFile) : avatarsDir(avatarsDir), avatarsFile(avatarsFile) {
+AvatarFileStorage::AvatarFileStorage(const boost::filesystem::path& avatarsDir, const boost::filesystem::path& avatarsFile, CryptoProvider* crypto) : avatarsDir(avatarsDir), avatarsFile(avatarsFile), crypto(crypto) {
 	if (boost::filesystem::exists(avatarsFile)) {
 		try {
 			boost::filesystem::ifstream file(avatarsFile);
@@ -47,7 +47,7 @@ bool AvatarFileStorage::hasAvatar(const std::string& hash) const {
 }
 
 void AvatarFileStorage::addAvatar(const std::string& hash, const ByteArray& avatar) {
-	assert(Hexify::hexify(SHA1::getHash(avatar)) == hash);
+	assert(Hexify::hexify(crypto->getSHA1Hash(avatar)) == hash);
 
 	boost::filesystem::path avatarPath = getAvatarPath(hash);
 	if (!boost::filesystem::exists(avatarPath.parent_path())) {
diff --git a/Swift/Controllers/Storages/AvatarFileStorage.h b/Swift/Controllers/Storages/AvatarFileStorage.h
index b7e73f5..85a6463 100644
--- a/Swift/Controllers/Storages/AvatarFileStorage.h
+++ b/Swift/Controllers/Storages/AvatarFileStorage.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -15,9 +15,11 @@
 #include "Swiften/Avatars/AvatarStorage.h"
 
 namespace Swift {
+	class CryptoProvider;
+
 	class AvatarFileStorage : public AvatarStorage {
 		public:
-			AvatarFileStorage(const boost::filesystem::path& avatarsDir, const boost::filesystem::path& avatarsFile);
+			AvatarFileStorage(const boost::filesystem::path& avatarsDir, const boost::filesystem::path& avatarsFile, CryptoProvider* crypto);
 
 			virtual bool hasAvatar(const std::string& hash) const;
 			virtual void addAvatar(const std::string& hash, const ByteArray& avatar);
@@ -34,6 +36,7 @@ namespace Swift {
 		private:
 			boost::filesystem::path avatarsDir;
 			boost::filesystem::path avatarsFile;
+			CryptoProvider* crypto;
 			typedef std::map<JID, std::string> JIDAvatarMap;
 			JIDAvatarMap jidAvatars;
 	};
diff --git a/Swift/Controllers/Storages/CertificateFileStorage.cpp b/Swift/Controllers/Storages/CertificateFileStorage.cpp
index 55016d5..b5e85d2 100644
--- a/Swift/Controllers/Storages/CertificateFileStorage.cpp
+++ b/Swift/Controllers/Storages/CertificateFileStorage.cpp
@@ -10,14 +10,14 @@
 #include <boost/filesystem/fstream.hpp>
 #include <boost/numeric/conversion/cast.hpp>
 
-#include <Swiften/StringCodecs/SHA1.h>
 #include <Swiften/StringCodecs/Hexify.h>
 #include <Swiften/TLS/CertificateFactory.h>
 #include <Swiften/Base/Log.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 namespace Swift {
 
-CertificateFileStorage::CertificateFileStorage(const boost::filesystem::path& path, CertificateFactory* certificateFactory) : path(path), certificateFactory(certificateFactory) {
+CertificateFileStorage::CertificateFileStorage(const boost::filesystem::path& path, CertificateFactory* certificateFactory, CryptoProvider* crypto) : path(path), certificateFactory(certificateFactory), crypto(crypto) {
 }
 
 bool CertificateFileStorage::hasCertificate(Certificate::ref certificate) const {
@@ -56,7 +56,7 @@ void CertificateFileStorage::addCertificate(Certificate::ref certificate) {
 }
 
 boost::filesystem::path CertificateFileStorage::getCertificatePath(Certificate::ref certificate) const {
-	return path / Hexify::hexify(SHA1::getHash(certificate->toDER()));
+	return path / Hexify::hexify(crypto->getSHA1Hash(certificate->toDER()));
 }
 
 }
diff --git a/Swift/Controllers/Storages/CertificateFileStorage.h b/Swift/Controllers/Storages/CertificateFileStorage.h
index f7a60b9..12151d0 100644
--- a/Swift/Controllers/Storages/CertificateFileStorage.h
+++ b/Swift/Controllers/Storages/CertificateFileStorage.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -12,10 +12,11 @@
 
 namespace Swift {
 	class CertificateFactory;
+	class CryptoProvider;
 
 	class CertificateFileStorage : public CertificateStorage {
 		public:
-			CertificateFileStorage(const boost::filesystem::path& path, CertificateFactory* certificateFactory);
+			CertificateFileStorage(const boost::filesystem::path& path, CertificateFactory* certificateFactory, CryptoProvider* crypto);
 
 			virtual bool hasCertificate(Certificate::ref certificate) const;
 			virtual void addCertificate(Certificate::ref certificate);
@@ -26,6 +27,7 @@ namespace Swift {
 		private:
 			boost::filesystem::path path;
 			CertificateFactory* certificateFactory;
+			CryptoProvider* crypto;
 	};
 
 }
diff --git a/Swift/Controllers/Storages/CertificateFileStorageFactory.h b/Swift/Controllers/Storages/CertificateFileStorageFactory.h
index b215165..6834619 100644
--- a/Swift/Controllers/Storages/CertificateFileStorageFactory.h
+++ b/Swift/Controllers/Storages/CertificateFileStorageFactory.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -11,18 +11,20 @@
 
 namespace Swift {
 	class CertificateFactory;
+	class CryptoProvider;
 
 	class CertificateFileStorageFactory : public CertificateStorageFactory {
 		public:
-			CertificateFileStorageFactory(const boost::filesystem::path& basePath, CertificateFactory* certificateFactory) : basePath(basePath), certificateFactory(certificateFactory) {}
+			CertificateFileStorageFactory(const boost::filesystem::path& basePath, CertificateFactory* certificateFactory, CryptoProvider* crypto) : basePath(basePath), certificateFactory(certificateFactory), crypto(crypto) {}
 
 			virtual CertificateStorage* createCertificateStorage(const JID& profile) const {
 				boost::filesystem::path profilePath = basePath / profile.toString();
-				return new CertificateFileStorage(profilePath / "certificates", certificateFactory);
+				return new CertificateFileStorage(profilePath / "certificates", certificateFactory, crypto);
 			}
 
 		private:
 			boost::filesystem::path basePath;
 			CertificateFactory* certificateFactory;
+			CryptoProvider* crypto;
 	};
 }
diff --git a/Swift/Controllers/Storages/FileStorages.cpp b/Swift/Controllers/Storages/FileStorages.cpp
index cff87d3..357c213 100644
--- a/Swift/Controllers/Storages/FileStorages.cpp
+++ b/Swift/Controllers/Storages/FileStorages.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -13,11 +13,11 @@
 
 namespace Swift {
 
-FileStorages::FileStorages(const boost::filesystem::path& baseDir, const JID& jid) {
+FileStorages::FileStorages(const boost::filesystem::path& baseDir, const JID& jid, CryptoProvider* crypto) {
 	std::string profile = jid.toBare();
-	vcardStorage = new VCardFileStorage(baseDir / profile / "vcards");
+	vcardStorage = new VCardFileStorage(baseDir / profile / "vcards", crypto);
 	capsStorage = new CapsFileStorage(baseDir / "caps");
-	avatarStorage = new AvatarFileStorage(baseDir / "avatars", baseDir / profile / "avatars");
+	avatarStorage = new AvatarFileStorage(baseDir / "avatars", baseDir / profile / "avatars", crypto);
 	rosterStorage = new RosterFileStorage(baseDir / profile / "roster.xml");
 #ifdef SWIFT_EXPERIMENTAL_HISTORY
 	historyStorage = new SQLiteHistoryStorage((baseDir / "history.db").string());
diff --git a/Swift/Controllers/Storages/FileStorages.h b/Swift/Controllers/Storages/FileStorages.h
index 5e89db8..1e914b9 100644
--- a/Swift/Controllers/Storages/FileStorages.h
+++ b/Swift/Controllers/Storages/FileStorages.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -8,7 +8,7 @@
 
 #include <boost/filesystem/path.hpp>
 
-#include "Swiften/Client/Storages.h"
+#include <Swiften/Client/Storages.h>
 
 namespace Swift {
 	class VCardFileStorage;
@@ -17,6 +17,7 @@ namespace Swift {
 	class RosterFileStorage;
 	class HistoryStorage;
 	class JID;
+	class CryptoProvider;
 
 	/**
 	 * A storages implementation that stores all controller data on disk.
@@ -37,7 +38,7 @@ namespace Swift {
 			 * \param jid the subdir in which profile-specific data will be stored. 
 			 *   The bare JID will be used as the subdir name.
 			 */
-			FileStorages(const boost::filesystem::path& baseDir, const JID& jid);
+			FileStorages(const boost::filesystem::path& baseDir, const JID& jid, CryptoProvider*);
 			~FileStorages();
 
 			virtual VCardStorage* getVCardStorage() const;
diff --git a/Swift/Controllers/Storages/FileStoragesFactory.h b/Swift/Controllers/Storages/FileStoragesFactory.h
index 0676bc3..c119dcf 100644
--- a/Swift/Controllers/Storages/FileStoragesFactory.h
+++ b/Swift/Controllers/Storages/FileStoragesFactory.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -10,15 +10,18 @@
 #include "Swift/Controllers/Storages/FileStorages.h"
 
 namespace Swift {
+	class CryptoProvider;
+
 	class FileStoragesFactory : public StoragesFactory {
 		public:
-			FileStoragesFactory(const boost::filesystem::path& basePath) : basePath(basePath) {}
+			FileStoragesFactory(const boost::filesystem::path& basePath, CryptoProvider* crypto) : basePath(basePath), crypto(crypto) {}
 
 			virtual Storages* createStorages(const JID& profile) const {
-				return new FileStorages(basePath, profile);
+				return new FileStorages(basePath, profile, crypto);
 			}
 
 		private:
 			boost::filesystem::path basePath;
+			CryptoProvider* crypto;
 	};
 }
diff --git a/Swift/Controllers/Storages/VCardFileStorage.cpp b/Swift/Controllers/Storages/VCardFileStorage.cpp
index d799a90..633ed58 100644
--- a/Swift/Controllers/Storages/VCardFileStorage.cpp
+++ b/Swift/Controllers/Storages/VCardFileStorage.cpp
@@ -13,8 +13,8 @@
 #include <Swiften/Entity/GenericPayloadPersister.h>
 #include <Swiften/Base/String.h>
 #include <Swiften/StringCodecs/Hexify.h>
-#include <Swiften/StringCodecs/SHA1.h>
 #include <Swiften/Base/foreach.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 #include "Swiften/JID/JID.h"
 #include "Swiften/Elements/VCard.h"
 #include "Swiften/Serializer/PayloadSerializers/VCardSerializer.h"
@@ -25,7 +25,7 @@ using namespace Swift;
 
 typedef GenericPayloadPersister<VCard, VCardParser, VCardSerializer> VCardPersister;
 
-VCardFileStorage::VCardFileStorage(boost::filesystem::path dir) : vcardsPath(dir) {
+VCardFileStorage::VCardFileStorage(boost::filesystem::path dir, CryptoProvider* crypto) : VCardStorage(crypto), vcardsPath(dir), crypto(crypto) {
 	cacheFile = vcardsPath / "phashes";
 	if (boost::filesystem::exists(cacheFile)) {
 		try {
@@ -88,7 +88,7 @@ std::string VCardFileStorage::getPhotoHash(const JID& jid) const {
 std::string VCardFileStorage::getAndUpdatePhotoHash(const JID& jid, VCard::ref vCard) const {
 	std::string hash;
 	if (vCard && !vCard->getPhoto().empty()) {
-		hash = Hexify::hexify(SHA1::getHash(vCard->getPhoto()));
+		hash = Hexify::hexify(crypto->getSHA1Hash(vCard->getPhoto()));
 	}
 	std::pair<PhotoHashMap::iterator, bool> r = photoHashes.insert(std::make_pair(jid, hash));
 	if (r.second) {
diff --git a/Swift/Controllers/Storages/VCardFileStorage.h b/Swift/Controllers/Storages/VCardFileStorage.h
index ba422f4..2c3af3d 100644
--- a/Swift/Controllers/Storages/VCardFileStorage.h
+++ b/Swift/Controllers/Storages/VCardFileStorage.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -14,9 +14,11 @@
 #include "Swiften/VCards/VCardStorage.h"
 
 namespace Swift {
+	class CryptoProvider;
+
 	class VCardFileStorage : public VCardStorage {
 		public:
-			VCardFileStorage(boost::filesystem::path dir);
+			VCardFileStorage(boost::filesystem::path dir, CryptoProvider* crypto);
 
 			virtual VCard::ref getVCard(const JID& jid) const;
 			virtual void setVCard(const JID& jid, VCard::ref v);
@@ -31,6 +33,7 @@ namespace Swift {
 
 		private:
 			boost::filesystem::path vcardsPath;
+			CryptoProvider* crypto;
 			boost::filesystem::path cacheFile;
 			typedef std::map<JID, std::string> PhotoHashMap;
 			mutable PhotoHashMap photoHashes;
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index b44ee2f..839d079 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -159,8 +159,8 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa
 	tabs_ = options.count("no-tabs") && !splitter_ ? NULL : new QtChatTabs(splitter_ != NULL);
 	bool startMinimized = options.count("start-minimized") > 0;
 	applicationPathProvider_ = new PlatformApplicationPathProvider(SWIFT_APPLICATION_NAME);
-	storagesFactory_ = new FileStoragesFactory(applicationPathProvider_->getDataDir());
-	certificateStorageFactory_ = new CertificateFileStorageFactory(applicationPathProvider_->getDataDir(), tlsFactories_.getCertificateFactory());
+	storagesFactory_ = new FileStoragesFactory(applicationPathProvider_->getDataDir(), networkFactories_.getCryptoProvider());
+	certificateStorageFactory_ = new CertificateFileStorageFactory(applicationPathProvider_->getDataDir(), tlsFactories_.getCertificateFactory(), networkFactories_.getCryptoProvider());
 	chatWindowFactory_ = new QtChatWindowFactory(splitter_, settingsHierachy_, qtSettings_, tabs_, "", emoticons);
 	soundPlayer_ = new QtSoundPlayer(applicationPathProvider_);
 
diff --git a/Swiften/Avatars/AvatarManagerImpl.cpp b/Swiften/Avatars/AvatarManagerImpl.cpp
index 78d94dc..7c3baa7 100644
--- a/Swiften/Avatars/AvatarManagerImpl.cpp
+++ b/Swiften/Avatars/AvatarManagerImpl.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -16,11 +16,11 @@
 
 namespace Swift {
 
-AvatarManagerImpl::AvatarManagerImpl(VCardManager* vcardManager, StanzaChannel* stanzaChannel, AvatarStorage* avatarStorage, MUCRegistry* mucRegistry) : avatarStorage(avatarStorage) {
-	vcardUpdateAvatarManager = new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, mucRegistry);
+AvatarManagerImpl::AvatarManagerImpl(VCardManager* vcardManager, StanzaChannel* stanzaChannel, AvatarStorage* avatarStorage, CryptoProvider* crypto, MUCRegistry* mucRegistry) : avatarStorage(avatarStorage) {
+	vcardUpdateAvatarManager = new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto, mucRegistry);
 	combinedAvatarProvider.addProvider(vcardUpdateAvatarManager);
 
-	vcardAvatarManager = new VCardAvatarManager(vcardManager, avatarStorage, mucRegistry);
+	vcardAvatarManager = new VCardAvatarManager(vcardManager, avatarStorage, crypto, mucRegistry);
 	combinedAvatarProvider.addProvider(vcardAvatarManager);
 
 	offlineAvatarManager = new OfflineAvatarManager(avatarStorage);
diff --git a/Swiften/Avatars/AvatarManagerImpl.h b/Swiften/Avatars/AvatarManagerImpl.h
index c2b8956..4f59fe5 100644
--- a/Swiften/Avatars/AvatarManagerImpl.h
+++ b/Swiften/Avatars/AvatarManagerImpl.h
@@ -17,10 +17,11 @@ namespace Swift {
 	class VCardUpdateAvatarManager;
 	class VCardAvatarManager;
 	class OfflineAvatarManager;
+	class CryptoProvider;
 
 	class AvatarManagerImpl : public AvatarManager {
 		public:
-			AvatarManagerImpl(VCardManager*, StanzaChannel*, AvatarStorage*, MUCRegistry* = NULL);
+			AvatarManagerImpl(VCardManager*, StanzaChannel*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL);
 			virtual ~AvatarManagerImpl();
 
 			virtual boost::filesystem::path getAvatarPath(const JID&) const;
diff --git a/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp b/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp
index 81dc12c..dd76fb6 100644
--- a/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp
+++ b/Swiften/Avatars/UnitTest/VCardAvatarManagerTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -19,8 +19,9 @@
 #include <Swiften/MUC/MUCRegistry.h>
 #include <Swiften/Queries/IQRouter.h>
 #include <Swiften/Client/DummyStanzaChannel.h>
-#include <Swiften/StringCodecs/SHA1.h>
 #include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -37,6 +38,8 @@ class VCardAvatarManagerTest : public CppUnit::TestFixture {
 	public:
 		class TestVCardStorage : public VCardStorage {
 			public:
+				TestVCardStorage(CryptoProvider* crypto) : VCardStorage(crypto), crypto(crypto) {}
+
 				virtual VCard::ref getVCard(const JID& jid) const {
 					VCardMap::const_iterator i = vcards.find(jid);
 					if (i != vcards.end()) {
@@ -57,7 +60,7 @@ class VCardAvatarManagerTest : public CppUnit::TestFixture {
 					}
 					VCard::ref vCard = getVCard(jid);
 					if (vCard && !vCard->getPhoto().empty()) {
-						return Hexify::hexify(SHA1::getHash(vCard->getPhoto()));
+						return Hexify::hexify(crypto->getSHA1Hash(vCard->getPhoto()));
 					}
 					else {
 						return "";
@@ -69,19 +72,21 @@ class VCardAvatarManagerTest : public CppUnit::TestFixture {
 			private:
 				typedef std::map<JID, VCard::ref> VCardMap;
 				VCardMap vcards;
+				CryptoProvider* crypto;
 		};
 
 		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
 			ownJID = JID("foo@fum.com/bum");
 			stanzaChannel = new DummyStanzaChannel();
 			stanzaChannel->setAvailable(true);
 			iqRouter = new IQRouter(stanzaChannel);
 			mucRegistry = new DummyMUCRegistry();
 			avatarStorage = new AvatarMemoryStorage();
-			vcardStorage = new TestVCardStorage();
+			vcardStorage = new TestVCardStorage(crypto.get());
 			vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage);
 			avatar1 = createByteArray("abcdefg");
-			avatar1Hash = Hexify::hexify(SHA1::getHash(avatar1));
+			avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1));
 			user1 = JID("user1@bar.com/bla");
 			user2 = JID("user2@foo.com/baz");
 		}
@@ -153,7 +158,7 @@ class VCardAvatarManagerTest : public CppUnit::TestFixture {
 
 	private:
 		boost::shared_ptr<VCardAvatarManager> createManager() {
-			boost::shared_ptr<VCardAvatarManager> result(new VCardAvatarManager(vcardManager, avatarStorage, mucRegistry));
+			boost::shared_ptr<VCardAvatarManager> result(new VCardAvatarManager(vcardManager, avatarStorage, crypto.get(), mucRegistry));
 			result->onAvatarChanged.connect(boost::bind(&VCardAvatarManagerTest::handleAvatarChanged, this, _1));
 			return result;
 		}
@@ -197,6 +202,7 @@ class VCardAvatarManagerTest : public CppUnit::TestFixture {
 		std::vector<JID> changes;
 		JID user1;
 		JID user2;
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(VCardAvatarManagerTest);
diff --git a/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp b/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp
index 60e76f8..01b10a2 100644
--- a/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp
+++ b/Swiften/Avatars/UnitTest/VCardUpdateAvatarManagerTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -19,8 +19,9 @@
 #include <Swiften/MUC/MUCRegistry.h>
 #include <Swiften/Queries/IQRouter.h>
 #include <Swiften/Client/DummyStanzaChannel.h>
-#include <Swiften/StringCodecs/SHA1.h>
 #include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -37,19 +38,21 @@ class VCardUpdateAvatarManagerTest : public CppUnit::TestFixture {
 
 	public:
 		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
 			ownJID = JID("foo@fum.com/bum");
 			stanzaChannel = new DummyStanzaChannel();
 			stanzaChannel->setAvailable(true);
 			iqRouter = new IQRouter(stanzaChannel);
 			mucRegistry = new DummyMUCRegistry();
 			avatarStorage = new AvatarMemoryStorage();
-			vcardStorage = new VCardMemoryStorage();
+			vcardStorage = new VCardMemoryStorage(crypto.get());
 			vcardManager = new VCardManager(ownJID, iqRouter, vcardStorage);
 			avatar1 = createByteArray("abcdefg");
-			avatar1Hash = Hexify::hexify(SHA1::getHash(avatar1));
+			avatar1Hash = Hexify::hexify(crypto->getSHA1Hash(avatar1));
 			user1 = JID("user1@bar.com/bla");
 			user2 = JID("user2@foo.com/baz");
 		}
+		
 
 		void tearDown() {
 			delete vcardManager;
@@ -113,7 +116,7 @@ class VCardUpdateAvatarManagerTest : public CppUnit::TestFixture {
 			vcardManager->requestVCard(JID("foo@bar.com"));
 			stanzaChannel->onIQReceived(createVCardResult(ByteArray()));
 			
-			CPPUNIT_ASSERT(!avatarStorage->hasAvatar(Hexify::hexify(SHA1::getHash(ByteArray()))));
+			CPPUNIT_ASSERT(!avatarStorage->hasAvatar(Hexify::hexify(crypto->getSHA1Hash(ByteArray()))));
 			CPPUNIT_ASSERT_EQUAL(std::string(), testling->getAvatarHash(JID("foo@bar.com")));
 		}
 
@@ -150,7 +153,7 @@ class VCardUpdateAvatarManagerTest : public CppUnit::TestFixture {
 
 	private:
 		boost::shared_ptr<VCardUpdateAvatarManager> createManager() {
-			boost::shared_ptr<VCardUpdateAvatarManager> result(new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, mucRegistry));
+			boost::shared_ptr<VCardUpdateAvatarManager> result(new VCardUpdateAvatarManager(vcardManager, stanzaChannel, avatarStorage, crypto.get(), mucRegistry));
 			result->onAvatarChanged.connect(boost::bind(&VCardUpdateAvatarManagerTest::handleAvatarChanged, this, _1));
 			return result;
 		}
@@ -192,6 +195,7 @@ class VCardUpdateAvatarManagerTest : public CppUnit::TestFixture {
 		std::vector<JID> changes;
 		JID user1;
 		JID user2;
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(VCardUpdateAvatarManagerTest);
diff --git a/Swiften/Avatars/VCardAvatarManager.cpp b/Swiften/Avatars/VCardAvatarManager.cpp
index ef1d293..8212a6e 100644
--- a/Swiften/Avatars/VCardAvatarManager.cpp
+++ b/Swiften/Avatars/VCardAvatarManager.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -9,7 +9,7 @@
 #include <boost/bind.hpp>
 
 #include <Swiften/Elements/VCard.h>
-#include <Swiften/StringCodecs/SHA1.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 #include <Swiften/StringCodecs/Hexify.h>
 #include <Swiften/Avatars/AvatarStorage.h>
 #include <Swiften/MUC/MUCRegistry.h>
@@ -18,7 +18,7 @@
 
 namespace Swift {
 
-VCardAvatarManager::VCardAvatarManager(VCardManager* vcardManager, AvatarStorage* avatarStorage, MUCRegistry* mucRegistry) : vcardManager_(vcardManager), avatarStorage_(avatarStorage), mucRegistry_(mucRegistry) {
+VCardAvatarManager::VCardAvatarManager(VCardManager* vcardManager, AvatarStorage* avatarStorage, CryptoProvider* crypto, MUCRegistry* mucRegistry) : vcardManager_(vcardManager), avatarStorage_(avatarStorage), crypto_(crypto), mucRegistry_(mucRegistry) {
 	vcardManager_->onVCardChanged.connect(boost::bind(&VCardAvatarManager::handleVCardChanged, this, _1));
 }
 
@@ -36,7 +36,7 @@ std::string VCardAvatarManager::getAvatarHash(const JID& jid) const {
 		if (!avatarStorage_->hasAvatar(hash)) {
 			VCard::ref vCard = vcardManager_->getVCard(avatarJID);
 			if (vCard) {
-				std::string newHash = Hexify::hexify(SHA1::getHash(vCard->getPhoto()));
+				std::string newHash = Hexify::hexify(crypto_->getSHA1Hash(vCard->getPhoto()));
 				if (newHash != hash) {
 					// Shouldn't happen, but sometimes seem to. Might be fixed if we
 					// move to a safer backend.
diff --git a/Swiften/Avatars/VCardAvatarManager.h b/Swiften/Avatars/VCardAvatarManager.h
index ed2ba5d..9c6943e 100644
--- a/Swiften/Avatars/VCardAvatarManager.h
+++ b/Swiften/Avatars/VCardAvatarManager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -14,10 +14,11 @@ namespace Swift {
 	class MUCRegistry;
 	class AvatarStorage;
 	class VCardManager;
+	class CryptoProvider;
 
 	class SWIFTEN_API VCardAvatarManager : public AvatarProvider {
 		public:
-			VCardAvatarManager(VCardManager*, AvatarStorage*, MUCRegistry* = NULL);
+			VCardAvatarManager(VCardManager*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL);
 
 			std::string getAvatarHash(const JID&) const;
 
@@ -28,6 +29,7 @@ namespace Swift {
 		private:
 			VCardManager* vcardManager_;
 			AvatarStorage* avatarStorage_;
+			CryptoProvider* crypto_;
 			MUCRegistry* mucRegistry_;
 	};
 }
diff --git a/Swiften/Avatars/VCardUpdateAvatarManager.cpp b/Swiften/Avatars/VCardUpdateAvatarManager.cpp
index 3c086d5..adbefd5 100644
--- a/Swiften/Avatars/VCardUpdateAvatarManager.cpp
+++ b/Swiften/Avatars/VCardUpdateAvatarManager.cpp
@@ -11,7 +11,7 @@
 #include <Swiften/Client/StanzaChannel.h>
 #include <Swiften/Elements/VCardUpdate.h>
 #include <Swiften/VCards/GetVCardRequest.h>
-#include <Swiften/StringCodecs/SHA1.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 #include <Swiften/StringCodecs/Hexify.h>
 #include <Swiften/Avatars/AvatarStorage.h>
 #include <Swiften/MUC/MUCRegistry.h>
@@ -20,7 +20,7 @@
 
 namespace Swift {
 
-VCardUpdateAvatarManager::VCardUpdateAvatarManager(VCardManager* vcardManager, StanzaChannel* stanzaChannel, AvatarStorage* avatarStorage, MUCRegistry* mucRegistry) : vcardManager_(vcardManager), avatarStorage_(avatarStorage), mucRegistry_(mucRegistry) {
+VCardUpdateAvatarManager::VCardUpdateAvatarManager(VCardManager* vcardManager, StanzaChannel* stanzaChannel, AvatarStorage* avatarStorage, CryptoProvider* crypto, MUCRegistry* mucRegistry) : vcardManager_(vcardManager), avatarStorage_(avatarStorage), crypto_(crypto), mucRegistry_(mucRegistry) {
 	stanzaChannel->onPresenceReceived.connect(boost::bind(&VCardUpdateAvatarManager::handlePresenceReceived, this, _1));
 	stanzaChannel->onAvailableChanged.connect(boost::bind(&VCardUpdateAvatarManager::handleStanzaChannelAvailableChanged, this, _1));
 	vcardManager_->onVCardChanged.connect(boost::bind(&VCardUpdateAvatarManager::handleVCardChanged, this, _1, _2));
@@ -54,7 +54,7 @@ void VCardUpdateAvatarManager::handleVCardChanged(const JID& from, VCard::ref vC
 		setAvatarHash(from, "");
 	}
 	else {
-		std::string hash = Hexify::hexify(SHA1::getHash(vCard->getPhoto()));
+		std::string hash = Hexify::hexify(crypto_->getSHA1Hash(vCard->getPhoto()));
 		if (!avatarStorage_->hasAvatar(hash)) {
 			avatarStorage_->addAvatar(hash, vCard->getPhoto());
 		}
diff --git a/Swiften/Avatars/VCardUpdateAvatarManager.h b/Swiften/Avatars/VCardUpdateAvatarManager.h
index 43e1d62..3409f99 100644
--- a/Swiften/Avatars/VCardUpdateAvatarManager.h
+++ b/Swiften/Avatars/VCardUpdateAvatarManager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -21,10 +21,11 @@ namespace Swift {
 	class AvatarStorage;
 	class StanzaChannel;
 	class VCardManager;
+	class CryptoProvider;
 
 	class SWIFTEN_API VCardUpdateAvatarManager : public AvatarProvider, public boost::bsignals::trackable {
 		public:
-			VCardUpdateAvatarManager(VCardManager*, StanzaChannel*, AvatarStorage*, MUCRegistry* = NULL);
+			VCardUpdateAvatarManager(VCardManager*, StanzaChannel*, AvatarStorage*, CryptoProvider* crypto, MUCRegistry* = NULL);
 
 			std::string getAvatarHash(const JID&) const;
 
@@ -38,6 +39,7 @@ namespace Swift {
 		private:
 			VCardManager* vcardManager_;
 			AvatarStorage* avatarStorage_;
+			CryptoProvider* crypto_;
 			MUCRegistry* mucRegistry_;
 			std::map<JID, std::string> avatarHashes_;
 	};
diff --git a/Swiften/Base/Algorithm.h b/Swiften/Base/Algorithm.h
index 4e68e70..d5edab1 100644
--- a/Swiften/Base/Algorithm.h
+++ b/Swiften/Base/Algorithm.h
@@ -99,6 +99,11 @@ namespace Swift {
 		target.insert(target.end(), source.begin(), source.end());
 	}
 
+	template<typename Source, typename Target>
+	void assign(Target& target, const Source& source) {
+		target.assign(source.begin(), source.end());
+	}
+
 	template<typename A, typename B, typename C, typename D> 
 	B get(const std::map<A, B, C, D>& map, const A& key, const B& defaultValue) {
 		typename std::map<A, B, C, D>::const_iterator i = map.find(key);
diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp
index 00f0f44..54e0b83 100644
--- a/Swiften/Client/Client.cpp
+++ b/Swiften/Client/Client.cpp
@@ -38,7 +38,7 @@
 namespace Swift {
 
 Client::Client(const JID& jid, const SafeString& password, NetworkFactories* networkFactories, Storages* storages) : CoreClient(jid, password, networkFactories), storages(storages) {
-	memoryStorages = new MemoryStorages();
+	memoryStorages = new MemoryStorages(networkFactories->getCryptoProvider());
 
 	softwareVersionResponder = new SoftwareVersionResponder(getIQRouter());
 	softwareVersionResponder->start();
@@ -53,14 +53,14 @@ Client::Client(const JID& jid, const SafeString& password, NetworkFactories* net
 
 	stanzaChannelPresenceSender = new StanzaChannelPresenceSender(getStanzaChannel());
 	directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender);
-	discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender);
+	discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender, networkFactories->getCryptoProvider());
 
 	mucRegistry = new MUCRegistry();
 	mucManager = new MUCManager(getStanzaChannel(), getIQRouter(), directedPresenceSender, mucRegistry);
 
 	vcardManager = new VCardManager(jid, getIQRouter(), getStorages()->getVCardStorage());
-	avatarManager = new AvatarManagerImpl(vcardManager, getStanzaChannel(), getStorages()->getAvatarStorage(), mucRegistry);
-	capsManager = new CapsManager(getStorages()->getCapsStorage(), getStanzaChannel(), getIQRouter());
+	avatarManager = new AvatarManagerImpl(vcardManager, getStanzaChannel(), getStorages()->getAvatarStorage(), networkFactories->getCryptoProvider(), mucRegistry);
+	capsManager = new CapsManager(getStorages()->getCapsStorage(), getStanzaChannel(), getIQRouter(), networkFactories->getCryptoProvider());
 	entityCapsManager = new EntityCapsManager(capsManager, getStanzaChannel());
 
 	nickManager = new NickManagerImpl(jid.toBare(), vcardManager);
@@ -122,7 +122,7 @@ void Client::setSoftwareVersion(const std::string& name, const std::string& vers
 
 void Client::handleConnected() {
 #ifdef SWIFT_EXPERIMENTAL_FT
-	fileTransferManager = new FileTransferManagerImpl(getJID(), jingleSessionManager, getIQRouter(), getEntityCapsProvider(), presenceOracle, getNetworkFactories()->getConnectionFactory(), getNetworkFactories()->getConnectionServerFactory(), getNetworkFactories()->getTimerFactory(), getNetworkFactories()->getNATTraverser());
+	fileTransferManager = new FileTransferManagerImpl(getJID(), jingleSessionManager, getIQRouter(), getEntityCapsProvider(), presenceOracle, getNetworkFactories()->getConnectionFactory(), getNetworkFactories()->getConnectionServerFactory(), getNetworkFactories()->getTimerFactory(), getNetworkFactories()->getNATTraverser(), getNetworkFactories()->getCryptoProvider());
 #else
 	fileTransferManager = new DummyFileTransferManager();
 #endif
diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp
index c5a5c23..f03cbaa 100644
--- a/Swiften/Client/ClientSession.cpp
+++ b/Swiften/Client/ClientSession.cpp
@@ -40,6 +40,7 @@
 #include <Swiften/SASL/EXTERNALClientAuthenticator.h>
 #include <Swiften/SASL/SCRAMSHA1ClientAuthenticator.h>
 #include <Swiften/SASL/DIGESTMD5ClientAuthenticator.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 #include <Swiften/Session/SessionStream.h>
 #include <Swiften/TLS/CertificateTrustChecker.h>
 #include <Swiften/TLS/ServerIdentityVerifier.h>
@@ -57,11 +58,13 @@ namespace Swift {
 ClientSession::ClientSession(
 		const JID& jid, 
 		boost::shared_ptr<SessionStream> stream,
-		IDNConverter* idnConverter) :
+		IDNConverter* idnConverter,
+		CryptoProvider* crypto) :
 			localJID(jid),	
 			state(Initial), 
 			stream(stream),
 			idnConverter(idnConverter),
+			crypto(crypto),
 			allowPLAINOverNonTLS(false),
 			useStreamCompression(true),
 			useTLS(UseTLSWhenAvailable),
@@ -226,7 +229,7 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
 					plus &= !finishMessage.empty();
 				}
 				s << boost::uuids::random_generator()();
-				SCRAMSHA1ClientAuthenticator* scramAuthenticator = new SCRAMSHA1ClientAuthenticator(s.str(), plus, idnConverter);
+				SCRAMSHA1ClientAuthenticator* scramAuthenticator = new SCRAMSHA1ClientAuthenticator(s.str(), plus, idnConverter, crypto);
 				if (plus) {
 					scramAuthenticator->setTLSChannelBindingData(finishMessage);
 				}
@@ -239,11 +242,11 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
 				state = WaitingForCredentials;
 				onNeedCredentials();
 			}
-			else if (streamFeatures->hasAuthenticationMechanism("DIGEST-MD5") && DIGESTMD5ClientAuthenticator::canBeUsed()) {
+			else if (streamFeatures->hasAuthenticationMechanism("DIGEST-MD5") && crypto->isMD5AllowedForCrypto()) {
 				std::ostringstream s;
 				s << boost::uuids::random_generator()();
 				// FIXME: Host should probably be the actual host
-				authenticator = new DIGESTMD5ClientAuthenticator(localJID.getDomain(), s.str());
+				authenticator = new DIGESTMD5ClientAuthenticator(localJID.getDomain(), s.str(), crypto);
 				state = WaitingForCredentials;
 				onNeedCredentials();
 			}
diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h
index 842412d..6ef624e 100644
--- a/Swiften/Client/ClientSession.h
+++ b/Swiften/Client/ClientSession.h
@@ -23,6 +23,7 @@ namespace Swift {
 	class ClientAuthenticator;
 	class CertificateTrustChecker;
 	class IDNConverter;
+	class CryptoProvider;
 
 	class SWIFTEN_API ClientSession : public boost::enable_shared_from_this<ClientSession> {
 		public:
@@ -67,8 +68,8 @@ namespace Swift {
 
 			~ClientSession();
 
-			static boost::shared_ptr<ClientSession> create(const JID& jid, boost::shared_ptr<SessionStream> stream, IDNConverter* idnConverter) {
-				return boost::shared_ptr<ClientSession>(new ClientSession(jid, stream, idnConverter));
+			static boost::shared_ptr<ClientSession> create(const JID& jid, boost::shared_ptr<SessionStream> stream, IDNConverter* idnConverter, CryptoProvider* crypto) {
+				return boost::shared_ptr<ClientSession>(new ClientSession(jid, stream, idnConverter, crypto));
 			}
 
 			State getState() const {
@@ -133,7 +134,8 @@ namespace Swift {
 			ClientSession(
 					const JID& jid, 
 					boost::shared_ptr<SessionStream>,
-					IDNConverter* idnConverter);
+					IDNConverter* idnConverter,
+					CryptoProvider* crypto);
 
 			void finishSession(Error::Type error);
 			void finishSession(boost::shared_ptr<Swift::Error> error);
@@ -164,6 +166,7 @@ namespace Swift {
 			State state;
 			boost::shared_ptr<SessionStream> stream;
 			IDNConverter* idnConverter;
+			CryptoProvider* crypto;
 			bool allowPLAINOverNonTLS;
 			bool useStreamCompression;
 			UseTLS useTLS;
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 07124ed..4438135 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -142,7 +142,7 @@ void CoreClient::connect(const ClientOptions& o) {
 }
 
 void CoreClient::bindSessionToStream() {
-	session_ = ClientSession::create(jid_, sessionStream_, networkFactories->getIDNConverter());
+	session_ = ClientSession::create(jid_, sessionStream_, networkFactories->getIDNConverter(), networkFactories->getCryptoProvider());
 	session_->setCertificateTrustChecker(certificateTrustChecker);
 	session_->setUseStreamCompression(options.useStreamCompression);
 	session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS);
diff --git a/Swiften/Client/MemoryStorages.cpp b/Swiften/Client/MemoryStorages.cpp
index 703e9ff..885d74f 100644
--- a/Swiften/Client/MemoryStorages.cpp
+++ b/Swiften/Client/MemoryStorages.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -13,8 +13,8 @@
 
 namespace Swift {
 
-MemoryStorages::MemoryStorages() {
-	vcardStorage = new VCardMemoryStorage();
+MemoryStorages::MemoryStorages(CryptoProvider* crypto) {
+	vcardStorage = new VCardMemoryStorage(crypto);
 	capsStorage = new CapsMemoryStorage();
 	avatarStorage = new AvatarMemoryStorage();
 	rosterStorage = new RosterMemoryStorage();
diff --git a/Swiften/Client/MemoryStorages.h b/Swiften/Client/MemoryStorages.h
index 403a89a..68ec285 100644
--- a/Swiften/Client/MemoryStorages.h
+++ b/Swiften/Client/MemoryStorages.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -10,6 +10,7 @@
 
 namespace Swift {
 	class VCardMemoryStorage;
+	class CryptoProvider;
 
 	/**
 	 * An implementation of Storages for storing all
@@ -17,7 +18,7 @@ namespace Swift {
 	 */
 	class MemoryStorages : public Storages {
 		public:
-			MemoryStorages();
+			MemoryStorages(CryptoProvider*);
 			~MemoryStorages();
 
 			virtual VCardStorage* getVCardStorage() const;
diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp
index 63c922c..4ef6727 100644
--- a/Swiften/Client/UnitTest/ClientSessionTest.cpp
+++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp
@@ -33,6 +33,8 @@
 #include <Swiften/Elements/ResourceBind.h>
 #include <Swiften/TLS/SimpleCertificate.h>
 #include <Swiften/TLS/BlindCertificateTrustChecker.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -71,6 +73,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
 
 	public:
 		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
 			idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create());
 			server = boost::make_shared<MockSessionStream>();
 			sessionFinishedReceived = false;
@@ -342,7 +345,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
 
 	private:
 		boost::shared_ptr<ClientSession> createSession() {
-			boost::shared_ptr<ClientSession> session = ClientSession::create(JID("me@foo.com"), server, idnConverter.get());
+			boost::shared_ptr<ClientSession> session = ClientSession::create(JID("me@foo.com"), server, idnConverter.get(), crypto.get());
 			session->onFinished.connect(boost::bind(&ClientSessionTest::handleSessionFinished, this, _1));
 			session->onNeedCredentials.connect(boost::bind(&ClientSessionTest::handleSessionNeedCredentials, this));
 			session->setAllowPLAINOverNonTLS(true);
@@ -625,6 +628,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
 		bool needCredentials;
 		boost::shared_ptr<Error> sessionFinishedError;
 		BlindCertificateTrustChecker* blindCertificateTrustChecker;
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(ClientSessionTest);
diff --git a/Swiften/Client/UnitTest/NickResolverTest.cpp b/Swiften/Client/UnitTest/NickResolverTest.cpp
index dfc90fe..a8b011c 100644
--- a/Swiften/Client/UnitTest/NickResolverTest.cpp
+++ b/Swiften/Client/UnitTest/NickResolverTest.cpp
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #include <cppunit/extensions/HelperMacros.h>
 #include <cppunit/extensions/TestFactoryRegistry.h>
 
@@ -14,6 +20,8 @@
 #include <Swiften/VCards/VCardMemoryStorage.h>
 #include <Swiften/Queries/IQRouter.h>
 #include <Swiften/Client/DummyStanzaChannel.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -34,11 +42,12 @@ class NickResolverTest : public CppUnit::TestFixture {
 
 	public:
 		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
 			ownJID_ = JID("kev@wonderland.lit");
 			xmppRoster_ = new XMPPRosterImpl();
 			stanzaChannel_ = new DummyStanzaChannel();
 		  iqRouter_ = new IQRouter(stanzaChannel_);
-			vCardStorage_ = new VCardMemoryStorage();
+			vCardStorage_ = new VCardMemoryStorage(crypto.get());
 			vCardManager_ = new VCardManager(ownJID_, iqRouter_, vCardStorage_);
 			registry_ = new MUCRegistry();
 			resolver_ = new NickResolver(ownJID_, xmppRoster_, vCardManager_, registry_);
@@ -144,7 +153,7 @@ class NickResolverTest : public CppUnit::TestFixture {
 		MUCRegistry* registry_;
 		NickResolver* resolver_;
 		JID ownJID_;
-
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(NickResolverTest);
diff --git a/Swiften/Component/ComponentHandshakeGenerator.cpp b/Swiften/Component/ComponentHandshakeGenerator.cpp
index 79ba9b3..495d530 100644
--- a/Swiften/Component/ComponentHandshakeGenerator.cpp
+++ b/Swiften/Component/ComponentHandshakeGenerator.cpp
@@ -6,19 +6,19 @@
 
 #include <Swiften/Component/ComponentHandshakeGenerator.h>
 #include <Swiften/StringCodecs/Hexify.h>
-#include <Swiften/StringCodecs/SHA1.h>
 #include <Swiften/Base/String.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 namespace Swift {
 
-std::string ComponentHandshakeGenerator::getHandshake(const std::string& streamID, const std::string& secret) {
+std::string ComponentHandshakeGenerator::getHandshake(const std::string& streamID, const std::string& secret, CryptoProvider* crypto) {
 	std::string concatenatedString = streamID + secret;
 	String::replaceAll(concatenatedString, '&', "&amp;");
 	String::replaceAll(concatenatedString, '<', "&lt;");
 	String::replaceAll(concatenatedString, '>', "&gt;");
 	String::replaceAll(concatenatedString, '\'', "&apos;");
 	String::replaceAll(concatenatedString, '"', "&quot;");
-	return Hexify::hexify(SHA1::getHash(createByteArray(concatenatedString)));
+	return Hexify::hexify(crypto->getSHA1Hash(createByteArray(concatenatedString)));
 }
 
 }
diff --git a/Swiften/Component/ComponentHandshakeGenerator.h b/Swiften/Component/ComponentHandshakeGenerator.h
index c897fdc..e0e3ef8 100644
--- a/Swiften/Component/ComponentHandshakeGenerator.h
+++ b/Swiften/Component/ComponentHandshakeGenerator.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -11,9 +11,11 @@
 #include <Swiften/Base/API.h>
 
 namespace Swift {
+	class CryptoProvider;
+
 	class SWIFTEN_API ComponentHandshakeGenerator {
 		public:
-			static std::string getHandshake(const std::string& streamID, const std::string& secret);
+			static std::string getHandshake(const std::string& streamID, const std::string& secret, CryptoProvider* crypto);
 	};
 
 }
diff --git a/Swiften/Component/ComponentSession.cpp b/Swiften/Component/ComponentSession.cpp
index 3269f23..7925b23 100644
--- a/Swiften/Component/ComponentSession.cpp
+++ b/Swiften/Component/ComponentSession.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -17,7 +17,7 @@
 
 namespace Swift {
 
-ComponentSession::ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream> stream) : jid(jid), secret(secret), stream(stream), state(Initial) {
+ComponentSession::ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream> stream, CryptoProvider* crypto) : jid(jid), secret(secret), stream(stream), crypto(crypto), state(Initial) {
 }
 
 ComponentSession::~ComponentSession() {
@@ -46,7 +46,7 @@ void ComponentSession::sendStanza(boost::shared_ptr<Stanza> stanza) {
 void ComponentSession::handleStreamStart(const ProtocolHeader& header) {
 	checkState(WaitingForStreamStart);
 	state = Authenticating;
-	stream->writeElement(ComponentHandshake::ref(new ComponentHandshake(ComponentHandshakeGenerator::getHandshake(header.getID(), secret))));
+	stream->writeElement(ComponentHandshake::ref(new ComponentHandshake(ComponentHandshakeGenerator::getHandshake(header.getID(), secret, crypto))));
 }
 
 void ComponentSession::handleElement(boost::shared_ptr<Element> element) {
diff --git a/Swiften/Component/ComponentSession.h b/Swiften/Component/ComponentSession.h
index bc1ea5f..3103335 100644
--- a/Swiften/Component/ComponentSession.h
+++ b/Swiften/Component/ComponentSession.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -20,6 +20,7 @@
 
 namespace Swift {
 	class ComponentAuthenticator;
+	class CryptoProvider;
 
 	class SWIFTEN_API ComponentSession : public boost::enable_shared_from_this<ComponentSession> {
 		public:
@@ -42,8 +43,8 @@ namespace Swift {
 
 			~ComponentSession();
 
-			static boost::shared_ptr<ComponentSession> create(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream> stream) {
-				return boost::shared_ptr<ComponentSession>(new ComponentSession(jid, secret, stream));
+			static boost::shared_ptr<ComponentSession> create(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream> stream, CryptoProvider* crypto) {
+				return boost::shared_ptr<ComponentSession>(new ComponentSession(jid, secret, stream, crypto));
 			}
 
 			State getState() const {
@@ -61,7 +62,7 @@ namespace Swift {
 			boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived;
 		
 		private:
-			ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream>);
+			ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream>, CryptoProvider*);
 
 			void finishSession(Error::Type error);
 			void finishSession(boost::shared_ptr<Swift::Error> error);
@@ -78,6 +79,7 @@ namespace Swift {
 			JID jid;
 			std::string secret;
 			boost::shared_ptr<SessionStream> stream;
+			CryptoProvider* crypto;
 			boost::shared_ptr<Swift::Error> error;
 			State state;
 	};
diff --git a/Swiften/Component/CoreComponent.cpp b/Swiften/Component/CoreComponent.cpp
index aac2d89..de3b66e 100644
--- a/Swiften/Component/CoreComponent.cpp
+++ b/Swiften/Component/CoreComponent.cpp
@@ -67,7 +67,7 @@ void CoreComponent::handleConnectorFinished(boost::shared_ptr<Connection> connec
 		sessionStream_->onDataRead.connect(boost::bind(&CoreComponent::handleDataRead, this, _1));
 		sessionStream_->onDataWritten.connect(boost::bind(&CoreComponent::handleDataWritten, this, _1));
 
-		session_ = ComponentSession::create(jid_, secret_, sessionStream_);
+		session_ = ComponentSession::create(jid_, secret_, sessionStream_, networkFactories->getCryptoProvider());
 		stanzaChannel_->setSession(session_);
 		session_->onFinished.connect(boost::bind(&CoreComponent::handleSessionFinished, this, _1));
 		session_->start();
diff --git a/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp b/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp
index fd8f6fc..280e46e 100644
--- a/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp
+++ b/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -8,6 +8,8 @@
 #include <cppunit/extensions/TestFactoryRegistry.h>
 
 #include <Swiften/Component/ComponentHandshakeGenerator.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -18,16 +20,22 @@ class ComponentHandshakeGeneratorTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
+		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
+		}
+
 		void testGetHandshake() {
-			std::string result = ComponentHandshakeGenerator::getHandshake("myid", "mysecret");
+			std::string result = ComponentHandshakeGenerator::getHandshake("myid", "mysecret", crypto.get());
 			CPPUNIT_ASSERT_EQUAL(std::string("4011cd31f9b99ac089a0cd7ce297da7323fa2525"), result);
 		}
 
 		void testGetHandshake_SpecialChars() {
-			std::string result = ComponentHandshakeGenerator::getHandshake("&<", ">'\"");
+			std::string result = ComponentHandshakeGenerator::getHandshake("&<", ">'\"", crypto.get());
 			CPPUNIT_ASSERT_EQUAL(std::string("33631b3e0aaeb2a11c4994c917919324028873fe"), result);
 		}
 
+	private:
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(ComponentHandshakeGeneratorTest);
diff --git a/Swiften/Component/UnitTest/ComponentSessionTest.cpp b/Swiften/Component/UnitTest/ComponentSessionTest.cpp
index 238d0b0..97fde63 100644
--- a/Swiften/Component/UnitTest/ComponentSessionTest.cpp
+++ b/Swiften/Component/UnitTest/ComponentSessionTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -14,6 +14,8 @@
 #include <Swiften/Component/ComponentSession.h>
 #include <Swiften/Elements/ComponentHandshake.h>
 #include <Swiften/Elements/AuthFailure.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -28,6 +30,7 @@ class ComponentSessionTest : public CppUnit::TestFixture {
 		void setUp() {
 			server = boost::make_shared<MockSessionStream>();
 			sessionFinishedReceived = false;
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
 		}
 
 		void testStart() {
@@ -70,7 +73,7 @@ class ComponentSessionTest : public CppUnit::TestFixture {
 
 	private:
 		boost::shared_ptr<ComponentSession> createSession() {
-			boost::shared_ptr<ComponentSession> session = ComponentSession::create(JID("service.foo.com"), "servicesecret", server);
+			boost::shared_ptr<ComponentSession> session = ComponentSession::create(JID("service.foo.com"), "servicesecret", server, crypto.get());
 			session->onFinished.connect(boost::bind(&ComponentSessionTest::handleSessionFinished, this, _1));
 			return session;
 		}
@@ -212,6 +215,7 @@ class ComponentSessionTest : public CppUnit::TestFixture {
 		bool sessionFinishedReceived;
 		bool needCredentials;
 		boost::shared_ptr<Error> sessionFinishedError;
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(ComponentSessionTest);
diff --git a/Swiften/Crypto/CommonCryptoCryptoProvider.cpp b/Swiften/Crypto/CommonCryptoCryptoProvider.cpp
new file mode 100644
index 0000000..f1810ba
--- /dev/null
+++ b/Swiften/Crypto/CommonCryptoCryptoProvider.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Crypto/CommonCryptoCryptoProvider.h>
+
+#include <CommonCrypto/CommonDigest.h>
+#include <CommonCrypto/CommonHMAC.h>
+#include <cassert>
+
+#include <Swiften/Crypto/Hash.h>
+#include <Swiften/Base/ByteArray.h>
+#include <boost/numeric/conversion/cast.hpp>
+
+using namespace Swift;
+
+namespace {
+	class SHA1Hash : public Hash {
+		public:
+			SHA1Hash() : finalized(false) {
+				if (!CC_SHA1_Init(&context)) {
+					assert(false);
+				}
+			}
+
+			~SHA1Hash() {
+			}
+
+			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual std::vector<unsigned char> getHash() {
+				assert(!finalized);
+				std::vector<unsigned char> result(CC_SHA1_DIGEST_LENGTH);
+				CC_SHA1_Final(vecptr(result), &context);
+				return result;
+			}
+
+		private:
+			template<typename ContainerType>
+			Hash& updateInternal(const ContainerType& data) {
+				assert(!finalized);
+				if (!CC_SHA1_Update(&context, vecptr(data), boost::numeric_cast<CC_LONG>(data.size()))) {
+					assert(false);
+				}
+				return *this;
+			}
+
+		private:
+			CC_SHA1_CTX context;
+			bool finalized;
+	};
+
+	class MD5Hash : public Hash {
+		public:
+			MD5Hash() : finalized(false) {
+				if (!CC_MD5_Init(&context)) {
+					assert(false);
+				}
+			}
+
+			~MD5Hash() {
+			}
+
+			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual std::vector<unsigned char> getHash() {
+				assert(!finalized);
+				std::vector<unsigned char> result(CC_MD5_DIGEST_LENGTH);
+				CC_MD5_Final(vecptr(result), &context);
+				return result;
+			}
+
+		private:
+			template<typename ContainerType>
+			Hash& updateInternal(const ContainerType& data) {
+				assert(!finalized);
+				if (!CC_MD5_Update(&context, vecptr(data), boost::numeric_cast<CC_LONG>(data.size()))) {
+					assert(false);
+				}
+				return *this;
+			}
+
+		private:
+			CC_MD5_CTX context;
+			bool finalized;
+	};
+
+	template<typename T>
+	class HMACHash : public Hash {
+		public:
+			HMACHash(const T& key) : finalized(false) {
+				CCHmacInit(&context, kCCHmacAlgSHA1, vecptr(key), key.size());
+			}
+
+			~HMACHash() {
+			}
+
+			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual std::vector<unsigned char> getHash() {
+				assert(!finalized);
+				std::vector<unsigned char> result(CC_SHA1_DIGEST_LENGTH);
+				CCHmacFinal(&context, vecptr(result));
+				return result;
+			}
+
+		private:
+			template<typename ContainerType>
+			Hash& updateInternal(const ContainerType& data) {
+				assert(!finalized);
+				CCHmacUpdate(&context, vecptr(data), boost::numeric_cast<CC_LONG>(data.size()));
+				return *this;
+			}
+
+		private:
+			CCHmacContext context;
+			bool finalized;
+	};
+}
+
+CommonCryptoCryptoProvider::CommonCryptoCryptoProvider() {
+}
+
+CommonCryptoCryptoProvider::~CommonCryptoCryptoProvider() {
+}
+
+Hash* CommonCryptoCryptoProvider::createSHA1() {
+	return new SHA1Hash();
+}
+
+Hash* CommonCryptoCryptoProvider::createMD5() {
+	return new MD5Hash();
+}
+
+Hash* CommonCryptoCryptoProvider::createHMACSHA1(const SafeByteArray& key) {
+	return new HMACHash<SafeByteArray>(key);
+}
+
+Hash* CommonCryptoCryptoProvider::createHMACSHA1(const ByteArray& key) {
+	return new HMACHash<ByteArray>(key);
+}
+
+
+bool CommonCryptoCryptoProvider::isMD5AllowedForCrypto() const {
+	return true;
+}
+
diff --git a/Swiften/Crypto/CommonCryptoCryptoProvider.h b/Swiften/Crypto/CommonCryptoCryptoProvider.h
new file mode 100644
index 0000000..8072c0d
--- /dev/null
+++ b/Swiften/Crypto/CommonCryptoCryptoProvider.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Base/Override.h>
+
+namespace Swift {
+	class CommonCryptoCryptoProvider : public CryptoProvider {
+		public:
+			CommonCryptoCryptoProvider();
+			~CommonCryptoCryptoProvider();
+
+			virtual Hash* createSHA1() SWIFTEN_OVERRIDE;
+			virtual Hash* createMD5() SWIFTEN_OVERRIDE;
+			virtual Hash* createHMACSHA1(const SafeByteArray& key) SWIFTEN_OVERRIDE;
+			virtual Hash* createHMACSHA1(const ByteArray& key) SWIFTEN_OVERRIDE;
+			virtual bool isMD5AllowedForCrypto() const SWIFTEN_OVERRIDE;
+	};
+}
diff --git a/Swiften/Crypto/CryptoProvider.cpp b/Swiften/Crypto/CryptoProvider.cpp
new file mode 100644
index 0000000..0189de4
--- /dev/null
+++ b/Swiften/Crypto/CryptoProvider.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Crypto/CryptoProvider.h>
+
+#include <boost/shared_ptr.hpp>
+
+using namespace Swift;
+
+CryptoProvider::~CryptoProvider() {
+}
diff --git a/Swiften/Crypto/CryptoProvider.h b/Swiften/Crypto/CryptoProvider.h
new file mode 100644
index 0000000..afee8c4
--- /dev/null
+++ b/Swiften/Crypto/CryptoProvider.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/Base/SafeByteArray.h>
+#include <Swiften/Crypto/Hash.h>
+
+namespace Swift {
+	class Hash;
+
+	class CryptoProvider {
+		public:
+			virtual ~CryptoProvider();
+
+			virtual Hash* createSHA1() = 0;
+			virtual Hash* createMD5() = 0;
+			virtual Hash* createHMACSHA1(const SafeByteArray& key) = 0;
+			virtual Hash* createHMACSHA1(const ByteArray& key) = 0;
+			virtual bool isMD5AllowedForCrypto() const = 0;
+
+			// Convenience
+			template<typename T> ByteArray getSHA1Hash(const T& data) {
+				return boost::shared_ptr<Hash>(createSHA1())->update(data).getHash();
+			}
+
+			template<typename T> ByteArray getMD5Hash(const T& data) {
+				return boost::shared_ptr<Hash>(createMD5())->update(data).getHash();
+			}
+
+			template<typename T, typename U> ByteArray getHMACSHA1(const T& key, const U& data) {
+				return boost::shared_ptr<Hash>(createHMACSHA1(key))->update(data).getHash();
+			}
+	};
+}
diff --git a/Swiften/Crypto/Hash.cpp b/Swiften/Crypto/Hash.cpp
new file mode 100644
index 0000000..35c7e70
--- /dev/null
+++ b/Swiften/Crypto/Hash.cpp
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Crypto/Hash.h>
+
+using namespace Swift;
+
+Hash::~Hash() {
+}
diff --git a/Swiften/Crypto/Hash.h b/Swiften/Crypto/Hash.h
new file mode 100644
index 0000000..37c6ec8
--- /dev/null
+++ b/Swiften/Crypto/Hash.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013  Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/Base/SafeByteArray.h>
+
+namespace Swift {
+	class Hash {
+		public:
+			virtual ~Hash();
+
+			virtual Hash& update(const ByteArray& data) = 0;
+			virtual Hash& update(const SafeByteArray& data) = 0;
+
+			virtual std::vector<unsigned char> getHash() = 0;
+	};
+}
diff --git a/Swiften/Crypto/OpenSSLCryptoProvider.cpp b/Swiften/Crypto/OpenSSLCryptoProvider.cpp
new file mode 100644
index 0000000..afe73aa
--- /dev/null
+++ b/Swiften/Crypto/OpenSSLCryptoProvider.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Crypto/OpenSSLCryptoProvider.h>
+
+#include <openssl/sha.h>
+#include <openssl/md5.h>
+#include <openssl/hmac.h>
+#include <cassert>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Swiften/Crypto/Hash.h>
+#include <Swiften/Base/ByteArray.h>
+
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+using namespace Swift;
+
+namespace {
+	class SHA1Hash : public Hash {
+		public:
+			SHA1Hash() : finalized(false) {
+				if (!SHA1_Init(&context)) {
+					assert(false);
+				}
+			}
+
+			~SHA1Hash() {
+			}
+
+			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual std::vector<unsigned char> getHash() {
+				assert(!finalized);
+				std::vector<unsigned char> result(SHA_DIGEST_LENGTH);
+				SHA1_Final(vecptr(result), &context);
+				return result;
+			}
+
+		private:
+			template<typename ContainerType>
+			Hash& updateInternal(const ContainerType& data) {
+				assert(!finalized);
+				if (!SHA1_Update(&context, vecptr(data), data.size())) {
+					assert(false);
+				}
+				return *this;
+			}
+
+		private:
+			SHA_CTX context;
+			bool finalized;
+	};
+
+	class MD5Hash : public Hash {
+		public:
+			MD5Hash() : finalized(false) {
+				if (!MD5_Init(&context)) {
+					assert(false);
+				}
+			}
+
+			~MD5Hash() {
+			}
+
+			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual std::vector<unsigned char> getHash() {
+				assert(!finalized);
+				std::vector<unsigned char> result(MD5_DIGEST_LENGTH);
+				MD5_Final(vecptr(result), &context);
+				return result;
+			}
+
+		private:
+			template<typename ContainerType>
+			Hash& updateInternal(const ContainerType& data) {
+				assert(!finalized);
+				if (!MD5_Update(&context, vecptr(data), data.size())) {
+					assert(false);
+				}
+				return *this;
+			}
+
+		private:
+			MD5_CTX context;
+			bool finalized;
+	};
+
+
+	template<typename T>
+	class HMACHash : public Hash {
+		public:
+			HMACHash(const T& key) : finalized(false) {
+				HMAC_CTX_init(&context);
+				HMAC_Init(&context, vecptr(key), boost::numeric_cast<int>(key.size()), EVP_sha1());
+			}
+
+			~HMACHash() {
+				HMAC_CTX_cleanup(&context);
+			}
+
+			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual std::vector<unsigned char> getHash() {
+				assert(!finalized);
+				std::vector<unsigned char> result(SHA_DIGEST_LENGTH);
+				unsigned int len = SHA_DIGEST_LENGTH;
+				HMAC_Final(&context, vecptr(result), &len);
+				return result;
+			}
+
+		private:
+			template<typename ContainerType>
+			Hash& updateInternal(const ContainerType& data) {
+				assert(!finalized);
+				HMAC_Update(&context, vecptr(data), data.size());
+				return *this;
+			}
+
+		private:
+			HMAC_CTX context;
+			bool finalized;
+	};
+}
+
+OpenSSLCryptoProvider::OpenSSLCryptoProvider() {
+}
+
+OpenSSLCryptoProvider::~OpenSSLCryptoProvider() {
+}
+
+Hash* OpenSSLCryptoProvider::createSHA1() {
+	return new SHA1Hash();
+}
+
+Hash* OpenSSLCryptoProvider::createMD5() {
+	return new MD5Hash();
+}
+
+Hash* OpenSSLCryptoProvider::createHMACSHA1(const SafeByteArray& key) {
+	return new HMACHash<SafeByteArray>(key);
+}
+
+Hash* OpenSSLCryptoProvider::createHMACSHA1(const ByteArray& key) {
+	return new HMACHash<ByteArray>(key);
+}
+
+bool OpenSSLCryptoProvider::isMD5AllowedForCrypto() const {
+	return true;
+}
+
diff --git a/Swiften/Crypto/OpenSSLCryptoProvider.h b/Swiften/Crypto/OpenSSLCryptoProvider.h
new file mode 100644
index 0000000..e9ca37b
--- /dev/null
+++ b/Swiften/Crypto/OpenSSLCryptoProvider.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013  Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Base/Override.h>
+
+namespace Swift {
+	class OpenSSLCryptoProvider : public CryptoProvider {
+		public:
+			OpenSSLCryptoProvider();
+			~OpenSSLCryptoProvider();
+
+			virtual Hash* createSHA1() SWIFTEN_OVERRIDE;
+			virtual Hash* createMD5() SWIFTEN_OVERRIDE;
+			virtual Hash* createHMACSHA1(const SafeByteArray& key) SWIFTEN_OVERRIDE;
+			virtual Hash* createHMACSHA1(const ByteArray& key) SWIFTEN_OVERRIDE;
+			virtual bool isMD5AllowedForCrypto() const SWIFTEN_OVERRIDE;
+	};
+}
diff --git a/Swiften/Crypto/PlatformCryptoProvider.cpp b/Swiften/Crypto/PlatformCryptoProvider.cpp
new file mode 100644
index 0000000..ab0fa7b
--- /dev/null
+++ b/Swiften/Crypto/PlatformCryptoProvider.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
+
+#include <cassert>
+
+#include <Swiften/Base/Platform.h>
+#if defined(SWIFTEN_PLATFORM_WIN32)
+#include <Swiften/Crypto/WindowsCryptoProvider.h>
+#elif defined(HAVE_COMMONCRYPTO_CRYPTO_PROVIDER)
+#include <Swiften/Crypto/CommonCryptoCryptoProvider.h>
+#elif defined(HAVE_OPENSSL_CRYPTO_PROVIDER)
+#include <Swiften/Crypto/OpenSSLCryptoProvider.h>
+#endif
+
+using namespace Swift;
+
+CryptoProvider* PlatformCryptoProvider::create() {
+#if defined(SWIFTEN_PLATFORM_WIN32)
+	return new WindowsCryptoProvider();
+#elif defined(HAVE_COMMONCRYPTO_CRYPTO_PROVIDER)
+	return new CommonCryptoCryptoProvider();
+#elif defined(HAVE_OPENSSL_CRYPTO_PROVIDER)
+	return new OpenSSLCryptoProvider();
+#endif
+	assert(false);
+	return NULL;
+}
diff --git a/Swiften/Crypto/PlatformCryptoProvider.h b/Swiften/Crypto/PlatformCryptoProvider.h
new file mode 100644
index 0000000..0721887
--- /dev/null
+++ b/Swiften/Crypto/PlatformCryptoProvider.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/API.h>
+
+namespace Swift {
+	class CryptoProvider;
+
+	namespace PlatformCryptoProvider {
+		SWIFTEN_API CryptoProvider* create();
+	}
+}
diff --git a/Swiften/Crypto/SConscript b/Swiften/Crypto/SConscript
new file mode 100644
index 0000000..ce4bdae
--- /dev/null
+++ b/Swiften/Crypto/SConscript
@@ -0,0 +1,28 @@
+Import("swiften_env", "env")
+
+
+objects = swiften_env.SwiftenObject([
+	"CryptoProvider.cpp",
+	"Hash.cpp"
+])
+
+myenv = swiften_env.Clone()
+if myenv["PLATFORM"] == "win32" :
+	objects += myenv.SwiftenObject(["WindowsCryptoProvider.cpp"])
+if myenv.get("HAVE_OPENSSL", False) :
+	myenv.Append(CPPDEFINES = ["HAVE_OPENSSL_CRYPTO_PROVIDER"])
+	objects += myenv.SwiftenObject(["OpenSSLCryptoProvider.cpp"])
+if myenv["PLATFORM"] == "darwin" and myenv["target"] == "native" :
+	myenv.Append(CPPDEFINES = ["HAVE_COMMONCRYPTO_CRYPTO_PROVIDER"])
+	objects += myenv.SwiftenObject(["CommonCryptoCryptoProvider.cpp"])
+
+objects += myenv.SwiftenObject(["PlatformCryptoProvider.cpp"])
+
+swiften_env.Append(SWIFTEN_OBJECTS = [objects])
+
+if env["TEST"] :
+	test_env = myenv.Clone()
+	test_env.UseFlags(swiften_env["CPPUNIT_FLAGS"])
+	env.Append(UNITTEST_OBJECTS = test_env.SwiftenObject([
+				File("UnitTest/CryptoProviderTest.cpp"),
+	]))
diff --git a/Swiften/Crypto/UnitTest/CryptoProviderTest.cpp b/Swiften/Crypto/UnitTest/CryptoProviderTest.cpp
new file mode 100644
index 0000000..1e2275a
--- /dev/null
+++ b/Swiften/Crypto/UnitTest/CryptoProviderTest.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2010-2013 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/Base/Platform.h>
+#include <QA/Checker/IO.h>
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#ifdef SWIFTEN_PLATFORM_WIN32
+#include <Swiften/Crypto/WindowsCryptoProvider.h>
+#endif
+#ifdef HAVE_OPENSSL_CRYPTO_PROVIDER
+#include <Swiften/Crypto/OpenSSLCryptoProvider.h>
+#endif
+#ifdef HAVE_OPENSSL_CRYPTO_PROVIDER
+#include <Swiften/Crypto/CommonCryptoCryptoProvider.h>
+#endif
+#include <Swiften/Crypto/Hash.h>
+
+using namespace Swift;
+
+template <typename CryptoProviderType>
+class CryptoProviderTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(CryptoProviderTest);
+
+		CPPUNIT_TEST(testGetSHA1Hash);
+		CPPUNIT_TEST(testGetSHA1Hash_TwoUpdates);
+		CPPUNIT_TEST(testGetSHA1Hash_NoData);
+		CPPUNIT_TEST(testGetSHA1HashStatic);
+		CPPUNIT_TEST(testGetSHA1HashStatic_Twice);
+		CPPUNIT_TEST(testGetSHA1HashStatic_NoData);
+
+		CPPUNIT_TEST(testGetMD5Hash_Empty);
+		CPPUNIT_TEST(testGetMD5Hash_Alphabet);
+		CPPUNIT_TEST(testMD5Incremental);
+
+		CPPUNIT_TEST(testGetHMACSHA1);
+		CPPUNIT_TEST(testGetHMACSHA1_KeyLongerThanBlockSize);
+		
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		void setUp() {
+			provider = new CryptoProviderType();
+		}
+
+		void tearDown() {
+			delete provider;
+		}
+
+		////////////////////////////////////////////////////////////	
+		// SHA-1
+		////////////////////////////////////////////////////////////	
+		
+		void testGetSHA1Hash() {
+			boost::shared_ptr<Hash> sha = boost::shared_ptr<Hash>(provider->createSHA1());
+			sha->update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
+
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha->getHash());
+		}
+
+		void testGetSHA1Hash_TwoUpdates() {
+			boost::shared_ptr<Hash> sha = boost::shared_ptr<Hash>(provider->createSHA1());
+			sha->update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<"));
+			sha->update(createByteArray("http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
+
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha->getHash());
+		}
+
+		void testGetSHA1Hash_NoData() {
+			boost::shared_ptr<Hash> sha = boost::shared_ptr<Hash>(provider->createSHA1());
+			sha->update(std::vector<unsigned char>());
+
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09"), sha->getHash());
+		}
+
+		void testGetSHA1HashStatic() {
+			ByteArray result(provider->getSHA1Hash(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<")));
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), result);
+		}
+
+
+		void testGetSHA1HashStatic_Twice() {
+			ByteArray input(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
+			provider->getSHA1Hash(input);
+			ByteArray result(provider->getSHA1Hash(input));
+
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), result);
+		}
+
+		void testGetSHA1HashStatic_NoData() {
+			ByteArray result(provider->getSHA1Hash(ByteArray()));
+
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09"), result);
+		}
+		
+		
+		////////////////////////////////////////////////////////////	
+		// MD5
+		////////////////////////////////////////////////////////////	
+
+		void testGetMD5Hash_Empty() {
+			ByteArray result(provider->getMD5Hash(createByteArray("")));
+
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e", 16), result);
+		}
+
+		void testGetMD5Hash_Alphabet() {
+			ByteArray result(provider->getMD5Hash(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")));
+
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f", 16), result);
+		}
+
+		void testMD5Incremental() {
+			boost::shared_ptr<Hash> testling = boost::shared_ptr<Hash>(provider->createMD5());
+			testling->update(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
+			testling->update(createByteArray("abcdefghijklmnopqrstuvwxyz0123456789"));
+
+			ByteArray result = testling->getHash();
+
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f", 16), result);
+		}
+
+
+		////////////////////////////////////////////////////////////	
+		// HMAC-SHA1
+		////////////////////////////////////////////////////////////	
+
+		void testGetHMACSHA1() {
+			ByteArray result(provider->getHMACSHA1(createSafeByteArray("foo"), createByteArray("foobar")));
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\xa4\xee\xba\x8e\x63\x3d\x77\x88\x69\xf5\x68\xd0\x5a\x1b\x3d\xc7\x2b\xfd\x4\xdd"), result);
+		}
+
+		void testGetHMACSHA1_KeyLongerThanBlockSize() {
+			ByteArray result(provider->getHMACSHA1(createSafeByteArray("---------|---------|---------|---------|---------|----------|---------|"), createByteArray("foobar")));
+			CPPUNIT_ASSERT_EQUAL(createByteArray("\xd6""n""\x8f""P|1""\xd3"",""\x6"" ""\xb9\xe3""gg""\x8e\xcf"" ]+""\xa"), result);
+		}
+
+	private:
+		CryptoProviderType* provider;
+};
+
+#ifdef SWIFTEN_PLATFORM_WIN32
+CPPUNIT_TEST_SUITE_REGISTRATION(CryptoProviderTest<WindowsCryptoProvider>);
+#endif
+#ifdef HAVE_OPENSSL_CRYPTO_PROVIDER
+CPPUNIT_TEST_SUITE_REGISTRATION(CryptoProviderTest<OpenSSLCryptoProvider>);
+#endif
+#ifdef HAVE_COMMONCRYPTO_CRYPTO_PROVIDER
+CPPUNIT_TEST_SUITE_REGISTRATION(CryptoProviderTest<CommonCryptoCryptoProvider>);
+#endif
diff --git a/Swiften/Crypto/WindowsCryptoProvider.cpp b/Swiften/Crypto/WindowsCryptoProvider.cpp
new file mode 100644
index 0000000..7cc6a46
--- /dev/null
+++ b/Swiften/Crypto/WindowsCryptoProvider.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Swiften/Crypto/WindowsCryptoProvider.h>
+
+#include <Windows.h>
+#define SECURITY_WIN32
+#include <security.h>
+#include <Wincrypt.h>
+#include <cassert>
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Crypto/Hash.h>
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/Base/Algorithm.h>
+#include <Swiften/Base/WindowsRegistry.h>
+
+using namespace Swift;
+
+struct WindowsCryptoProvider::Private {
+	HCRYPTPROV context;
+};
+
+namespace {
+	class WindowsHash : public Hash {
+		public:
+			WindowsHash(HCRYPTPROV context, ALG_ID algorithm) : hash(NULL) {
+				if (!CryptCreateHash(context, algorithm, 0, 0, &hash)) {
+					assert(false);
+				}
+			}
+
+			~WindowsHash() {
+				CryptDestroyHash(hash);
+			}
+
+			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual std::vector<unsigned char> getHash() {
+				std::vector<unsigned char> result;
+				DWORD hashLength = sizeof(DWORD);
+				DWORD hashSize;
+				CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0);
+				result.resize(static_cast<size_t>(hashSize));
+				if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) {
+					assert(false);
+				}
+				result.resize(static_cast<size_t>(hashSize));
+				return result;
+			}
+
+		private:
+			template<typename ContainerType>
+			Hash& updateInternal(const ContainerType& data) {
+				if (!CryptHashData(hash, const_cast<BYTE*>(vecptr(data)), data.size(), 0)) {
+					assert(false);
+				}
+				return *this;
+			}
+
+		private:
+			HCRYPTHASH hash;
+	};
+
+#if 0
+	// Haven't tested the code below properly yet, but figured out after writing
+	// it that PLAINTEXTKEYBLOB doesn't work on XP or 2k, and the workaround is a
+	// bit too ugly to try this now. So, using our own algorithm for now.  See
+	// http://support.microsoft.com/kb/228786/en-us
+	
+	// MSDN describes this as PLAINTEXTKEYBLOB, but this struct doesn't exist,
+	// and seems to even conflict with the PLAINTEXTKEYBLOB constant. Redefining
+	// here.
+	struct PlainTextKeyBlob {
+		BLOBHEADER hdr;
+		DWORD dwKeySize;
+	};
+
+	class HMACHash : public Hash {
+		public:
+			template<typename T>
+			HMACHash(HCRYPTPROV context, const T& rawKey) : hash(NULL) {
+				// Import raw key
+				T blobData(sizeof(PlainTextKeyBlob) + rawKey.size());
+				PlainTextKeyBlob* blob = reinterpret_cast<PlainTextKeyBlob*>(vecptr(blobData));
+				blob->hdr.bType = PLAINTEXTKEYBLOB;
+				blob->hdr.bVersion = CUR_BLOB_VERSION;
+				blob->hdr.reserved = 0;
+				blob->hdr.aiKeyAlg = CALG_RC2;
+				blob->dwKeySize = rawKey.size();
+				std::copy(rawKey.begin(), rawKey.end(), blobData.begin() + sizeof(PlainTextKeyBlob));
+				HCRYPTKEY key;
+				if (!CryptImportKey(context, vecptr(blobData), blobData.size(), 0, CRYPT_IPSEC_HMAC_KEY, &key)) {
+					assert(false);
+					return;
+				}
+
+				// Create hash
+				if (!CryptCreateHash(context, CALG_HMAC, key, 0, &hash)) {
+					assert(false);
+					return;
+				}
+				ZeroMemory(&info, sizeof(info));
+				info.HashAlgid = CALG_SHA1;
+			}
+
+			~HMACHash() {
+				CryptDestroyHash(hash);
+			}
+
+			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual std::vector<unsigned char> getHash() {
+				std::vector<unsigned char> result;
+				DWORD hashLength = sizeof(DWORD);
+				DWORD hashSize;
+				CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0);
+				result.resize(static_cast<size_t>(hashSize));
+				if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) {
+					assert(false);
+				}
+				result.resize(static_cast<size_t>(hashSize));
+				return result;
+			}
+
+		private:
+			template<typename ContainerType>
+			Hash& updateInternal(const ContainerType& data) {
+				if (!CryptHashData(hash, const_cast<BYTE*>(vecptr(data)), data.size(), 0)) {
+					assert(false);
+				}
+				return *this;
+			}
+
+		private:
+			HCRYPTHASH hash;
+			HMAC_INFO info;
+	};
+#endif
+
+	// Simple implementation. You can only call 'update' once.
+	template<typename T>
+	class HMACHash : public Hash {
+		public:
+			HMACHash(const T& key, CryptoProvider* crypto) : crypto(crypto), finished(false) {
+				if (key.size() <= BLOCK_SIZE) {
+					paddedKey = key;
+				}
+				else {
+					assign(paddedKey, crypto->getSHA1Hash(key));
+				}
+				paddedKey.resize(BLOCK_SIZE, 0x0);
+			}
+
+			~HMACHash() {
+			}
+
+			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
+				return updateInternal(data);
+			}
+
+			virtual std::vector<unsigned char> getHash() {
+				return result;
+			}
+
+		private:
+			template<typename ContainerType>
+			Hash& updateInternal(const ContainerType& data) {
+				assert(!finished);
+
+				// Create the first value
+				T x(paddedKey);
+				for (unsigned int i = 0; i < x.size(); ++i) {
+					x[i] ^= 0x36;
+				}
+				append(x, data);
+
+				// Create the second value
+				T y(paddedKey);
+				for (unsigned int i = 0; i < y.size(); ++i) {
+					y[i] ^= 0x5c;
+				}
+				append(y, crypto->getSHA1Hash(x));
+				result = crypto->getSHA1Hash(y);
+
+				finished = true;
+				return *this;
+			}
+
+		private:
+			static const int BLOCK_SIZE = 64;
+			CryptoProvider* crypto;
+			T paddedKey;
+			SafeByteArray data;
+			bool finished;
+			std::vector<unsigned char> result;
+	};
+
+
+}
+
+WindowsCryptoProvider::WindowsCryptoProvider() {
+	p = boost::make_shared<Private>();
+	if (!CryptAcquireContext(&p->context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+		assert(false);
+	}
+}
+
+WindowsCryptoProvider::~WindowsCryptoProvider() {
+	CryptReleaseContext(p->context, 0);
+}
+
+Hash* WindowsCryptoProvider::createSHA1() {
+	return new WindowsHash(p->context, CALG_SHA1);
+}
+
+Hash* WindowsCryptoProvider::createMD5() {
+	return new WindowsHash(p->context, CALG_MD5);
+}
+
+bool WindowsCryptoProvider::isMD5AllowedForCrypto() const {
+	return !WindowsRegistry::isFIPSEnabled();
+}
+
+Hash* WindowsCryptoProvider::createHMACSHA1(const SafeByteArray& key) {
+	return new HMACHash<SafeByteArray>(key, this);
+}
+
+Hash* WindowsCryptoProvider::createHMACSHA1(const ByteArray& key) {
+	return new HMACHash<ByteArray>(key, this);
+}
diff --git a/Swiften/Crypto/WindowsCryptoProvider.h b/Swiften/Crypto/WindowsCryptoProvider.h
new file mode 100644
index 0000000..242d4c2
--- /dev/null
+++ b/Swiften/Crypto/WindowsCryptoProvider.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013  Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Base/Override.h>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace Swift {
+	class WindowsCryptoProvider : public CryptoProvider, public boost::noncopyable {
+		public:
+			WindowsCryptoProvider();
+			~WindowsCryptoProvider();
+
+			virtual Hash* createSHA1() SWIFTEN_OVERRIDE;
+			virtual Hash* createMD5() SWIFTEN_OVERRIDE;
+			virtual Hash* createHMACSHA1(const SafeByteArray& key) SWIFTEN_OVERRIDE;
+			virtual Hash* createHMACSHA1(const ByteArray& key) SWIFTEN_OVERRIDE;
+			virtual bool isMD5AllowedForCrypto() const SWIFTEN_OVERRIDE;
+
+		private:
+			struct Private;
+			boost::shared_ptr<Private> p;
+	};
+}
diff --git a/Swiften/Disco/CapsInfoGenerator.cpp b/Swiften/Disco/CapsInfoGenerator.cpp
index 6d84984..cb93182 100644
--- a/Swiften/Disco/CapsInfoGenerator.cpp
+++ b/Swiften/Disco/CapsInfoGenerator.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -11,7 +11,7 @@
 #include <Swiften/Base/foreach.h>
 #include <Swiften/Elements/DiscoInfo.h>
 #include <Swiften/Elements/FormField.h>
-#include <Swiften/StringCodecs/SHA1.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 #include <Swiften/StringCodecs/Base64.h>
 
 namespace {
@@ -22,7 +22,7 @@ namespace {
 
 namespace Swift {
 
-CapsInfoGenerator::CapsInfoGenerator(const std::string& node) : node_(node) {
+CapsInfoGenerator::CapsInfoGenerator(const std::string& node, CryptoProvider* crypto) : node_(node), crypto_(crypto) {
 }
 
 CapsInfo CapsInfoGenerator::generateCapsInfo(const DiscoInfo& discoInfo) const {
@@ -57,7 +57,7 @@ CapsInfo CapsInfoGenerator::generateCapsInfo(const DiscoInfo& discoInfo) const {
 		}
 	}
 
-	std::string version(Base64::encode(SHA1::getHash(createByteArray(serializedCaps))));
+	std::string version(Base64::encode(crypto_->getSHA1Hash(createByteArray(serializedCaps))));
 	return CapsInfo(node_, version, "sha-1");
 }
 
diff --git a/Swiften/Disco/CapsInfoGenerator.h b/Swiften/Disco/CapsInfoGenerator.h
index 62958e7..17a01dd 100644
--- a/Swiften/Disco/CapsInfoGenerator.h
+++ b/Swiften/Disco/CapsInfoGenerator.h
@@ -12,14 +12,16 @@
 
 namespace Swift {
 	class DiscoInfo;
+	class CryptoProvider;
 
 	class SWIFTEN_API CapsInfoGenerator {
 		public:
-			CapsInfoGenerator(const std::string& node);
+			CapsInfoGenerator(const std::string& node, CryptoProvider* crypto);
 
 			CapsInfo generateCapsInfo(const DiscoInfo& discoInfo) const;
 
 		private:
 			std::string node_;
+			CryptoProvider* crypto_;
 	};
 }
diff --git a/Swiften/Disco/CapsManager.cpp b/Swiften/Disco/CapsManager.cpp
index 66eb47e..18f8745 100644
--- a/Swiften/Disco/CapsManager.cpp
+++ b/Swiften/Disco/CapsManager.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -17,7 +17,7 @@
 
 namespace Swift {
 
-CapsManager::CapsManager(CapsStorage* capsStorage, StanzaChannel* stanzaChannel, IQRouter* iqRouter) : iqRouter(iqRouter), capsStorage(capsStorage), warnOnInvalidHash(true) {
+CapsManager::CapsManager(CapsStorage* capsStorage, StanzaChannel* stanzaChannel, IQRouter* iqRouter, CryptoProvider* crypto) : iqRouter(iqRouter), crypto(crypto), capsStorage(capsStorage), warnOnInvalidHash(true) {
 	stanzaChannel->onPresenceReceived.connect(boost::bind(&CapsManager::handlePresenceReceived, this, _1));
 	stanzaChannel->onAvailableChanged.connect(boost::bind(&CapsManager::handleStanzaChannelAvailableChanged, this, _1));
 }
@@ -51,7 +51,7 @@ void CapsManager::handleStanzaChannelAvailableChanged(bool available) {
 
 void CapsManager::handleDiscoInfoReceived(const JID& from, const std::string& hash, DiscoInfo::ref discoInfo, ErrorPayload::ref error) {
 	requestedDiscoInfos.erase(hash);
-	if (error || !discoInfo || CapsInfoGenerator("").generateCapsInfo(*discoInfo.get()).getVersion() != hash) {
+	if (error || !discoInfo || CapsInfoGenerator("", crypto).generateCapsInfo(*discoInfo.get()).getVersion() != hash) {
 		if (warnOnInvalidHash && !error &&  discoInfo) {
 			std::cerr << "Warning: Caps from " << from.toString() << " do not verify" << std::endl;
 		}
diff --git a/Swiften/Disco/CapsManager.h b/Swiften/Disco/CapsManager.h
index 9f1d83b..3529812 100644
--- a/Swiften/Disco/CapsManager.h
+++ b/Swiften/Disco/CapsManager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -22,10 +22,11 @@ namespace Swift {
 	class IQRouter;
 	class JID;
 	class CapsStorage;
+	class CryptoProvider;
 
 	class SWIFTEN_API CapsManager : public CapsProvider, public boost::bsignals::trackable { 
 		public:
-			CapsManager(CapsStorage*, StanzaChannel*, IQRouter*);
+			CapsManager(CapsStorage*, StanzaChannel*, IQRouter*, CryptoProvider*);
 
 			DiscoInfo::ref getCaps(const std::string&) const;
 
@@ -42,6 +43,7 @@ namespace Swift {
 
 		private:
 			IQRouter* iqRouter;
+			CryptoProvider* crypto;
 			CapsStorage* capsStorage;
 			bool warnOnInvalidHash;
 			std::set<std::string> requestedDiscoInfos;
diff --git a/Swiften/Disco/ClientDiscoManager.cpp b/Swiften/Disco/ClientDiscoManager.cpp
index cca0144..f6683a8 100644
--- a/Swiften/Disco/ClientDiscoManager.cpp
+++ b/Swiften/Disco/ClientDiscoManager.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -12,7 +12,7 @@
 
 namespace Swift {
 
-ClientDiscoManager::ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender) {
+ClientDiscoManager::ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender, CryptoProvider* crypto) : crypto(crypto) {
 	discoInfoResponder = new DiscoInfoResponder(iqRouter);
 	discoInfoResponder->start();
 	this->presenceSender = new PayloadAddingPresenceSender(presenceSender);
@@ -29,7 +29,7 @@ void ClientDiscoManager::setCapsNode(const std::string& node) {
 }
 
 void ClientDiscoManager::setDiscoInfo(const DiscoInfo& discoInfo) {
-	capsInfo = CapsInfo::ref(new CapsInfo(CapsInfoGenerator(capsNode).generateCapsInfo(discoInfo)));
+	capsInfo = CapsInfo::ref(new CapsInfo(CapsInfoGenerator(capsNode, crypto).generateCapsInfo(discoInfo)));
 	discoInfoResponder->clearDiscoInfo();
 	discoInfoResponder->setDiscoInfo(discoInfo);
 	discoInfoResponder->setDiscoInfo(capsInfo->getNode() + "#" + capsInfo->getVersion(), discoInfo);
diff --git a/Swiften/Disco/ClientDiscoManager.h b/Swiften/Disco/ClientDiscoManager.h
index 0cae40e..a9ed10a 100644
--- a/Swiften/Disco/ClientDiscoManager.h
+++ b/Swiften/Disco/ClientDiscoManager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -16,6 +16,7 @@ namespace Swift {
 	class DiscoInfoResponder;
 	class PayloadAddingPresenceSender;
 	class PresenceSender;
+	class CryptoProvider;
 
 	/**
 	 * Class responsible for managing outgoing disco information for a client.
@@ -36,7 +37,7 @@ namespace Swift {
 			 * \param presenceSender the presence sender to which all outgoing presence
 			 *   (with caps information) will be sent.
 			 */
-			ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender);
+			ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender, CryptoProvider* crypto);
 			~ClientDiscoManager();
 
 			/**
@@ -68,6 +69,7 @@ namespace Swift {
 
 		private:
 			PayloadAddingPresenceSender* presenceSender;
+			CryptoProvider* crypto;
 			DiscoInfoResponder* discoInfoResponder;
 			std::string capsNode;
 			CapsInfo::ref capsInfo;
diff --git a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp
index 52fdbaa..a1b1a7b 100644
--- a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp
+++ b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -9,6 +9,8 @@
 
 #include <Swiften/Elements/DiscoInfo.h>
 #include <Swiften/Disco/CapsInfoGenerator.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -19,6 +21,10 @@ class CapsInfoGeneratorTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
+		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
+		}
+
 		void testGenerate_XEP0115SimpleExample() {
 			DiscoInfo discoInfo;
 			discoInfo.addIdentity(DiscoInfo::Identity("Exodus 0.9.1", "client", "pc"));
@@ -27,7 +33,7 @@ class CapsInfoGeneratorTest : public CppUnit::TestFixture {
 			discoInfo.addFeature("http://jabber.org/protocol/disco#info");
 			discoInfo.addFeature("http://jabber.org/protocol/muc");
 
-			CapsInfoGenerator testling("http://code.google.com/p/exodus");
+			CapsInfoGenerator testling("http://code.google.com/p/exodus", crypto.get());
 			CapsInfo result = testling.generateCapsInfo(discoInfo);
 
 			CPPUNIT_ASSERT_EQUAL(std::string("http://code.google.com/p/exodus"), result.getNode());
@@ -74,11 +80,14 @@ class CapsInfoGeneratorTest : public CppUnit::TestFixture {
 			extension->addField(field);
 			discoInfo.addExtension(extension);
 
-			CapsInfoGenerator testling("http://psi-im.org");
+			CapsInfoGenerator testling("http://psi-im.org", crypto.get());
 			CapsInfo result = testling.generateCapsInfo(discoInfo);
 
 			CPPUNIT_ASSERT_EQUAL(std::string("q07IKJEyjvHSyhy//CH0CxmKi8w="), result.getVersion());
 		}
+		
+	private:
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(CapsInfoGeneratorTest);
diff --git a/Swiften/Disco/UnitTest/CapsManagerTest.cpp b/Swiften/Disco/UnitTest/CapsManagerTest.cpp
index ca55c48..303fd78 100644
--- a/Swiften/Disco/UnitTest/CapsManagerTest.cpp
+++ b/Swiften/Disco/UnitTest/CapsManagerTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -16,6 +16,8 @@
 #include <Swiften/Elements/CapsInfo.h>
 #include <Swiften/Elements/DiscoInfo.h>
 #include <Swiften/Client/DummyStanzaChannel.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -41,18 +43,19 @@ class CapsManagerTest : public CppUnit::TestFixture {
 
 	public:
 		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
 			stanzaChannel = new DummyStanzaChannel();
 			iqRouter = new IQRouter(stanzaChannel);
 			storage = new CapsMemoryStorage();
 			user1 = JID("user1@bar.com/bla");
 			discoInfo1 = boost::make_shared<DiscoInfo>();
 			discoInfo1->addFeature("http://swift.im/feature1");
-			capsInfo1 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im").generateCapsInfo(*discoInfo1.get()));
-			capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im").generateCapsInfo(*discoInfo1.get()));
+			capsInfo1 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get()));
+			capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get()));
 			user2 = JID("user2@foo.com/baz");
 			discoInfo2 = boost::make_shared<DiscoInfo>();
 			discoInfo2->addFeature("http://swift.im/feature2");
-			capsInfo2 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im").generateCapsInfo(*discoInfo2.get()));
+			capsInfo2 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get()));
 			user3 = JID("user3@foo.com/baz");
 			legacyCapsInfo = boost::make_shared<CapsInfo>("http://swift.im", "ver1", "");
 		}
@@ -246,7 +249,7 @@ class CapsManagerTest : public CppUnit::TestFixture {
 
 	private:
 		boost::shared_ptr<CapsManager> createManager() {
-			boost::shared_ptr<CapsManager> manager(new CapsManager(storage, stanzaChannel, iqRouter));
+			boost::shared_ptr<CapsManager> manager(new CapsManager(storage, stanzaChannel, iqRouter, crypto.get()));
 			manager->setWarnOnInvalidHash(false);
 			//manager->onCapsChanged.connect(boost::bind(&CapsManagerTest::handleCapsChanged, this, _1));
 			return manager;
@@ -281,6 +284,7 @@ class CapsManagerTest : public CppUnit::TestFixture {
 		boost::shared_ptr<CapsInfo> capsInfo2;
 		boost::shared_ptr<CapsInfo> legacyCapsInfo;
 		JID user3;
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(CapsManagerTest);
diff --git a/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp b/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp
index 0fd966d..940f043 100644
--- a/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp
+++ b/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -14,6 +14,8 @@
 #include <Swiften/Elements/CapsInfo.h>
 #include <Swiften/Client/DummyStanzaChannel.h>
 #include <Swiften/Disco/CapsInfoGenerator.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -30,18 +32,20 @@ class EntityCapsManagerTest : public CppUnit::TestFixture {
 
 	public:
 		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
+
 			stanzaChannel = new DummyStanzaChannel();
 			capsProvider = new DummyCapsProvider();
 
 			user1 = JID("user1@bar.com/bla");
 			discoInfo1 = boost::make_shared<DiscoInfo>();
 			discoInfo1->addFeature("http://swift.im/feature1");
-			capsInfo1 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im").generateCapsInfo(*discoInfo1.get()));
-			capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im").generateCapsInfo(*discoInfo1.get()));
+			capsInfo1 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get()));
+			capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get()));
 			user2 = JID("user2@foo.com/baz");
 			discoInfo2 = boost::make_shared<DiscoInfo>();
 			discoInfo2->addFeature("http://swift.im/feature2");
-			capsInfo2 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im").generateCapsInfo(*discoInfo2.get()));
+			capsInfo2 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get()));
 			user3 = JID("user3@foo.com/baz");
 			legacyCapsInfo = boost::make_shared<CapsInfo>("http://swift.im", "ver1", "");
 		}
@@ -183,6 +187,7 @@ class EntityCapsManagerTest : public CppUnit::TestFixture {
 		boost::shared_ptr<CapsInfo> legacyCapsInfo;
 		JID user3;
 		std::vector<JID> changes;
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(EntityCapsManagerTest);
diff --git a/Swiften/Examples/SendFile/SendFile.cpp b/Swiften/Examples/SendFile/SendFile.cpp
index 39a8603..1e4fc14 100644
--- a/Swiften/Examples/SendFile/SendFile.cpp
+++ b/Swiften/Examples/SendFile/SendFile.cpp
@@ -29,8 +29,6 @@
 #include <Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.h>
 #include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h>
 #include <Swiften/Base/ByteArray.h>
-#include <Swiften/StringCodecs/MD5.h>
-#include <Swiften/StringCodecs/SHA1.h>
 #include <Swiften/StringCodecs/Hexify.h>
 #include <Swiften/FileTransfer/FileTransferManager.h>
 
diff --git a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.cpp b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.cpp
index 4a6b61f..40b23d2 100644
--- a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.cpp
+++ b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.cpp
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.h>
 
 #include <boost/smart_ptr/make_shared.hpp>
@@ -18,7 +24,7 @@
 
 namespace Swift {
 
-DefaultRemoteJingleTransportCandidateSelector::DefaultRemoteJingleTransportCandidateSelector(ConnectionFactory* connectionFactory, TimerFactory* timerFactory) : connectionFactory(connectionFactory), timerFactory(timerFactory) {
+DefaultRemoteJingleTransportCandidateSelector::DefaultRemoteJingleTransportCandidateSelector(ConnectionFactory* connectionFactory, TimerFactory* timerFactory, CryptoProvider* crypto) : connectionFactory(connectionFactory), timerFactory(timerFactory), crypto(crypto) {
 }
 
 DefaultRemoteJingleTransportCandidateSelector::~DefaultRemoteJingleTransportCandidateSelector() {
@@ -58,7 +64,7 @@ void DefaultRemoteJingleTransportCandidateSelector::tryNextCandidate(bool error)
 				lastCandidate.type == JingleS5BTransportPayload::Candidate::AssistedType || lastCandidate.type == JingleS5BTransportPayload::Candidate::ProxyType ) {
 				// create connection
 				connection = connectionFactory->createConnection();
-				s5bSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, lastCandidate.hostPort, SOCKS5BytestreamRegistry::getHostname(transportSID, requester, target), timerFactory);
+				s5bSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, lastCandidate.hostPort, SOCKS5BytestreamRegistry::getHostname(transportSID, requester, target, crypto), timerFactory);
 
 				// bind onReady to this method
 				s5bSession->onSessionReady.connect(boost::bind(&DefaultRemoteJingleTransportCandidateSelector::tryNextCandidate, this, _1));
diff --git a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.h b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.h
index 073c51f..13e8cd6 100644
--- a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.h
+++ b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.h
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #pragma once
 
 #include <queue>
@@ -23,10 +29,11 @@ namespace Swift {
 
 class ConnectionFactory;
 class TimerFactory;
+class CryptoProvider;
 
 class DefaultRemoteJingleTransportCandidateSelector : public RemoteJingleTransportCandidateSelector {
 public:
-	DefaultRemoteJingleTransportCandidateSelector(ConnectionFactory*, TimerFactory*);
+	DefaultRemoteJingleTransportCandidateSelector(ConnectionFactory*, TimerFactory*, CryptoProvider*);
 	virtual ~DefaultRemoteJingleTransportCandidateSelector();
 
 	virtual void addRemoteTransportCandidates(JingleTransportPayload::ref) SWIFTEN_OVERRIDE;
@@ -45,6 +52,7 @@ private:
 private:
 	ConnectionFactory* connectionFactory;
 	TimerFactory* timerFactory;
+	CryptoProvider* crypto;
 
 	std::priority_queue<JingleS5BTransportPayload::Candidate, std::vector<JingleS5BTransportPayload::Candidate>, JingleS5BTransportPayload::CompareCandidate> candidates;
 
diff --git a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.cpp b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.cpp
index 8ebbf46..5fcdf79 100644
--- a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.cpp
+++ b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.cpp
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #include "DefaultRemoteJingleTransportCandidateSelectorFactory.h"
 
 #include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelector.h>
@@ -12,14 +18,14 @@
 
 namespace Swift {
 
-DefaultRemoteJingleTransportCandidateSelectorFactory::DefaultRemoteJingleTransportCandidateSelectorFactory(ConnectionFactory* connectionFactory, TimerFactory* timerFactory) : connectionFactory(connectionFactory), timerFactory(timerFactory) {
+DefaultRemoteJingleTransportCandidateSelectorFactory::DefaultRemoteJingleTransportCandidateSelectorFactory(ConnectionFactory* connectionFactory, TimerFactory* timerFactory, CryptoProvider* crypto) : connectionFactory(connectionFactory), timerFactory(timerFactory), crypto(crypto) {
 }
 
 DefaultRemoteJingleTransportCandidateSelectorFactory::~DefaultRemoteJingleTransportCandidateSelectorFactory() {
 }
 
 RemoteJingleTransportCandidateSelector* DefaultRemoteJingleTransportCandidateSelectorFactory::createCandidateSelector() {
-	return new DefaultRemoteJingleTransportCandidateSelector(connectionFactory, timerFactory);
+	return new DefaultRemoteJingleTransportCandidateSelector(connectionFactory, timerFactory, crypto);
 }
 
 }
diff --git a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h
index ca29e1f..19f8c38 100644
--- a/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h
+++ b/Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #pragma once
 
 #include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h>
@@ -12,10 +18,11 @@ namespace Swift {
 
 class ConnectionFactory;
 class TimerFactory;
+class CryptoProvider;
 
 class DefaultRemoteJingleTransportCandidateSelectorFactory : public RemoteJingleTransportCandidateSelectorFactory {
 public:
-	DefaultRemoteJingleTransportCandidateSelectorFactory(ConnectionFactory*, TimerFactory*);
+	DefaultRemoteJingleTransportCandidateSelectorFactory(ConnectionFactory*, TimerFactory*, CryptoProvider*);
 	virtual ~DefaultRemoteJingleTransportCandidateSelectorFactory();
 
 	RemoteJingleTransportCandidateSelector* createCandidateSelector();
@@ -23,6 +30,7 @@ public:
 private:
 	ConnectionFactory* connectionFactory;
 	TimerFactory* timerFactory;
+	CryptoProvider* crypto;
 };
 
 }
diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
index d5d4aaf..b80ad9a 100644
--- a/Swiften/FileTransfer/FileTransferManagerImpl.cpp
+++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #include <Swiften/FileTransfer/FileTransferManagerImpl.h>
 
 #include <boost/bind.hpp>
@@ -35,7 +41,7 @@
 
 namespace Swift {
 
-FileTransferManagerImpl::FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, NATTraverser* natTraverser) : ownJID(ownFullJID), jingleSM(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), presenceOracle(presOracle), connectionServerFactory(connectionServerFactory), bytestreamServer(NULL), s5bProxyFinder(NULL) {
+FileTransferManagerImpl::FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, NATTraverser* natTraverser, CryptoProvider* crypto) : ownJID(ownFullJID), jingleSM(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), presenceOracle(presOracle), connectionServerFactory(connectionServerFactory), crypto(crypto), bytestreamServer(NULL), s5bProxyFinder(NULL) {
 	assert(!ownFullJID.isBare());
 
 	connectivityManager = new ConnectivityManager(natTraverser);
@@ -43,9 +49,9 @@ FileTransferManagerImpl::FileTransferManagerImpl(const JID& ownFullJID, JingleSe
 	bytestreamProxy = new SOCKS5BytestreamProxy(connectionFactory, timerFactory);
 
 	localCandidateGeneratorFactory = new DefaultLocalJingleTransportCandidateGeneratorFactory(connectivityManager, bytestreamRegistry, bytestreamProxy, ownFullJID);
-	remoteCandidateSelectorFactory = new DefaultRemoteJingleTransportCandidateSelectorFactory(connectionFactory, timerFactory);
-	outgoingFTManager = new OutgoingFileTransferManager(jingleSM, iqRouter, capsProvider, remoteCandidateSelectorFactory, localCandidateGeneratorFactory, bytestreamRegistry, bytestreamProxy);
-	incomingFTManager = new IncomingFileTransferManager(jingleSM, iqRouter, remoteCandidateSelectorFactory, localCandidateGeneratorFactory, bytestreamRegistry, bytestreamProxy, timerFactory);
+	remoteCandidateSelectorFactory = new DefaultRemoteJingleTransportCandidateSelectorFactory(connectionFactory, timerFactory, crypto);
+	outgoingFTManager = new OutgoingFileTransferManager(jingleSM, iqRouter, capsProvider, remoteCandidateSelectorFactory, localCandidateGeneratorFactory, bytestreamRegistry, bytestreamProxy, crypto);
+	incomingFTManager = new IncomingFileTransferManager(jingleSM, iqRouter, remoteCandidateSelectorFactory, localCandidateGeneratorFactory, bytestreamRegistry, bytestreamProxy, timerFactory, crypto);
 	incomingFTManager->onIncomingFileTransfer.connect(onIncomingFileTransfer);
 }
 
@@ -70,7 +76,7 @@ void FileTransferManagerImpl::startListeningOnPort(int port) {
 	SWIFT_LOG(debug) << "Start listening on port " << port << " and hope it's not in use." << std::endl;
 	boost::shared_ptr<ConnectionServer> server = connectionServerFactory->createConnectionServer(HostAddress("0.0.0.0"), port);
 	server->start();
-	bytestreamServer = new SOCKS5BytestreamServer(server, bytestreamRegistry);
+	bytestreamServer = new SOCKS5BytestreamServer(server, bytestreamRegistry, crypto);
 	bytestreamServer->start();
 	connectivityManager->addListeningPort(port);
 
diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.h b/Swiften/FileTransfer/FileTransferManagerImpl.h
index 0bbbf31..d5ef144 100644
--- a/Swiften/FileTransfer/FileTransferManagerImpl.h
+++ b/Swiften/FileTransfer/FileTransferManagerImpl.h
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #pragma once
 
 #include <vector>
@@ -40,10 +46,11 @@ namespace Swift {
 	class SOCKS5BytestreamProxy;
 	class TimerFactory;
 	class SOCKS5BytestreamProxyFinder;
+	class CryptoProvider;
 
 	class FileTransferManagerImpl : public FileTransferManager {
 		public:
-			FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, NATTraverser* natTraverser);
+			FileTransferManagerImpl(const JID& ownFullJID, JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, PresenceOracle* presOracle, ConnectionFactory* connectionFactory, ConnectionServerFactory* connectionServerFactory, TimerFactory* timerFactory, NATTraverser* natTraverser, CryptoProvider* crypto);
 			~FileTransferManagerImpl();
 			
 			void startListeningOnPort(int port);
@@ -68,6 +75,7 @@ namespace Swift {
 			PresenceOracle* presenceOracle;
 
 			ConnectionServerFactory* connectionServerFactory;
+			CryptoProvider* crypto;
 			SOCKS5BytestreamRegistry* bytestreamRegistry;
 			SOCKS5BytestreamServer* bytestreamServer;
 			SOCKS5BytestreamProxy* bytestreamProxy;
diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.cpp b/Swiften/FileTransfer/IncomingFileTransferManager.cpp
index 22e8bf9..9bde8e8 100644
--- a/Swiften/FileTransfer/IncomingFileTransferManager.cpp
+++ b/Swiften/FileTransfer/IncomingFileTransferManager.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -20,7 +20,7 @@ namespace Swift {
 
 IncomingFileTransferManager::IncomingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router,
 							RemoteJingleTransportCandidateSelectorFactory* remoteFactory,
-														 LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, TimerFactory* timerFactory) : jingleSessionManager(jingleSessionManager), router(router), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), timerFactory(timerFactory) {
+														 LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, TimerFactory* timerFactory, CryptoProvider* crypto) : jingleSessionManager(jingleSessionManager), router(router), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), timerFactory(timerFactory), crypto(crypto) {
 	jingleSessionManager->addIncomingSessionHandler(this);
 }
 
@@ -35,7 +35,7 @@ bool IncomingFileTransferManager::handleIncomingJingleSession(JingleSession::ref
 			JingleFileTransferDescription::ref description = content->getDescription<JingleFileTransferDescription>();
 
 			if (description && description->getOffers().size() == 1) {
-				IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>(recipient, session, content, remoteFactory, localFactory, router, bytestreamRegistry, bytestreamProxy, timerFactory);
+				IncomingJingleFileTransfer::ref transfer = boost::shared_ptr<IncomingJingleFileTransfer>(new IncomingJingleFileTransfer(recipient, session, content, remoteFactory, localFactory, router, bytestreamRegistry, bytestreamProxy, timerFactory, crypto));
 				onIncomingFileTransfer(transfer);
 			} else {
 				std::cerr << "Received a file-transfer request with no description or more than one file!" << std::endl;
diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.h b/Swiften/FileTransfer/IncomingFileTransferManager.h
index 2d1c07f..d7b5ae2 100644
--- a/Swiften/FileTransfer/IncomingFileTransferManager.h
+++ b/Swiften/FileTransfer/IncomingFileTransferManager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -20,10 +20,11 @@ namespace Swift {
 	class SOCKS5BytestreamRegistry;
 	class SOCKS5BytestreamProxy;
 	class TimerFactory;
+	class CryptoProvider;
 
 	class IncomingFileTransferManager : public IncomingJingleSessionHandler {
 		public:
-			IncomingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, TimerFactory* timerFactory);
+			IncomingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, TimerFactory* timerFactory, CryptoProvider* crypto);
 			~IncomingFileTransferManager();
 
 			boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer;
@@ -39,5 +40,6 @@ namespace Swift {
 			SOCKS5BytestreamRegistry* bytestreamRegistry;
 			SOCKS5BytestreamProxy* bytestreamProxy;
 			TimerFactory* timerFactory;
+			CryptoProvider* crypto;
 	};
 }
diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
index 0d576ac..6dc53fb 100644
--- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
+++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
@@ -37,11 +37,13 @@ IncomingJingleFileTransfer::IncomingJingleFileTransfer(
 		IQRouter* router,
 		SOCKS5BytestreamRegistry* registry,
 		SOCKS5BytestreamProxy* proxy,
-		TimerFactory* timerFactory) :
+		TimerFactory* timerFactory,
+		CryptoProvider* crypto) :
 			ourJID(ourJID),
 			session(session),
 			router(router),
 			initialContent(content),
+			crypto(crypto),
 			state(Initial),
 			receivedBytes(0),
 			s5bRegistry(registry),
@@ -93,7 +95,7 @@ void IncomingJingleFileTransfer::accept(WriteBytestream::ref stream) {
 	assert(!this->stream);
 	this->stream = stream;
 
-	hashCalculator = new IncrementalBytestreamHashCalculator( algo == "md5" || hash.empty() , algo == "sha-1" || hash.empty() );
+	hashCalculator = new IncrementalBytestreamHashCalculator( algo == "md5" || hash.empty() , algo == "sha-1" || hash.empty(), crypto);
 	stream->onWrite.connect(boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1));
 	stream->onWrite.connect(boost::bind(&IncomingJingleFileTransfer::handleWriteStreamDataReceived, this, _1));
 	onStateChange(FileTransfer::State(FileTransfer::State::Negotiating));
@@ -106,7 +108,7 @@ void IncomingJingleFileTransfer::accept(WriteBytestream::ref stream) {
 		SWIFT_LOG(debug) << "Got S5B transport payload!" << std::endl;
 		state = CreatingInitialTransports;
 		s5bSessionID = s5bTransport->getSessionID().empty() ? idGenerator.generateID() : s5bTransport->getSessionID();
-		s5bDestination = SOCKS5BytestreamRegistry::getHostname(s5bSessionID, ourJID, session->getInitiator());
+		s5bDestination = SOCKS5BytestreamRegistry::getHostname(s5bSessionID, ourJID, session->getInitiator(), crypto);
 		s5bRegistry->addWriteBytestream(s5bDestination, stream);
 		fillCandidateMap(theirCandidates, s5bTransport);
 		candidateSelector->addRemoteTransportCandidates(s5bTransport);
@@ -329,7 +331,7 @@ void IncomingJingleFileTransfer::useTheirCandidateChoiceForTransfer(JingleS5BTra
 
 	if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) {
 		// get proxy client session from s5bRegistry
-		clientSession = s5bProxy->createSOCKS5BytestreamClientSession(candidate.hostPort, SOCKS5BytestreamRegistry::getHostname(s5bSessionID, ourJID, session->getInitiator()));
+		clientSession = s5bProxy->createSOCKS5BytestreamClientSession(candidate.hostPort, SOCKS5BytestreamRegistry::getHostname(s5bSessionID, ourJID, session->getInitiator(), crypto));
 		clientSession->onSessionReady.connect(boost::bind(&IncomingJingleFileTransfer::proxySessionReady, this, candidate.jid, _1));
 		clientSession->start();
 
diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.h b/Swiften/FileTransfer/IncomingJingleFileTransfer.h
index 0731e04..1243d11 100644
--- a/Swiften/FileTransfer/IncomingJingleFileTransfer.h
+++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.h
@@ -35,6 +35,7 @@ namespace Swift {
 	class SOCKS5BytestreamRegistry;
 	class SOCKS5BytestreamProxy;
 	class IncrementalBytestreamHashCalculator;
+	class CryptoProvider;
 
 	class SWIFTEN_API IncomingJingleFileTransfer : public IncomingFileTransfer {
 		public:
@@ -57,7 +58,8 @@ namespace Swift {
 					IQRouter* router,
 					SOCKS5BytestreamRegistry* bytestreamRegistry,
 					SOCKS5BytestreamProxy* bytestreamProxy,
-					TimerFactory*);
+					TimerFactory*,
+					CryptoProvider*);
 			~IncomingJingleFileTransfer();
 
 			virtual void accept(WriteBytestream::ref);
@@ -103,6 +105,7 @@ namespace Swift {
 			JingleSession::ref session;
 			IQRouter* router;
 			JingleContentPayload::ref initialContent;
+			CryptoProvider* crypto;
 			State state;
 			JingleFileTransferDescription::ref description;
 			WriteBytestream::ref stream;
diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp
index 6b53a1b..e669a51 100644
--- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp
+++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp
@@ -4,17 +4,23 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+
 #include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h>
 
 #include <Swiften/StringCodecs/Hexify.h>
-#include <Swiften/StringCodecs/MD5.h>
-#include <Swiften/StringCodecs/SHA1.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 namespace Swift {
 
-IncrementalBytestreamHashCalculator::IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1) {
-	md5Hasher = doMD5 ? new MD5() : NULL;
-	sha1Hasher = doSHA1 ? new SHA1() : NULL;
+IncrementalBytestreamHashCalculator::IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1, CryptoProvider* crypto) {
+	md5Hasher = doMD5 ? crypto->createMD5() : NULL;
+	sha1Hasher = doSHA1 ? crypto->createSHA1() : NULL;
 }
 
 IncrementalBytestreamHashCalculator::~IncrementalBytestreamHashCalculator() {
diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h
index 64f4b5f..f9f43b9 100644
--- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h
+++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h
@@ -4,30 +4,35 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #pragma once
 
 #include <Swiften/Base/ByteArray.h>
 #include <Swiften/Base/SafeByteArray.h>
 
 namespace Swift {
+	class Hash;
+	class CryptoProvider;
 
-class MD5;
-class SHA1;
-
-class IncrementalBytestreamHashCalculator {
-public:
-	IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1);
-	~IncrementalBytestreamHashCalculator();
+	class IncrementalBytestreamHashCalculator {
+	public:
+		IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1, CryptoProvider* crypto);
+		~IncrementalBytestreamHashCalculator();
 
-	void feedData(const ByteArray& data);
-	//void feedData(const SafeByteArray& data);
+		void feedData(const ByteArray& data);
+		//void feedData(const SafeByteArray& data);
 
-	std::string getSHA1String();
-	std::string getMD5String();
+		std::string getSHA1String();
+		std::string getMD5String();
 
-private:
-	MD5* md5Hasher;
-	SHA1* sha1Hasher;
-};
+	private:
+		Hash* md5Hasher;
+		Hash* sha1Hasher;
+	};
 
 }
diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp
index 6f23bb7..99ca175 100644
--- a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp
+++ b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #include "OutgoingFileTransferManager.h"
 
 #include <boost/smart_ptr/make_shared.hpp>
@@ -17,7 +23,7 @@
 
 namespace Swift {
 
-OutgoingFileTransferManager::OutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy) {
+OutgoingFileTransferManager::OutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, CryptoProvider* crypto) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), crypto(crypto) {
 	idGenerator = new IDGenerator();
 }
 
@@ -34,7 +40,7 @@ boost::shared_ptr<OutgoingFileTransfer> OutgoingFileTransferManager::createOutgo
 	//jsManager->getSession(receipient, idGenerator->generateID());
 	assert(jingleSession);
 	jsManager->registerOutgoingSession(from, jingleSession);
-	boost::shared_ptr<OutgoingJingleFileTransfer> jingleFT =  boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(jingleSession, remoteFactory, localFactory, iqRouter, idGenerator, from, receipient, readBytestream, fileInfo, bytestreamRegistry, bytestreamProxy));
+	boost::shared_ptr<OutgoingJingleFileTransfer> jingleFT =  boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(jingleSession, remoteFactory, localFactory, iqRouter, idGenerator, from, receipient, readBytestream, fileInfo, bytestreamRegistry, bytestreamProxy, crypto));
 	
 	// otherwise try SI
 	
diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.h b/Swiften/FileTransfer/OutgoingFileTransferManager.h
index c686001..409c5ed 100644
--- a/Swiften/FileTransfer/OutgoingFileTransferManager.h
+++ b/Swiften/FileTransfer/OutgoingFileTransferManager.h
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #pragma once
 
 #include <boost/shared_ptr.hpp>
@@ -24,10 +30,11 @@ class ReadBytestream;
 class StreamInitiationFileInfo;
 class SOCKS5BytestreamRegistry;
 class SOCKS5BytestreamProxy;
+class CryptoProvider;
 
 class OutgoingFileTransferManager {
 public:
-	OutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy);
+	OutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, CryptoProvider* crypto);
 	~OutgoingFileTransferManager();
 	
 	boost::shared_ptr<OutgoingFileTransfer> createOutgoingFileTransfer(const JID& from, const JID& to, boost::shared_ptr<ReadBytestream>, const StreamInitiationFileInfo&);
@@ -41,6 +48,7 @@ private:
 	IDGenerator *idGenerator;
 	SOCKS5BytestreamRegistry* bytestreamRegistry;
 	SOCKS5BytestreamProxy* bytestreamProxy;
+	CryptoProvider* crypto;
 };
 
 }
diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp
index 8229a2f..285dbe3 100644
--- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp
+++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp
@@ -28,7 +28,7 @@
 #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h>
 #include <Swiften/FileTransfer/SOCKS5BytestreamProxy.h>
 #include <Swiften/StringCodecs/Hexify.h>
-#include <Swiften/StringCodecs/SHA1.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 #include <Swiften/Base/Log.h>
 
@@ -44,8 +44,9 @@ OutgoingJingleFileTransfer::OutgoingJingleFileTransfer(JingleSession::ref sessio
 					boost::shared_ptr<ReadBytestream> readStream,
 					const StreamInitiationFileInfo &fileInfo,
 					SOCKS5BytestreamRegistry* bytestreamRegistry,
-					SOCKS5BytestreamProxy* bytestreamProxy) :
-	session(session), router(router), idGenerator(idGenerator), fromJID(fromJID), toJID(toJID), readStream(readStream), fileInfo(fileInfo), s5bRegistry(bytestreamRegistry), s5bProxy(bytestreamProxy), serverSession(NULL), contentID(JingleContentID(idGenerator->generateID(), JingleContentPayload::InitiatorCreator)), canceled(false) {
+					SOCKS5BytestreamProxy* bytestreamProxy,
+					CryptoProvider* crypto) :
+	session(session), router(router), idGenerator(idGenerator), fromJID(fromJID), toJID(toJID), readStream(readStream), fileInfo(fileInfo), s5bRegistry(bytestreamRegistry), s5bProxy(bytestreamProxy), crypto(crypto), serverSession(NULL), contentID(JingleContentID(idGenerator->generateID(), JingleContentPayload::InitiatorCreator)), canceled(false) {
 	session->onSessionAcceptReceived.connect(boost::bind(&OutgoingJingleFileTransfer::handleSessionAcceptReceived, this, _1, _2, _3));
 	session->onSessionTerminateReceived.connect(boost::bind(&OutgoingJingleFileTransfer::handleSessionTerminateReceived, this, _1));
 	session->onTransportInfoReceived.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransportInfoReceived, this, _1, _2));
@@ -60,7 +61,7 @@ OutgoingJingleFileTransfer::OutgoingJingleFileTransfer(JingleSession::ref sessio
 	remoteCandidateSelector = remoteFactory->createCandidateSelector();
 	remoteCandidateSelector->onRemoteTransportCandidateSelectFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1));
 	// calculate both, MD5 and SHA-1 since we don't know which one the other side supports
-	hashCalculator = new IncrementalBytestreamHashCalculator(true, true);
+	hashCalculator = new IncrementalBytestreamHashCalculator(true, true, crypto);
 	this->readStream->onRead.connect(boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1));
 }
 
@@ -92,7 +93,7 @@ void OutgoingJingleFileTransfer::cancel() {
 	if (ibbSession) {
 		ibbSession->stop();
 	}
-	SOCKS5BytestreamServerSession *serverSession = s5bRegistry->getConnectedSession(SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID));
+	SOCKS5BytestreamServerSession *serverSession = s5bRegistry->getConnectedSession(SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID, crypto));
 	if (serverSession) {
 		serverSession->stop();
 	}
@@ -200,14 +201,14 @@ void OutgoingJingleFileTransfer::startTransferViaTheirCandidateChoice(JingleS5BT
 	SWIFT_LOG(debug) << "Transferring data using their candidate." << std::endl;
 	if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) {
 		// connect to proxy
-		clientSession = s5bProxy->createSOCKS5BytestreamClientSession(candidate.hostPort, SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID));
+		clientSession = s5bProxy->createSOCKS5BytestreamClientSession(candidate.hostPort, SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID, crypto));
 		clientSession->onSessionReady.connect(boost::bind(&OutgoingJingleFileTransfer::proxySessionReady, this, candidate.jid, _1));
 		clientSession->start();
 
 		// on reply send activate
 
 	} else {
-		serverSession = s5bRegistry->getConnectedSession(SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID));
+		serverSession = s5bRegistry->getConnectedSession(SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID, crypto));
 		serverSession->onBytesSent.connect(boost::bind(boost::ref(onProcessedBytes), _1));
 		serverSession->onFinished.connect(boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1));
 		serverSession->startTransfer();
@@ -356,7 +357,7 @@ void OutgoingJingleFileTransfer::handleLocalTransportCandidatesGenerated(JingleT
 		fillCandidateMap(ourCandidates, emptyCandidates);
 
 		transport = emptyCandidates;
-		s5bRegistry->addReadBytestream(SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID), readStream);
+		s5bRegistry->addReadBytestream(SOCKS5BytestreamRegistry::getHostname(s5bSessionID, session->getInitiator(), toJID, crypto), readStream);
 	}
 	else {
 		SWIFT_LOG(debug) << "Unknown tranport payload: " << typeid(*payload).name() << std::endl;
diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h
index e18b5c3..ee2c20e 100644
--- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h
+++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h
@@ -19,7 +19,6 @@
 #include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h>
 #include <Swiften/Jingle/JingleContentID.h>
 #include <Swiften/Jingle/JingleSession.h>
-#include <Swiften/StringCodecs/SHA1.h>
 
 namespace Swift {
 
@@ -34,6 +33,7 @@ class IDGenerator;
 class IncrementalBytestreamHashCalculator;
 class SOCKS5BytestreamRegistry;
 class SOCKS5BytestreamProxy;
+class CryptoProvider;
 
 class SWIFTEN_API OutgoingJingleFileTransfer : public OutgoingFileTransfer {
 public:
@@ -47,7 +47,8 @@ public:
 					boost::shared_ptr<ReadBytestream>,
 					const StreamInitiationFileInfo&,
 					SOCKS5BytestreamRegistry*,
-					SOCKS5BytestreamProxy*);
+					SOCKS5BytestreamProxy*,
+					CryptoProvider*);
 	virtual ~OutgoingJingleFileTransfer();
 	
 	void start();
@@ -105,6 +106,7 @@ private:
 
 	SOCKS5BytestreamRegistry* s5bRegistry;
 	SOCKS5BytestreamProxy* s5bProxy;
+	CryptoProvider* crypto;
 	SOCKS5BytestreamClientSession::ref clientSession;
 	SOCKS5BytestreamServerSession* serverSession;
 	JingleContentID contentID;
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp
index 1b3399f..a0b6e7f 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp
+++ b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp
@@ -13,7 +13,6 @@
 #include <Swiften/Base/SafeByteArray.h>
 #include <Swiften/Base/Concat.h>
 #include <Swiften/Base/Log.h>
-#include <Swiften/StringCodecs/SHA1.h>
 #include <Swiften/StringCodecs/Hexify.h>
 #include <Swiften/FileTransfer/BytestreamException.h>
 #include <Swiften/Network/TimerFactory.h>
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp
index ffc4298..8939579 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp
+++ b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -11,8 +11,8 @@
 #include <Swiften/Base/Algorithm.h>
 #include <Swiften/Base/Log.h>
 #include <Swiften/Base/foreach.h>
-#include <Swiften/StringCodecs/SHA1.h>
 #include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 namespace Swift {
 
@@ -64,8 +64,8 @@ SOCKS5BytestreamServerSession* SOCKS5BytestreamRegistry::getConnectedSession(con
 	}
 }
 
-std::string SOCKS5BytestreamRegistry::getHostname(const std::string& sessionID, const JID& requester, const JID& target) {
-	return Hexify::hexify(SHA1::getHash(createSafeByteArray(sessionID + requester.toString() + target.toString())));
+std::string SOCKS5BytestreamRegistry::getHostname(const std::string& sessionID, const JID& requester, const JID& target, CryptoProvider* crypto) {
+	return Hexify::hexify(crypto->getSHA1Hash(createSafeByteArray(sessionID + requester.toString() + target.toString())));
 }
 
 }
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h
index 6d89e27..107707f 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h
+++ b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -24,6 +24,8 @@
 #include <Swiften/Network/HostAddressPort.h>
 
 namespace Swift {
+	class CryptoProvider;
+
 	class SWIFTEN_API SOCKS5BytestreamRegistry {
 		public:
 			SOCKS5BytestreamRegistry();
@@ -47,7 +49,7 @@ namespace Swift {
 			SOCKS5BytestreamServerSession* getConnectedSession(const std::string& destination);
 
 		public:
-			static std::string getHostname(const std::string& sessionID, const JID& requester, const JID& target);
+			static std::string getHostname(const std::string& sessionID, const JID& requester, const JID& target, CryptoProvider* crypto);
 
 		private:
 			friend class SOCKS5BytestreamServerSession;
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp
index 90fed7a..00c72a7 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp
+++ b/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -10,13 +10,13 @@
 
 #include <Swiften/Base/Log.h>
 #include <Swiften/StringCodecs/Hexify.h>
-#include <Swiften/StringCodecs/SHA1.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 #include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h>
 #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h>
 
 namespace Swift {
 
-SOCKS5BytestreamServer::SOCKS5BytestreamServer(boost::shared_ptr<ConnectionServer> connectionServer, SOCKS5BytestreamRegistry* registry) : connectionServer(connectionServer), registry(registry) {
+SOCKS5BytestreamServer::SOCKS5BytestreamServer(boost::shared_ptr<ConnectionServer> connectionServer, SOCKS5BytestreamRegistry* registry, CryptoProvider* crypto) : connectionServer(connectionServer), registry(registry), crypto(crypto) {
 }
 
 void SOCKS5BytestreamServer::start() {
@@ -36,7 +36,7 @@ void SOCKS5BytestreamServer::removeReadBytestream(const std::string& id, const J
 }
 
 std::string SOCKS5BytestreamServer::getSOCKSDestinationAddress(const std::string& id, const JID& from, const JID& to) {
-	return Hexify::hexify(SHA1::getHash(createByteArray(id + from.toString() + to.toString())));
+	return Hexify::hexify(crypto->getSHA1Hash(createByteArray(id + from.toString() + to.toString())));
 }
 
 void SOCKS5BytestreamServer::handleNewConnection(boost::shared_ptr<Connection> connection) {
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServer.h b/Swiften/FileTransfer/SOCKS5BytestreamServer.h
index 6bb598e..b19ae90 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamServer.h
+++ b/Swiften/FileTransfer/SOCKS5BytestreamServer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -17,10 +17,11 @@
 
 namespace Swift {
 	class SOCKS5BytestreamServerSession;
+	class CryptoProvider;
 
 	class SOCKS5BytestreamServer {
 		public:
-			SOCKS5BytestreamServer(boost::shared_ptr<ConnectionServer> connectionServer, SOCKS5BytestreamRegistry* registry);
+			SOCKS5BytestreamServer(boost::shared_ptr<ConnectionServer> connectionServer, SOCKS5BytestreamRegistry* registry, CryptoProvider* crypto);
 
 			HostAddressPort getAddressPort() const;
 
@@ -36,13 +37,14 @@ namespace Swift {
 		private:
 			void handleNewConnection(boost::shared_ptr<Connection> connection);
 
-			static std::string getSOCKSDestinationAddress(const std::string& id, const JID& from, const JID& to);
+			std::string getSOCKSDestinationAddress(const std::string& id, const JID& from, const JID& to);
 
 		private:
 			friend class SOCKS5BytestreamServerSession;
 
 			boost::shared_ptr<ConnectionServer> connectionServer;
 			SOCKS5BytestreamRegistry* registry;
+			CryptoProvider* crypto;
 			std::vector<boost::shared_ptr<SOCKS5BytestreamServerSession> > sessions;
 	};
 }
diff --git a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
index 9d180a0..47798ab 100644
--- a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #include <cppunit/extensions/HelperMacros.h>
 #include <cppunit/extensions/TestFactoryRegistry.h>
 
@@ -30,6 +36,8 @@
 #include <Swiften/Network/DummyConnectionFactory.h>
 #include <Swiften/Network/PlatformNATTraversalWorker.h>
 #include <Swiften/Queries/IQRouter.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 #include <iostream>
 
@@ -122,7 +130,7 @@ class IncomingJingleFileTransferTest : public CppUnit::TestFixture {
 public:
 		shared_ptr<IncomingJingleFileTransfer> createTestling() {
 			JID ourJID("our@jid.org/full");
-			return make_shared<IncomingJingleFileTransfer>(ourJID, shared_ptr<JingleSession>(fakeJingleSession), jingleContentPayload, fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, bytestreamRegistry, bytestreamProxy, timerFactory);
+			return boost::shared_ptr<IncomingJingleFileTransfer>(new IncomingJingleFileTransfer(ourJID, shared_ptr<JingleSession>(fakeJingleSession), jingleContentPayload, fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, bytestreamRegistry, bytestreamProxy, timerFactory, crypto.get()));
 		}
 
 		IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) {
@@ -132,6 +140,7 @@ public:
 		}
 
 		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
 			eventLoop = new DummyEventLoop();
 			fakeJingleSession = new FakeJingleSession("foo@bar.com/baz", "mysession");
 			jingleContentPayload = make_shared<JingleContentPayload>();
@@ -280,6 +289,7 @@ private:
 	DummyConnectionFactory* connectionFactory;
 	SOCKS5BytestreamProxy* bytestreamProxy;
 	DummyTimerFactory* timerFactory;
+	boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(IncomingJingleFileTransferTest);
diff --git a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp
index 73b496a..1dc7fba 100644
--- a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
 #include <cppunit/extensions/HelperMacros.h>
 #include <cppunit/extensions/TestFactoryRegistry.h>
 
@@ -36,6 +42,8 @@
 #include <Swiften/Network/DummyConnection.h>
 #include <Swiften/Network/ConnectionFactory.h>
 #include <Swiften/Network/DummyConnectionFactory.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 #include <Swiften/Base/Log.h>
 
@@ -147,7 +155,7 @@ public:
 			fileInfo.setName("test.bin");
 			fileInfo.setHash("asdjasdas");
 			fileInfo.setSize(1024 * 1024);
-			return boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(boost::shared_ptr<JingleSession>(fakeJingleSession), fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, idGen, JID(), to, stream, fileInfo, s5bRegistry, s5bProxy));
+			return boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(boost::shared_ptr<JingleSession>(fakeJingleSession), fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, idGen, JID(), to, stream, fileInfo, s5bRegistry, s5bProxy, crypto.get()));
 		}
 
 		IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) {
@@ -157,6 +165,7 @@ public:
 		}
 
 		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
 			fakeJingleSession = new FakeJingleSession("foo@bar.com/baz", "mysession");
 			jingleContentPayload = boost::make_shared<JingleContentPayload>();
 			fakeRJTCSF = boost::make_shared<OFakeRemoteJingleTransportCandidateSelectorFactory>();
@@ -281,6 +290,7 @@ private:
 	SOCKS5BytestreamProxy* s5bProxy;
 	DummyTimerFactory* timerFactory;
 	DummyConnectionFactory* connectionFactory;
+	boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(OutgoingJingleFileTransferTest);
diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp
index 502cf2d..65ff290 100644
--- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp
@@ -30,6 +30,8 @@
 #include <Swiften/Network/DummyConnection.h>
 #include <Swiften/Network/DummyTimerFactory.h>
 #include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -44,14 +46,12 @@ class SOCKS5BytestreamClientSessionTest : public CppUnit::TestFixture {
 	CPPUNIT_TEST(testReadBytestream);
 	CPPUNIT_TEST_SUITE_END();
 
-	const HostAddressPort destinationAddressPort;
-	const std::string destination;
-
 public:
-	SOCKS5BytestreamClientSessionTest() : destinationAddressPort(HostAddressPort(HostAddress("127.0.0.1"), 8888)),
-		destination(SOCKS5BytestreamRegistry::getHostname("foo", JID("requester@example.com/test"), JID("target@example.com/test"))), eventLoop(NULL), timerFactory(NULL) { }
+	SOCKS5BytestreamClientSessionTest() : destinationAddressPort(HostAddressPort(HostAddress("127.0.0.1"), 8888)) {}
 
 	void setUp() {
+		crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
+		destination = SOCKS5BytestreamRegistry::getHostname("foo", JID("requester@example.com/test"), JID("target@example.com/test"), crypto.get());
 		randomGen.seed(static_cast<unsigned int>(time(NULL)));
 		eventLoop = new DummyEventLoop();
 		timerFactory = new DummyTimerFactory();
@@ -297,10 +297,13 @@ private:
 	};
 
 private:
+	HostAddressPort destinationAddressPort;
+	std::string destination;
 	DummyEventLoop* eventLoop;
 	DummyTimerFactory* timerFactory;
 	boost::shared_ptr<MockeryConnection> connection;
 	const std::vector<HostAddressPort> failingPorts;
+	boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(SOCKS5BytestreamClientSessionTest);
diff --git a/Swiften/Network/BoostNetworkFactories.cpp b/Swiften/Network/BoostNetworkFactories.cpp
index 1265682..9f781e4 100644
--- a/Swiften/Network/BoostNetworkFactories.cpp
+++ b/Swiften/Network/BoostNetworkFactories.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -17,6 +17,8 @@
 #include <Swiften/Network/PlatformProxyProvider.h>
 #include <Swiften/IDN/PlatformIDNConverter.h>
 #include <Swiften/IDN/IDNConverter.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 namespace Swift {
 
@@ -35,9 +37,11 @@ BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop) : eventLoop(e
 	proxyProvider = new PlatformProxyProvider();
 	idnConverter = PlatformIDNConverter::create();
 	domainNameResolver = new PlatformDomainNameResolver(idnConverter, eventLoop);
+	cryptoProvider = PlatformCryptoProvider::create();
 }
 
 BoostNetworkFactories::~BoostNetworkFactories() {
+	delete cryptoProvider;
 	delete domainNameResolver;
 	delete idnConverter;
 	delete proxyProvider;
diff --git a/Swiften/Network/BoostNetworkFactories.h b/Swiften/Network/BoostNetworkFactories.h
index 8bf3576..9c3bab1 100644
--- a/Swiften/Network/BoostNetworkFactories.h
+++ b/Swiften/Network/BoostNetworkFactories.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -67,6 +67,10 @@ namespace Swift {
 				return idnConverter;
 			}
 
+			virtual CryptoProvider* getCryptoProvider() const SWIFTEN_OVERRIDE {
+				return cryptoProvider;
+			}
+
 		private:
 			BoostIOServiceThread ioServiceThread;
 			TimerFactory* timerFactory;
@@ -80,5 +84,6 @@ namespace Swift {
 			ProxyProvider* proxyProvider;
 			EventLoop* eventLoop;
 			IDNConverter* idnConverter;
+			CryptoProvider* cryptoProvider;
 	};
 }
diff --git a/Swiften/Network/NetworkFactories.h b/Swiften/Network/NetworkFactories.h
index 228d92d..dd8e216 100644
--- a/Swiften/Network/NetworkFactories.h
+++ b/Swiften/Network/NetworkFactories.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -19,6 +19,7 @@ namespace Swift {
 	class EventLoop;
 	class IDNConverter;
 	class NetworkEnvironment;
+	class CryptoProvider;
 
 	/**
 	 * An interface collecting network factories.
@@ -38,5 +39,6 @@ namespace Swift {
 			virtual ProxyProvider* getProxyProvider() const = 0;
 			virtual EventLoop* getEventLoop() const = 0;
 			virtual IDNConverter* getIDNConverter() const = 0;
+			virtual CryptoProvider* getCryptoProvider() const = 0;
 	};
 }
diff --git a/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp b/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp
index 249a538..74cdb85 100644
--- a/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp
+++ b/Swiften/SASL/DIGESTMD5ClientAuthenticator.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -8,18 +8,14 @@
 
 #include <cassert>
 
-#include <Swiften/StringCodecs/MD5.h>
 #include <Swiften/StringCodecs/Hexify.h>
 #include <Swiften/Base/Concat.h>
 #include <Swiften/Base/Algorithm.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 namespace Swift {
 
-DIGESTMD5ClientAuthenticator::DIGESTMD5ClientAuthenticator(const std::string& host, const std::string& nonce) : ClientAuthenticator("DIGEST-MD5"), step(Initial), host(host), cnonce(nonce) {
-}
-
-bool DIGESTMD5ClientAuthenticator::canBeUsed() {
-	return MD5::isAllowedForCrypto();
+DIGESTMD5ClientAuthenticator::DIGESTMD5ClientAuthenticator(const std::string& host, const std::string& nonce, CryptoProvider* crypto) : ClientAuthenticator("DIGEST-MD5"), step(Initial), host(host), cnonce(nonce), crypto(crypto) {
 }
 
 boost::optional<SafeByteArray> DIGESTMD5ClientAuthenticator::getResponse() const {
@@ -37,7 +33,7 @@ boost::optional<SafeByteArray> DIGESTMD5ClientAuthenticator::getResponse() const
 
 		// Compute the response value
 		ByteArray A1 = concat(
-				MD5::getHash(
+				crypto->getMD5Hash(
 					concat(createSafeByteArray(getAuthenticationID().c_str()), createSafeByteArray(":"), createSafeByteArray(realm.c_str()), createSafeByteArray(":"), getPassword())),
 				createByteArray(":"), createByteArray(*challenge.getValue("nonce")), createByteArray(":"), createByteArray(cnonce));
 		if (!getAuthorizationID().empty()) {
@@ -45,10 +41,10 @@ boost::optional<SafeByteArray> DIGESTMD5ClientAuthenticator::getResponse() const
 		}
 		ByteArray A2 = createByteArray("AUTHENTICATE:" + digestURI);
 
-		std::string responseValue = Hexify::hexify(MD5::getHash(createByteArray(
-			Hexify::hexify(MD5::getHash(A1)) + ":"
+		std::string responseValue = Hexify::hexify(crypto->getMD5Hash(createByteArray(
+			Hexify::hexify(crypto->getMD5Hash(A1)) + ":"
 			+ *challenge.getValue("nonce") + ":" + nc + ":" + cnonce + ":" + qop + ":"
-			+ Hexify::hexify(MD5::getHash(A2)))));
+			+ Hexify::hexify(crypto->getMD5Hash(A2)))));
 
 
 		DIGESTMD5Properties response;
diff --git a/Swiften/SASL/DIGESTMD5ClientAuthenticator.h b/Swiften/SASL/DIGESTMD5ClientAuthenticator.h
index 813ded2..d141401 100644
--- a/Swiften/SASL/DIGESTMD5ClientAuthenticator.h
+++ b/Swiften/SASL/DIGESTMD5ClientAuthenticator.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -16,13 +16,14 @@
 #include <Swiften/Base/SafeByteArray.h>
 
 namespace Swift {
+	class CryptoProvider;
+
 	class SWIFTEN_API DIGESTMD5ClientAuthenticator : public ClientAuthenticator {
 		public:
-			DIGESTMD5ClientAuthenticator(const std::string& host, const std::string& nonce);
+			DIGESTMD5ClientAuthenticator(const std::string& host, const std::string& nonce, CryptoProvider*);
 			
 			virtual boost::optional<SafeByteArray> getResponse() const;
 			virtual bool setChallenge(const boost::optional<std::vector<unsigned char> >&);
-			static bool canBeUsed();
 
 		private:
 			enum Step {
@@ -32,6 +33,7 @@ namespace Swift {
 			} step;
 			std::string host;
 			std::string cnonce;
+			CryptoProvider* crypto;
 			DIGESTMD5Properties challenge;
 	};
 }
diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
index 38e3289..44fef76 100644
--- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
+++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
@@ -10,9 +10,8 @@
 #include <map>
 #include <boost/lexical_cast.hpp>
 
-#include <Swiften/StringCodecs/SHA1.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 #include <Swiften/StringCodecs/Base64.h>
-#include <Swiften/StringCodecs/HMAC_SHA1.h>
 #include <Swiften/StringCodecs/PBKDF2.h>
 #include <Swiften/IDN/IDNConverter.h>
 #include <Swiften/Base/Concat.h>
@@ -36,7 +35,7 @@ static std::string escape(const std::string& s) {
 }
 
 
-SCRAMSHA1ClientAuthenticator::SCRAMSHA1ClientAuthenticator(const std::string& nonce, bool useChannelBinding, IDNConverter* idnConverter) : ClientAuthenticator(useChannelBinding ? "SCRAM-SHA-1-PLUS" : "SCRAM-SHA-1"), step(Initial), clientnonce(nonce), useChannelBinding(useChannelBinding), idnConverter(idnConverter) {
+SCRAMSHA1ClientAuthenticator::SCRAMSHA1ClientAuthenticator(const std::string& nonce, bool useChannelBinding, IDNConverter* idnConverter, CryptoProvider* crypto) : ClientAuthenticator(useChannelBinding ? "SCRAM-SHA-1-PLUS" : "SCRAM-SHA-1"), step(Initial), clientnonce(nonce), useChannelBinding(useChannelBinding), idnConverter(idnConverter), crypto(crypto) {
 }
 
 boost::optional<SafeByteArray> SCRAMSHA1ClientAuthenticator::getResponse() const {
@@ -44,9 +43,9 @@ boost::optional<SafeByteArray> SCRAMSHA1ClientAuthenticator::getResponse() const
 		return createSafeByteArray(concat(getGS2Header(), getInitialBareClientMessage()));
 	}
 	else if (step == Proof) {
-		ByteArray clientKey = HMAC_SHA1()(saltedPassword, createByteArray("Client Key"));
-		ByteArray storedKey = SHA1::getHash(clientKey);
-		ByteArray clientSignature = HMAC_SHA1()(createSafeByteArray(storedKey), authMessage);
+		ByteArray clientKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Client Key"));
+		ByteArray storedKey = crypto->getSHA1Hash(clientKey);
+		ByteArray clientSignature = crypto->getHMACSHA1(createSafeByteArray(storedKey), authMessage);
 		ByteArray clientProof = clientKey;
 		for (unsigned int i = 0; i < clientProof.size(); ++i) {
 			clientProof[i] ^= clientSignature[i];
@@ -96,13 +95,13 @@ bool SCRAMSHA1ClientAuthenticator::setChallenge(const boost::optional<ByteArray>
 
 		// Compute all the values needed for the server signature
 		try {
-			saltedPassword = PBKDF2::encode<HMAC_SHA1>(idnConverter->getStringPrepared(getPassword(), IDNConverter::SASLPrep), salt, iterations);
+			saltedPassword = PBKDF2::encode(idnConverter->getStringPrepared(getPassword(), IDNConverter::SASLPrep), salt, iterations, crypto);
 		}
 		catch (const std::exception&) {
 		}
 		authMessage = concat(getInitialBareClientMessage(), createByteArray(","), initialServerMessage, createByteArray(","), getFinalMessageWithoutProof());
-		ByteArray serverKey = HMAC_SHA1()(saltedPassword, createByteArray("Server Key"));
-		serverSignature = HMAC_SHA1()(serverKey, authMessage);
+		ByteArray serverKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Server Key"));
+		serverSignature = crypto->getHMACSHA1(serverKey, authMessage);
 
 		step = Proof;
 		return true;
diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h
index da52bbc..b713f9f 100644
--- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h
+++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -16,10 +16,11 @@
 
 namespace Swift {
 	class IDNConverter;
+	class CryptoProvider;
 
 	class SWIFTEN_API SCRAMSHA1ClientAuthenticator : public ClientAuthenticator {
 		public:
-			SCRAMSHA1ClientAuthenticator(const std::string& nonce, bool useChannelBinding, IDNConverter*);
+			SCRAMSHA1ClientAuthenticator(const std::string& nonce, bool useChannelBinding, IDNConverter*, CryptoProvider*);
 
 			void setTLSChannelBindingData(const ByteArray& channelBindingData);
 			
@@ -47,6 +48,7 @@ namespace Swift {
 			ByteArray serverSignature;
 			bool useChannelBinding;
 			IDNConverter* idnConverter;
+			CryptoProvider* crypto;
 			boost::optional<ByteArray> tlsChannelBindingData;
 	};
 }
diff --git a/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp b/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp
index 38bab15..94bcd0a 100644
--- a/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp
+++ b/Swiften/SASL/UnitTest/DIGESTMD5ClientAuthenticatorTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -12,6 +12,9 @@
 #include <Swiften/SASL/DIGESTMD5ClientAuthenticator.h>
 #include <Swiften/Base/ByteArray.h>
 
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
+
 using namespace Swift;
 
 class DIGESTMD5ClientAuthenticatorTest : public CppUnit::TestFixture {
@@ -23,14 +26,18 @@ class DIGESTMD5ClientAuthenticatorTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
+		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
+		}
+
 		void testGetInitialResponse() {
-			DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh");
+			DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get());
 
 			CPPUNIT_ASSERT(!testling.getResponse());
 		}
 
 		void testGetResponse() {
-			DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh");
+			DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get());
 
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 			testling.setChallenge(createByteArray(
@@ -44,7 +51,7 @@ class DIGESTMD5ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testGetResponse_WithAuthorizationID() {
-			DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh");
+			DIGESTMD5ClientAuthenticator testling("xmpp.example.com", "abcdefgh", crypto.get());
 
 			testling.setCredentials("user", createSafeByteArray("pass"), "myauthzid");
 			testling.setChallenge(createByteArray(
@@ -56,6 +63,9 @@ class DIGESTMD5ClientAuthenticatorTest : public CppUnit::TestFixture {
 
 			CPPUNIT_ASSERT_EQUAL(createSafeByteArray("authzid=\"myauthzid\",charset=utf-8,cnonce=\"abcdefgh\",digest-uri=\"xmpp/xmpp.example.com\",nc=00000001,nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\",qop=auth,realm=\"example.com\",response=4293834432b6e7889a2dee7e8fe7dd06,username=\"user\""), response);
 		}
+	
+	private:
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(DIGESTMD5ClientAuthenticatorTest);
diff --git a/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp b/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp
index 6266f3e..3341ad8 100644
--- a/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp
+++ b/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp
@@ -13,6 +13,8 @@
 #include <Swiften/Base/ByteArray.h>
 #include <Swiften/IDN/IDNConverter.h>
 #include <Swiften/IDN/PlatformIDNConverter.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -42,10 +44,11 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 	public:
 		void setUp() {
 			idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create());
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
 		}
 
 		void testGetInitialResponse() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 
 			SafeByteArray response = *testling.getResponse();
@@ -54,7 +57,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testGetInitialResponse_UsernameHasSpecialChars() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get());
 			testling.setCredentials(",us=,er=", createSafeByteArray("pass"), "");
 
 			SafeByteArray response = *testling.getResponse();
@@ -63,7 +66,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testGetInitialResponse_WithAuthorizationID() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "auth");
 
 			SafeByteArray response = *testling.getResponse();
@@ -72,7 +75,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testGetInitialResponse_WithAuthorizationIDWithSpecialChars() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "a=u,th");
 
 			SafeByteArray response = *testling.getResponse();
@@ -81,7 +84,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testGetInitialResponse_WithoutChannelBindingWithTLSChannelBindingData() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", false, idnConverter.get(), crypto.get());
 			testling.setTLSChannelBindingData(createByteArray("xyza"));
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 
@@ -91,7 +94,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testGetInitialResponse_WithChannelBindingWithTLSChannelBindingData() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", true, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH", true, idnConverter.get(), crypto.get());
 			testling.setTLSChannelBindingData(createByteArray("xyza"));
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 
@@ -101,7 +104,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testGetFinalResponse() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 			testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
 
@@ -111,7 +114,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testGetFinalResponse_WithoutChannelBindingWithTLSChannelBindingData() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 			testling.setTLSChannelBindingData(createByteArray("xyza"));
 			testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
@@ -122,7 +125,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testGetFinalResponse_WithChannelBindingWithTLSChannelBindingData() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", true, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", true, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 			testling.setTLSChannelBindingData(createByteArray("xyza"));
 			testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
@@ -133,7 +136,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testSetFinalChallenge() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 			testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
 
@@ -143,7 +146,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testSetChallenge() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 
 			bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
@@ -152,7 +155,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testSetChallenge_InvalidClientNonce() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 
 			bool result = testling.setChallenge(createByteArray("r=abcdefgiABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
@@ -161,7 +164,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testSetChallenge_OnlyClientNonce() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 
 			bool result = testling.setChallenge(createByteArray("r=abcdefgh,s=MTIzNDU2NzgK,i=4096"));
@@ -170,7 +173,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testSetChallenge_InvalidIterations() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 
 			bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=bla"));
@@ -179,7 +182,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testSetChallenge_MissingIterations() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 
 			bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK"));
@@ -188,7 +191,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testSetChallenge_ZeroIterations() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 
 			bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=0"));
@@ -197,7 +200,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testSetChallenge_NegativeIterations() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 
 			bool result = testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=-1"));
@@ -206,7 +209,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testSetFinalChallenge_InvalidChallenge() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 			testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
 			bool result = testling.setChallenge(createByteArray("v=e26kI69ICb6zosapLLxrER/631A="));
@@ -215,7 +218,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		void testGetResponseAfterFinalChallenge() {
-			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get());
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh", false, idnConverter.get(), crypto.get());
 			testling.setCredentials("user", createSafeByteArray("pass"), "");
 			testling.setChallenge(createByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
 			testling.setChallenge(createByteArray("v=Dd+Q20knZs9jeeK0pi1Mx1Se+yo="));
@@ -224,6 +227,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		}
 
 		boost::shared_ptr<IDNConverter> idnConverter;
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(SCRAMSHA1ClientAuthenticatorTest);
diff --git a/Swiften/SConscript b/Swiften/SConscript
index b9fad17..1cb3543 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -221,8 +221,6 @@ if env["SCONS_STAGE"] == "build" :
 			"Session/BasicSessionStream.cpp",
 			"Session/BOSHSessionStream.cpp",
 			"StringCodecs/Base64.cpp",
-			"StringCodecs/SHA256.cpp",
-			"StringCodecs/MD5.cpp",
 			"StringCodecs/Hexify.cpp",
 			"Whiteboard/WhiteboardResponder.cpp",
 			"Whiteboard/WhiteboardSession.cpp",
@@ -241,6 +239,7 @@ if env["SCONS_STAGE"] == "build" :
 			"IDN",
 			"SASL",
 			"TLS",
+			"Crypto",
 			"EventLoop",
 			"Parser",
 			"JID",
@@ -267,11 +266,6 @@ if env["SCONS_STAGE"] == "build" :
 		])
 
 	myenv = swiften_env.Clone()
-	if myenv["PLATFORM"] == "win32":
-		sources.append("StringCodecs/SHA1_Windows.cpp")
-	else:
-		sources.append("StringCodecs/SHA1.cpp")
-
 	if myenv["PLATFORM"] != "darwin" and myenv["PLATFORM"] != "win32" and myenv.get("HAVE_GCONF", 0) :
 		env.MergeFlags(env["GCONF_FLAGS"])
 
@@ -441,11 +435,7 @@ if env["SCONS_STAGE"] == "build" :
 			File("StreamStack/UnitTest/StreamStackTest.cpp"),
 			File("StreamStack/UnitTest/XMPPLayerTest.cpp"),
 			File("StringCodecs/UnitTest/Base64Test.cpp"),
-			File("StringCodecs/UnitTest/SHA1Test.cpp"),
-			File("StringCodecs/UnitTest/SHA256Test.cpp"),
-			File("StringCodecs/UnitTest/MD5Test.cpp"),
 			File("StringCodecs/UnitTest/HexifyTest.cpp"),
-			File("StringCodecs/UnitTest/HMACTest.cpp"),
 			File("StringCodecs/UnitTest/PBKDF2Test.cpp"),
 			File("TLS/UnitTest/ServerIdentityVerifierTest.cpp"),
 			File("TLS/UnitTest/CertificateTest.cpp"),
diff --git a/Swiften/StringCodecs/HMAC.h b/Swiften/StringCodecs/HMAC.h
deleted file mode 100644
index 8b02d88..0000000
--- a/Swiften/StringCodecs/HMAC.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <Swiften/Base/SafeByteArray.h>
-#include <Swiften/Base/ByteArray.h>
-#include <Swiften/Base/Algorithm.h>
-#include <cassert>
-
-namespace Swift {
-	namespace HMAC_Detail {
-		template<typename KeyType> struct KeyWrapper;
-		template<> struct KeyWrapper<ByteArray> {
-			ByteArray wrap(const ByteArray& hash) const {
-				return hash;
-			}
-		};
-		template<> struct KeyWrapper<SafeByteArray> {
-			SafeByteArray wrap(const ByteArray& hash) const {
-				return createSafeByteArray(hash);
-			}
-		};
-
-		template<typename Hash, typename KeyType, int BlockSize>
-		static ByteArray getHMAC(const KeyType& key, const ByteArray& data) {
-			Hash hash;
-
-			// Create the padded key
-			KeyType paddedKey(key.size() <= BlockSize ? key : KeyWrapper<KeyType>().wrap(hash(key)));
-			paddedKey.resize(BlockSize, 0x0);
-
-			// Create the first value
-			KeyType x(paddedKey);
-			for (unsigned int i = 0; i < x.size(); ++i) {
-				x[i] ^= 0x36;
-			}
-			append(x, data);
-
-			// Create the second value
-			KeyType y(paddedKey);
-			for (unsigned int i = 0; i < y.size(); ++i) {
-				y[i] ^= 0x5c;
-			}
-			append(y, hash(x));
-
-			return hash(y);
-		}
-	}
-
-	template<typename Hash, int BlockSize>
-	class HMAC {
-		private:
-
-		public:
-			ByteArray operator()(const ByteArray& key, const ByteArray& data) const {
-				return HMAC_Detail::getHMAC<Hash,ByteArray,BlockSize>(key, data);
-			}
-
-			ByteArray operator()(const SafeByteArray& key, const ByteArray& data) const {
-				return HMAC_Detail::getHMAC<Hash,SafeByteArray,BlockSize>(key, data);
-			}
-	};
-}
diff --git a/Swiften/StringCodecs/HMAC_SHA1.h b/Swiften/StringCodecs/HMAC_SHA1.h
deleted file mode 100644
index 8f403c6..0000000
--- a/Swiften/StringCodecs/HMAC_SHA1.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <Swiften/StringCodecs/HMAC.h>
-#include <Swiften/StringCodecs/SHA1.h>
-
-namespace Swift {
-	typedef HMAC<SHA1, 64> HMAC_SHA1;
-}
diff --git a/Swiften/StringCodecs/HMAC_SHA256.h b/Swiften/StringCodecs/HMAC_SHA256.h
deleted file mode 100644
index 2d856cb..0000000
--- a/Swiften/StringCodecs/HMAC_SHA256.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2011 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <Swiften/StringCodecs/HMAC.h>
-#include <Swiften/StringCodecs/SHA256.h>
-
-namespace Swift {
-	typedef HMAC<SHA256, 64> HMAC_SHA256;
-}
diff --git a/Swiften/StringCodecs/MD5.cpp b/Swiften/StringCodecs/MD5.cpp
deleted file mode 100644
index ffed37b..0000000
--- a/Swiften/StringCodecs/MD5.cpp
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-/*
- * This implementation is shamelessly copied from L. Peter Deutsch's
- * implementation, and altered to use our own defines and datastructures.
- * Original license below.
- *//*
-	Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.
-
-	This software is provided 'as-is', without any express or implied
-	warranty.  In no event will the authors be held liable for any damages
-	arising from the use of this software.
-
-	Permission is granted to anyone to use this software for any purpose,
-	including commercial applications, and to alter it and redistribute it
-	freely, subject to the following restrictions:
-
-	1. The origin of this software must not be misrepresented; you must not
-		 claim that you wrote the original software. If you use this software
-		 in a product, an acknowledgment in the product documentation would be
-		 appreciated but is not required.
-	2. Altered source versions must be plainly marked as such, and must not be
-		 misrepresented as being the original software.
-	3. This notice may not be removed or altered from any source distribution.
-
-	L. Peter Deutsch
-	ghost@aladdin.com
- */
-
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wcast-align"
-#pragma clang diagnostic ignored "-Wmissing-prototypes"
-
-#include <Swiften/StringCodecs/MD5.h>
-
-#include <cassert>
-#include <string.h>
-
-#include <Swiften/Base/ByteArray.h>
-#include <Swiften/Base/Platform.h>
-
-#ifdef SWIFTEN_PLATFORM_WIN32
-#include <Swiften/Base/WindowsRegistry.h>
-#endif
-
-namespace Swift {
-
-typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
-
-/* Define the state of the MD5 Algorithm. */
-typedef struct md5_state_s {
-		md5_word_t count[2];				/* message length in bits, lsw first */
-		md5_word_t abcd[4];					/* digest buffer */
-		md5_byte_t buf[64];					/* accumulate block */
-} md5_state_t;
-
-#define T_MASK ((md5_word_t)~0)
-#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
-#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3		0x242070db
-#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
-#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6		0x4787c62a
-#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
-#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9		0x698098d8
-#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
-#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
-#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13		 0x6b901122
-#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
-#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16		 0x49b40821
-#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
-#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19		 0x265e5a51
-#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
-#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22		 0x02441453
-#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
-#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25		 0x21e1cde6
-#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
-#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28		 0x455a14ed
-#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
-#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31		 0x676f02d9
-#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
-#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
-#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35		 0x6d9d6122
-#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
-#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38		 0x4bdecfa9
-#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
-#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41		 0x289b7ec6
-#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
-#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44		 0x04881d05
-#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
-#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47		 0x1fa27cf8
-#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
-#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50		 0x432aff97
-#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
-#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53		 0x655b59c3
-#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
-#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
-#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57		 0x6fa87e4f
-#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
-#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60		 0x4e0811a1
-#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
-#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63		 0x2ad7d2bb
-#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
-
-
-static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) {
-		md5_word_t
-		a = pms->abcd[0], b = pms->abcd[1],
-		c = pms->abcd[2], d = pms->abcd[3];
-		md5_word_t t;
-#ifdef SWIFTEN_LITTLE_ENDIAN
-		/* Define storage for little-endian or both types of CPUs. */
-		md5_word_t xbuf[16];
-		const md5_word_t *X;
-#else
-		/* Define storage only for big-endian CPUs. */
-		md5_word_t X[16];
-#endif
-
-		{
-#ifdef SWIFTEN_LITTLE_ENDIAN
-				{
-						/*
-						 * On little-endian machines, we can process properly aligned
-						 * data without copying it.
-						 */
-						if (!((data - (const md5_byte_t *)0) & 3)) {
-								/* data are properly aligned */
-								X = (const md5_word_t *)data;
-						} else {
-								/* not aligned */
-								memcpy(xbuf, data, 64);
-								X = xbuf;
-						}
-				}
-#else
-				{
-						/*
-						 * On big-endian machines, we must arrange the bytes in the
-						 * right order.
-						 */
-						const md5_byte_t *xp = data;
-						int i;
-
-						for (i = 0; i < 16; ++i, xp += 4)
-								X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
-				}
-#endif
-		}
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
-		/* Round 1. */
-		/* Let [abcd k s i] denote the operation
-			 a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
-	t = a + F(b,c,d) + X[k] + Ti;\
-	a = ROTATE_LEFT(t, s) + b
-		/* Do the following 16 operations. */
-		SET(a, b, c, d,  0,  7,  T1);
-		SET(d, a, b, c,  1, 12,  T2);
-		SET(c, d, a, b,  2, 17,  T3);
-		SET(b, c, d, a,  3, 22,  T4);
-		SET(a, b, c, d,  4,  7,  T5);
-		SET(d, a, b, c,  5, 12,  T6);
-		SET(c, d, a, b,  6, 17,  T7);
-		SET(b, c, d, a,  7, 22,  T8);
-		SET(a, b, c, d,  8,  7,  T9);
-		SET(d, a, b, c,  9, 12, T10);
-		SET(c, d, a, b, 10, 17, T11);
-		SET(b, c, d, a, 11, 22, T12);
-		SET(a, b, c, d, 12,  7, T13);
-		SET(d, a, b, c, 13, 12, T14);
-		SET(c, d, a, b, 14, 17, T15);
-		SET(b, c, d, a, 15, 22, T16);
-#undef SET
-
-		 /* Round 2. */
-		 /* Let [abcd k s i] denote the operation
-					a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-	t = a + G(b,c,d) + X[k] + Ti;\
-	a = ROTATE_LEFT(t, s) + b
-		 /* Do the following 16 operations. */
-		SET(a, b, c, d,  1,  5, T17);
-		SET(d, a, b, c,  6,  9, T18);
-		SET(c, d, a, b, 11, 14, T19);
-		SET(b, c, d, a,  0, 20, T20);
-		SET(a, b, c, d,  5,  5, T21);
-		SET(d, a, b, c, 10,  9, T22);
-		SET(c, d, a, b, 15, 14, T23);
-		SET(b, c, d, a,  4, 20, T24);
-		SET(a, b, c, d,  9,  5, T25);
-		SET(d, a, b, c, 14,  9, T26);
-		SET(c, d, a, b,  3, 14, T27);
-		SET(b, c, d, a,  8, 20, T28);
-		SET(a, b, c, d, 13,  5, T29);
-		SET(d, a, b, c,  2,  9, T30);
-		SET(c, d, a, b,  7, 14, T31);
-		SET(b, c, d, a, 12, 20, T32);
-#undef SET
-
-		 /* Round 3. */
-		 /* Let [abcd k s t] denote the operation
-					a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
-	t = a + H(b,c,d) + X[k] + Ti;\
-	a = ROTATE_LEFT(t, s) + b
-		 /* Do the following 16 operations. */
-		SET(a, b, c, d,  5,  4, T33);
-		SET(d, a, b, c,  8, 11, T34);
-		SET(c, d, a, b, 11, 16, T35);
-		SET(b, c, d, a, 14, 23, T36);
-		SET(a, b, c, d,  1,  4, T37);
-		SET(d, a, b, c,  4, 11, T38);
-		SET(c, d, a, b,  7, 16, T39);
-		SET(b, c, d, a, 10, 23, T40);
-		SET(a, b, c, d, 13,  4, T41);
-		SET(d, a, b, c,  0, 11, T42);
-		SET(c, d, a, b,  3, 16, T43);
-		SET(b, c, d, a,  6, 23, T44);
-		SET(a, b, c, d,  9,  4, T45);
-		SET(d, a, b, c, 12, 11, T46);
-		SET(c, d, a, b, 15, 16, T47);
-		SET(b, c, d, a,  2, 23, T48);
-#undef SET
-
-		 /* Round 4. */
-		 /* Let [abcd k s t] denote the operation
-					a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-	t = a + I(b,c,d) + X[k] + Ti;\
-	a = ROTATE_LEFT(t, s) + b
-		 /* Do the following 16 operations. */
-		SET(a, b, c, d,  0,  6, T49);
-		SET(d, a, b, c,  7, 10, T50);
-		SET(c, d, a, b, 14, 15, T51);
-		SET(b, c, d, a,  5, 21, T52);
-		SET(a, b, c, d, 12,  6, T53);
-		SET(d, a, b, c,  3, 10, T54);
-		SET(c, d, a, b, 10, 15, T55);
-		SET(b, c, d, a,  1, 21, T56);
-		SET(a, b, c, d,  8,  6, T57);
-		SET(d, a, b, c, 15, 10, T58);
-		SET(c, d, a, b,  6, 15, T59);
-		SET(b, c, d, a, 13, 21, T60);
-		SET(a, b, c, d,  4,  6, T61);
-		SET(d, a, b, c, 11, 10, T62);
-		SET(c, d, a, b,  2, 15, T63);
-		SET(b, c, d, a,  9, 21, T64);
-#undef SET
-
-		 /* Then perform the following additions. (That is increment each
-				of the four registers by the value it had before this block
-				was started.) */
-		pms->abcd[0] += a;
-		pms->abcd[1] += b;
-		pms->abcd[2] += c;
-		pms->abcd[3] += d;
-}
-
-void
-md5_init(md5_state_t *pms)
-{
-		pms->count[0] = pms->count[1] = 0;
-		pms->abcd[0] = 0x67452301;
-		pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
-		pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
-		pms->abcd[3] = 0x10325476;
-}
-
-void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
-{
-		const md5_byte_t *p = data;
-		int left = nbytes;
-		int offset = (pms->count[0] >> 3) & 63;
-		md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
-		if (nbytes <= 0)
-				return;
-
-		/* Update the message length. */
-		pms->count[1] += nbytes >> 29;
-		pms->count[0] += nbits;
-		if (pms->count[0] < nbits)
-				pms->count[1]++;
-
-		/* Process an initial partial block. */
-		if (offset) {
-				int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
-				memcpy(pms->buf + offset, p, copy);
-				if (offset + copy < 64)
-						return;
-				p += copy;
-				left -= copy;
-				md5_process(pms, pms->buf);
-		}
-
-		/* Process full blocks. */
-		for (; left >= 64; p += 64, left -= 64)
-				md5_process(pms, p);
-
-		/* Process a final partial block. */
-		if (left)
-				memcpy(pms->buf, p, left);
-}
-
-void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
-{
-		static const md5_byte_t pad[64] = {
-				0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-		};
-		md5_byte_t data[8];
-		int i;
-
-		/* Save the length before padding. */
-		for (i = 0; i < 8; ++i)
-				data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
-		/* Pad to 56 bytes mod 64. */
-		md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
-		/* Append the length. */
-		md5_append(pms, data, 8);
-		for (i = 0; i < 16; ++i)
-				digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}
-
-namespace {
-	template<typename SourceType>
-	ByteArray getMD5Hash(const SourceType& data) {
-		ByteArray digest;
-		digest.resize(16);
-
-		md5_state_t state;
-		md5_init(&state);
-		md5_append(&state, reinterpret_cast<const md5_byte_t*>(vecptr(data)), data.size());
-		md5_finish(&state, reinterpret_cast<md5_byte_t*>(vecptr(digest)));
-
-		return digest;
-	}
-}
-
-MD5::MD5() {
-	state = new md5_state_t;
-	md5_init(state);
-}
-
-MD5::~MD5() {
-	delete state;
-}
-
-MD5& MD5::update(const std::vector<unsigned char>& input) {
-	md5_append(state, reinterpret_cast<const md5_byte_t*>(vecptr(input)), input.size());
-	return *this;
-}
-
-std::vector<unsigned char> MD5::getHash() {
-	ByteArray digest;
-	digest.resize(16);
-	md5_finish(state, reinterpret_cast<md5_byte_t*>(vecptr(digest)));
-	return digest;
-}
-
-ByteArray MD5::getHash(const ByteArray& data) {
-	return getMD5Hash(data);
-}
-
-ByteArray MD5::getHash(const SafeByteArray& data) {
-	return getMD5Hash(data);
-}
-
-bool MD5::isAllowedForCrypto() {
-#ifdef SWIFTEN_PLATFORM_WIN32
-	return !WindowsRegistry::isFIPSEnabled();
-#else
-	return true;
-#endif
-}
-
-}
diff --git a/Swiften/StringCodecs/MD5.h b/Swiften/StringCodecs/MD5.h
deleted file mode 100644
index 48d62af..0000000
--- a/Swiften/StringCodecs/MD5.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <Swiften/Base/API.h>
-#include <Swiften/Base/ByteArray.h>
-#include <Swiften/Base/SafeByteArray.h>
-
-namespace Swift {
-	struct md5_state_s;
-
-	class SWIFTEN_API MD5 {
-		public:
-			MD5();
-			~MD5();
-
-			MD5& update(const std::vector<unsigned char>& data);
-			std::vector<unsigned char> getHash();
-
-			static ByteArray getHash(const ByteArray& data);
-			static ByteArray getHash(const SafeByteArray& data);
-			static bool isAllowedForCrypto();
-
-		private:
-			md5_state_s* state;
-	};
-}
diff --git a/Swiften/StringCodecs/PBKDF2.h b/Swiften/StringCodecs/PBKDF2.h
index 0c04145..ae0bb17 100644
--- a/Swiften/StringCodecs/PBKDF2.h
+++ b/Swiften/StringCodecs/PBKDF2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -8,18 +8,17 @@
 
 #include <Swiften/Base/SafeByteArray.h>
 #include <Swiften/Base/Concat.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 namespace Swift {
 	class PBKDF2 {
 		public:
-			template<typename PRF>
-			static ByteArray encode(const SafeByteArray& password, const ByteArray& salt, int iterations) {
-				PRF prf;
-				ByteArray u = prf(password, concat(salt, createByteArray("\0\0\0\1", 4)));
+			static ByteArray encode(const SafeByteArray& password, const ByteArray& salt, int iterations, CryptoProvider* crypto) {
+				ByteArray u = crypto->getHMACSHA1(password, concat(salt, createByteArray("\0\0\0\1", 4)));
 				ByteArray result(u);
 				int i = 1;
 				while (i < iterations) {
-					u = prf(password, u);
+					u = crypto->getHMACSHA1(password, u);
 					for (unsigned int j = 0; j < u.size(); ++j) {
 						result[j] ^= u[j];
 					}
diff --git a/Swiften/StringCodecs/SHA1.cpp b/Swiften/StringCodecs/SHA1.cpp
deleted file mode 100644
index 8b03989..0000000
--- a/Swiften/StringCodecs/SHA1.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <Swiften/StringCodecs/SHA1.h>
-
-#include <Swiften/Base/Platform.h>
-
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-
-using namespace Swift;
-
-/*
-SHA-1 in C
-By Steve Reid <steve@edmweb.com>
-100% Public Domain
-
-Test Vectors (from FIPS PUB 180-1)
-"abc"
-	A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-	84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
-	34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-/* #define LITTLE_ENDIAN * This should be #define'd if true. */
-/* #define SHA1HANDSOFF * Copies data before messing with it. */
-
-#include <stdio.h>
-#include <string.h>
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-#ifdef SWIFTEN_LITTLE_ENDIAN
-#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
-		|(rol(block->l[i],8)&0x00FF00FF))
-#else
-#define blk0(i) block->l[i]
-#endif
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
-		^block->l[(i+2)&15]^block->l[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-void SHA1::Transform(boost::uint32_t state[5], boost::uint8_t buffer[64])
-{
-boost::uint32_t a, b, c, d, e;
-typedef union {
-		boost::uint8_t c[64];
-		boost::uint32_t l[16];
-} CHAR64LONG16;
-CHAR64LONG16* block;
-#ifdef SHA1HANDSOFF
-static boost::uint8_t workspace[64];
-		block = (CHAR64LONG16*)workspace;
-		memcpy(block, buffer, 64);
-#else
-		block = reinterpret_cast<CHAR64LONG16*>(buffer);
-#endif
-		/* Copy context->state[] to working vars */
-		a = state[0];
-		b = state[1];
-		c = state[2];
-		d = state[3];
-		e = state[4];
-		/* 4 rounds of 20 operations each. Loop unrolled. */
-		R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-		R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-		R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-		R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-		R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-		R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-		R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-		R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-		R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-		R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-		R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-		R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-		R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-		R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-		R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-		R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-		R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-		R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-		R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-		R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-		/* Add the working vars back into context.state[] */
-		state[0] += a;
-		state[1] += b;
-		state[2] += c;
-		state[3] += d;
-		state[4] += e;
-		/* Wipe variables */
-		a = b = c = d = e = 0;
-}
-
-
-/* SHA1Init - Initialize new context */
-
-void SHA1::Init(SHA1::CTX* context)
-{
-		/* SHA1 initialization constants */
-		context->state[0] = 0x67452301;
-		context->state[1] = 0xEFCDAB89;
-		context->state[2] = 0x98BADCFE;
-		context->state[3] = 0x10325476;
-		context->state[4] = 0xC3D2E1F0;
-		context->count[0] = context->count[1] = 0;
-}
-
-
-/* Run your data through this. */
-
-void SHA1::Update(SHA1::CTX* context, boost::uint8_t* data, unsigned int len)
-{
-unsigned int i, j;
-
-		j = (context->count[0] >> 3) & 63;
-		if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
-		context->count[1] += (len >> 29);
-		if ((j + len) > 63) {
-				memcpy(&context->buffer[j], data, (i = 64-j));
-				Transform(context->state, context->buffer);
-				for ( ; i + 63 < len; i += 64) {
-						Transform(context->state, &data[i]);
-				}
-				j = 0;
-		}
-		else i = 0;
-		memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-/* Add padding and return the message digest. */
-
-void SHA1::Final(boost::uint8_t digest[20], SHA1::CTX* context)
-{
-boost::uint32_t i, j;
-boost::uint8_t finalcount[8];
-
-		for (i = 0; i < 8; i++) {
-				finalcount[i] = (boost::uint8_t) ((context->count[(i >= 4 ? 0 : 1)]
-				 >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
-		}
-		Update(context, (boost::uint8_t *)("\200"), 1);
-		while ((context->count[0] & 504) != 448) {
-				Update(context, (boost::uint8_t *)("\0"), 1);
-		}
-		Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
-		for (i = 0; i < 20; i++) {
-				digest[i] = (boost::uint8_t)
-				 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
-		}
-		/* Wipe variables */
-		i = j = 0;
-		memset(context->buffer, 0, 64);
-		memset(context->state, 0, 20);
-		memset(context->count, 0, 8);
-		memset(&finalcount, 0, 8);
-#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
-		Transform(context->state, context->buffer);
-#endif
-}
-
-// -----------------------------------------------------------------------------
-
-namespace Swift {
-
-SHA1::SHA1() {
-	Init(&context);
-}
-
-SHA1& SHA1::update(const std::vector<unsigned char>& input) {
-	std::vector<unsigned char> inputCopy(input);
-	Update(&context, (boost::uint8_t*) vecptr(inputCopy), static_cast<unsigned int>(inputCopy.size()));
-	return *this;
-}
-
-std::vector<unsigned char> SHA1::getHash() const {
-	std::vector<unsigned char> digest;
-	digest.resize(20);
-	CTX contextCopy(context);
-	Final((boost::uint8_t*) vecptr(digest), &contextCopy);
-	return digest;
-}
-
-template<typename Container>
-ByteArray SHA1::getHashInternal(const Container& input) {
-	CTX context;
-	Init(&context);
-
-	Container inputCopy(input);
-	Update(&context, (boost::uint8_t*) vecptr(inputCopy), static_cast<unsigned int>(inputCopy.size()));
-
-	ByteArray digest;
-	digest.resize(20);
-	Final((boost::uint8_t*) vecptr(digest), &context);
-
-	return digest;
-}
-
-ByteArray SHA1::getHash(const ByteArray& input) {
-	return getHashInternal(input);
-}
-
-ByteArray SHA1::getHash(const SafeByteArray& input) {
-	return getHashInternal(input);
-}
-
-
-}
diff --git a/Swiften/StringCodecs/SHA1.h b/Swiften/StringCodecs/SHA1.h
deleted file mode 100644
index 30e757c..0000000
--- a/Swiften/StringCodecs/SHA1.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#ifdef SWIFTEN_PLATFORM_WIN32
-#include "SHA1_Windows.h"
-#else
-
-#include <vector>
-#include <boost/cstdint.hpp>
-
-#include <Swiften/Base/API.h>
-#include <Swiften/Base/ByteArray.h>
-#include <Swiften/Base/SafeByteArray.h>
-
-namespace Swift {
-	class SWIFTEN_API SHA1 {
-		public:
-			SHA1();
-
-			SHA1& update(const std::vector<unsigned char>& data);
-			std::vector<unsigned char> getHash() const;
-
-			/**
-			 * Equivalent of:
-			 *	SHA1().update(data),getHash(), but slightly more efficient and
-			 *	convenient.
-			 */
-			static ByteArray getHash(const ByteArray& data);
-			static ByteArray getHash(const SafeByteArray& data);
-
-			ByteArray operator()(const SafeByteArray& data) {
-				return getHash(data);
-			}
-
-			ByteArray operator()(const ByteArray& data) {
-				return getHash(data);
-			}
-
-		private:
-			typedef struct {
-					boost::uint32_t state[5];
-					boost::uint32_t count[2];
-					boost::uint8_t buffer[64];
-			} CTX;
-			static void Init(CTX* context);
-			static void Transform(boost::uint32_t state[5], boost::uint8_t buffer[64]);
-			static void Update(CTX* context, boost::uint8_t* data, unsigned int len);
-			static void Final(boost::uint8_t digest[20], CTX* context);
-
-			template<typename Container> static	ByteArray getHashInternal(const Container& input);
-
-		private:
-			CTX context;
-	};
-}
-
-#endif
diff --git a/Swiften/StringCodecs/SHA256.cpp b/Swiften/StringCodecs/SHA256.cpp
deleted file mode 100644
index 6e3c4ec..0000000
--- a/Swiften/StringCodecs/SHA256.cpp
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (c) 2011 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <Swiften/StringCodecs/SHA256.h>
-
-#include <cassert>
-#include <algorithm>
-#include <string.h>
-
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wunused-macros"
-#pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
-
-using namespace Swift;
-
-// Copied & adapted from LibTomCrypt, by Tom St Denis, tomstdenis@gmail.com, http://libtom.org
-// Substituted some macros by the platform-independent (slower) variants
-
-#include <stdlib.h>
-
-#define CRYPT_OK 0
-#define CRYPT_INVALID_ARG -1
-#define LTC_ARGCHK assert
-
-#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
-#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
-
-#define LOAD32H(x, y)														 \
-		 { x = ((unsigned long)((y)[0] & 255)<<24) | \
-					 ((unsigned long)((y)[1] & 255)<<16) | \
-					 ((unsigned long)((y)[2] & 255)<<8)  | \
-					 ((unsigned long)((y)[3] & 255)); }
-
-#define STORE32H(x, y)																																		 \
-		 { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255);	 \
-			 (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
-
-#define STORE64H(x, y)																																		 \
-	 { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);		 \
-		 (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);		 \
-		 (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);		 \
-		 (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
-
-/* a simple macro for making hash "process" functions */
-#define HASH_PROCESS(func_name, compress_name, state_var, block_size)												\
-int func_name (State * md, const unsigned char *in, unsigned int inlen)								\
-{																																														\
-		unsigned long n;																																				\
-		int						err;																																			\
-		LTC_ARGCHK(md != NULL);																																	\
-		LTC_ARGCHK(in != NULL || inlen == 0);																																	\
-		if (md-> curlen > sizeof(md->buf)) {														 \
-			 return CRYPT_INVALID_ARG;																														\
-		}																																												\
-		while (inlen > 0) {																																			\
-				if (md->curlen == 0 && inlen >= block_size) {														\
-					 if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) {								\
-							return err;																																		\
-					 }																																								\
-					 md-> length += block_size * 8;																				 \
-					 in							+= block_size;																										\
-					 inlen					-= block_size;																										\
-				} else {																																						\
-					 n = std::min(inlen, (block_size - md-> curlen));														\
-					 memcpy(md-> buf + md-> curlen, in, (size_t)n);							 \
-					 md-> curlen += n;																										 \
-					 in							+= n;																															\
-					 inlen					-= n;																															\
-					 if (md-> curlen == block_size) {																			 \
-							if ((err = compress_name (md, md-> buf)) != CRYPT_OK) {						 \
-								 return err;																																\
-							}																																							\
-							md-> length += 8*block_size;																			 \
-							md-> curlen = 0;																									 \
-					 }																																								\
-			 }																																										\
-		}																																												\
-		return CRYPT_OK;																																				\
-}
-
-#ifdef LTC_SMALL_CODE
-/* the K array */
-static const boost::uint32_t K[64] = {
-		0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
-		0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
-		0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
-		0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
-		0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
-		0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
-		0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
-		0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
-		0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
-		0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
-		0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
-		0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
-		0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
-};
-#endif
-
-/* Various logical functions */
-#define Ch(x,y,z)				(z ^ (x & (y ^ z)))
-#define Maj(x,y,z)			(((x | y) & z) | (x & y)) 
-#define S(x, n)					RORc((x),(n))
-#define R(x, n)					(((x)&0xFFFFFFFFUL)>>(n))
-#define Sigma0(x)				(S(x, 2) ^ S(x, 13) ^ S(x, 22))
-#define Sigma1(x)				(S(x, 6) ^ S(x, 11) ^ S(x, 25))
-#define Gamma0(x)				(S(x, 7) ^ S(x, 18) ^ R(x, 3))
-#define Gamma1(x)				(S(x, 17) ^ S(x, 19) ^ R(x, 10))
-
-#ifdef LTC_CLEAN_STACK
-int SHA256::_compress(State * md, unsigned char *buf)
-#else
-int  SHA256::compress(State * md, unsigned char *buf)
-#endif
-{
-		boost::uint32_t S[8], W[64], t0, t1;
-#ifdef LTC_SMALL_CODE
-		boost::uint32_t t;
-#endif
-		int i;
-
-		/* copy state into S */
-		for (i = 0; i < 8; i++) {
-				S[i] = md->state[i];
-		}
-
-		/* copy the state into 512-bits into W[0..15] */
-		for (i = 0; i < 16; i++) {
-				LOAD32H(W[i], buf + (4*i));
-		}
-
-		/* fill W[16..63] */
-		for (i = 16; i < 64; i++) {
-				W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
-		}				 
-
-		/* Compress */
-#ifdef LTC_SMALL_CODE		
-#define RND(a,b,c,d,e,f,g,h,i)												 \
-		 t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];	 \
-		 t1 = Sigma0(a) + Maj(a, b, c);										 \
-		 d += t0;																					 \
-		 h	= t0 + t1;
-
-		 for (i = 0; i < 64; ++i) {
-				 RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);
-				 t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; 
-				 S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
-		 }	
-#else 
-#define RND(a,b,c,d,e,f,g,h,i,ki)										 \
-		 t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i];	 \
-		 t1 = Sigma0(a) + Maj(a, b, c);									 \
-		 d += t0;																				 \
-		 h	= t0 + t1;
-
-		RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
-		RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
-		RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
-		RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
-		RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
-		RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
-		RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
-		RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
-		RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
-		RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
-		RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
-		RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
-		RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
-		RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
-		RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
-		RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
-		RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
-		RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
-		RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
-		RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
-		RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
-		RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
-		RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
-		RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
-		RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
-		RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
-		RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
-		RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
-		RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
-		RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
-		RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
-		RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
-		RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
-		RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
-		RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
-		RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
-		RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
-		RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
-		RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
-		RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
-		RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
-		RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
-		RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
-		RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
-		RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
-		RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
-		RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
-		RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
-		RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
-		RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
-		RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
-		RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
-		RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
-		RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
-		RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
-		RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
-		RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
-		RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
-		RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
-		RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
-		RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
-		RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
-		RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
-		RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
-
-#undef RND		 
-		
-#endif		 
-
-		/* feedback */
-		for (i = 0; i < 8; i++) {
-				md->state[i] = md->state[i] + S[i];
-		}
-		return CRYPT_OK;
-}
-
-#ifdef LTC_CLEAN_STACK
-int SHA256::compress(State * md, unsigned char *buf)
-{
-		int err;
-		err = SHA256::_compress(md, buf);
-		burn_stack(sizeof(boost::uint32_t) * 74);
-		return err;
-}
-#endif
-
-/**
-	 Initialize the hash state
-	 @param md	 The hash state you wish to initialize
-	 @return CRYPT_OK if successful
-*/
-int SHA256::init(State * md)
-{
-		LTC_ARGCHK(md != NULL);
-
-		md->curlen = 0;
-		md->length = 0;
-		md->state[0] = 0x6A09E667UL;
-		md->state[1] = 0xBB67AE85UL;
-		md->state[2] = 0x3C6EF372UL;
-		md->state[3] = 0xA54FF53AUL;
-		md->state[4] = 0x510E527FUL;
-		md->state[5] = 0x9B05688CUL;
-		md->state[6] = 0x1F83D9ABUL;
-		md->state[7] = 0x5BE0CD19UL;
-		return CRYPT_OK;
-}
-
-/**
-	 Process a block of memory though the hash
-	 @param md		 The hash state
-	 @param in		 The data to hash
-	 @param inlen  The length of the data (octets)
-	 @return CRYPT_OK if successful
-*/
-HASH_PROCESS(SHA256::process, SHA256::compress, sha256, 64)
-
-/**
-	 Terminate the hash to get the digest
-	 @param md	The hash state
-	 @param out [out] The destination of the hash (32 bytes)
-	 @return CRYPT_OK if successful
-*/
-int SHA256::done(State * md, unsigned char *out)
-{
-		int i;
-
-		LTC_ARGCHK(md  != NULL);
-		LTC_ARGCHK(out != NULL);
-
-		if (md->curlen >= sizeof(md->buf)) {
-			 return CRYPT_INVALID_ARG;
-		}
-
-
-		/* increase the length of the message */
-		md->length += md->curlen * 8;
-
-		/* append the '1' bit */
-		md->buf[md->curlen++] = (unsigned char)0x80;
-
-		/* if the length is currently above 56 bytes we append zeros
-		 * then compress.  Then we can fall back to padding zeros and length
-		 * encoding like normal.
-		 */
-		if (md->curlen > 56) {
-				while (md->curlen < 64) {
-						md->buf[md->curlen++] = (unsigned char)0;
-				}
-				SHA256::compress(md, md->buf);
-				md->curlen = 0;
-		}
-
-		/* pad upto 56 bytes of zeroes */
-		while (md->curlen < 56) {
-				md->buf[md->curlen++] = (unsigned char)0;
-		}
-
-		/* store length */
-		STORE64H(md->length, md->buf+56);
-		SHA256::compress(md, md->buf);
-
-		/* copy output */
-		for (i = 0; i < 8; i++) {
-				STORE32H(md->state[i], out+(4*i));
-		}
-#ifdef LTC_CLEAN_STACK
-		zeromem(md, sizeof(State));
-#endif
-		return CRYPT_OK;
-}
-
-// End copied code
-
-namespace Swift {
-
-SHA256::SHA256() {
-	init(&state);
-}
-
-SHA256& SHA256::update(const std::vector<unsigned char>& input) {
-	std::vector<unsigned char> inputCopy(input);
-	process(&state, (boost::uint8_t*) vecptr(inputCopy), inputCopy.size());
-	return *this;
-}
-
-std::vector<unsigned char> SHA256::getHash() const {
-	std::vector<unsigned char> digest;
-	digest.resize(256/8);
-	State contextCopy(state);
-	done(&contextCopy, (boost::uint8_t*) vecptr(digest));
-	return digest;
-}
-
-template<typename Container>
-ByteArray SHA256::getHashInternal(const Container& input) {
-	State context;
-	init(&context);
-
-	Container inputCopy(input);
-	process(&context, (boost::uint8_t*) vecptr(inputCopy), inputCopy.size());
-
-	ByteArray digest;
-	digest.resize(256/8);
-	done(&context, (boost::uint8_t*) vecptr(digest));
-
-	return digest;
-}
-
-ByteArray SHA256::getHash(const ByteArray& input) {
-	return getHashInternal(input);
-}
-
-ByteArray SHA256::getHash(const SafeByteArray& input) {
-	return getHashInternal(input);
-}
-
-}
diff --git a/Swiften/StringCodecs/SHA256.h b/Swiften/StringCodecs/SHA256.h
deleted file mode 100644
index fe60f2e..0000000
--- a/Swiften/StringCodecs/SHA256.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <vector>
-#include <boost/cstdint.hpp>
-
-#include <Swiften/Base/API.h>
-#include <Swiften/Base/ByteArray.h>
-#include <Swiften/Base/SafeByteArray.h>
-
-namespace Swift {
-	class SWIFTEN_API SHA256 {
-		public:
-			SHA256();
-
-			SHA256& update(const std::vector<unsigned char>& data);
-			std::vector<unsigned char> getHash() const;
-
-			/**
-			 * Equivalent of:
-			 *	SHA256().update(data),getHash(), but slightly more efficient and
-			 *	convenient.
-			 */
-			static ByteArray getHash(const ByteArray& data);
-			static ByteArray getHash(const SafeByteArray& data);
-
-			ByteArray operator()(const SafeByteArray& data) {
-				return getHash(data);
-			}
-
-			ByteArray operator()(const ByteArray& data) {
-				return getHash(data);
-			}
-
-		private:
-			struct State {
-					boost::uint64_t length;
-					boost::uint32_t state[8], curlen;
-					unsigned char buf[64];
-			};
-
-			static int init(State *md);
-			static int process(State * md, const unsigned char *in, unsigned int inlen);
-			static int compress(State *md, unsigned char *buf);
-			static int done(State * md, unsigned char *out);
-
-			template<typename Container> static	ByteArray getHashInternal(const Container& input);
-
-		private:
-			State state;
-	};
-}
diff --git a/Swiften/StringCodecs/UnitTest/HMACTest.cpp b/Swiften/StringCodecs/UnitTest/HMACTest.cpp
deleted file mode 100644
index 50b1330..0000000
--- a/Swiften/StringCodecs/UnitTest/HMACTest.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <Swiften/Base/ByteArray.h>
-#include <QA/Checker/IO.h>
-
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
-
-#include <Swiften/Base/ByteArray.h>
-#include <Swiften/StringCodecs/HMAC_SHA1.h>
-#include <Swiften/StringCodecs/HMAC_SHA256.h>
-
-using namespace Swift;
-
-class HMACTest : public CppUnit::TestFixture {
-		CPPUNIT_TEST_SUITE(HMACTest);
-		CPPUNIT_TEST(testGetResult);
-		CPPUNIT_TEST(testGetResult_KeyLongerThanBlockSize);
-		CPPUNIT_TEST(testGetResult_RFC4231_1);
-		CPPUNIT_TEST(testGetResult_RFC4231_7);
-		CPPUNIT_TEST_SUITE_END();
-
-	public:
-		void testGetResult() {
-			ByteArray result(HMAC_SHA1()(createSafeByteArray("foo"), createByteArray("foobar")));
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\xa4\xee\xba\x8e\x63\x3d\x77\x88\x69\xf5\x68\xd0\x5a\x1b\x3d\xc7\x2b\xfd\x4\xdd"), result);
-		}
-
-		void testGetResult_KeyLongerThanBlockSize() {
-			ByteArray result(HMAC_SHA1()(createSafeByteArray("---------|---------|---------|---------|---------|----------|---------|"), createByteArray("foobar")));
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\xd6""n""\x8f""P|1""\xd3"",""\x6"" ""\xb9\xe3""gg""\x8e\xcf"" ]+""\xa"), result);
-		}
-
-		void testGetResult_RFC4231_1() {
-			ByteArray result(HMAC_SHA256()(createSafeByteArray("\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20), createByteArray("Hi There")));
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7", 32), result);
-		}
-
-		void testGetResult_RFC4231_7() {
-			ByteArray result(HMAC_SHA256()(createSafeByteArray("\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131), createByteArray("This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.")));
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2", 32), result);
-		}
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION(HMACTest);
diff --git a/Swiften/StringCodecs/UnitTest/MD5Test.cpp b/Swiften/StringCodecs/UnitTest/MD5Test.cpp
deleted file mode 100644
index c62c46a..0000000
--- a/Swiften/StringCodecs/UnitTest/MD5Test.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <Swiften/Base/ByteArray.h>
-#include <QA/Checker/IO.h>
-
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
-
-#include <Swiften/StringCodecs/MD5.h>
-#include <Swiften/Base/ByteArray.h>
-
-using namespace Swift;
-
-class MD5Test : public CppUnit::TestFixture {
-		CPPUNIT_TEST_SUITE(MD5Test);
-		CPPUNIT_TEST(testGetHash_Empty);
-		CPPUNIT_TEST(testGetHash_Alphabet);
-		CPPUNIT_TEST(testIncrementalTest);
-		CPPUNIT_TEST_SUITE_END();
-
-	public:
-		void testGetHash_Empty() {
-			ByteArray result(MD5::getHash(createByteArray("")));
-
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e", 16), result);
-		}
-
-		void testGetHash_Alphabet() {
-			ByteArray result(MD5::getHash(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")));
-
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f", 16), result);
-		}
-
-		void testIncrementalTest() {
-			MD5 testling;
-			testling.update(createByteArray("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
-			testling.update(createByteArray("abcdefghijklmnopqrstuvwxyz0123456789"));
-
-			ByteArray result = testling.getHash();
-
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f", 16), result);
-		}
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION(MD5Test);
diff --git a/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp b/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp
index 608ca62..1172679 100644
--- a/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp
+++ b/Swiften/StringCodecs/UnitTest/PBKDF2Test.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -12,7 +12,8 @@
 
 #include <Swiften/Base/ByteArray.h>
 #include <Swiften/StringCodecs/PBKDF2.h>
-#include <Swiften/StringCodecs/HMAC_SHA1.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -24,23 +25,30 @@ class PBKDF2Test : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
+		void setUp() {
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
+		}
+
 		void testGetResult_I1() {
-			ByteArray result(PBKDF2::encode<HMAC_SHA1 >(createSafeByteArray("password"), createByteArray("salt"), 1));
+			ByteArray result(PBKDF2::encode(createSafeByteArray("password"), createByteArray("salt"), 1, crypto.get()));
 
 			CPPUNIT_ASSERT_EQUAL(createByteArray("\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6"), result);
 		}
 
 		void testGetResult_I2() {
-			ByteArray result(PBKDF2::encode<HMAC_SHA1 >(createSafeByteArray("password"), createByteArray("salt"), 2));
+			ByteArray result(PBKDF2::encode(createSafeByteArray("password"), createByteArray("salt"), 2, crypto.get()));
 
 			CPPUNIT_ASSERT_EQUAL(createByteArray("\xea\x6c\x1\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57"), result);
 		}
 
 		void testGetResult_I4096() {
-			ByteArray result(PBKDF2::encode<HMAC_SHA1 >(createSafeByteArray("password"), createByteArray("salt"), 4096));
+			ByteArray result(PBKDF2::encode(createSafeByteArray("password"), createByteArray("salt"), 4096, crypto.get()));
 
 			CPPUNIT_ASSERT_EQUAL(createByteArray("\x4b\x00\x79\x1\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20), result);
 		}
+	
+	private:
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(PBKDF2Test);
diff --git a/Swiften/StringCodecs/UnitTest/SHA1Test.cpp b/Swiften/StringCodecs/UnitTest/SHA1Test.cpp
deleted file mode 100644
index cb1a6f4..0000000
--- a/Swiften/StringCodecs/UnitTest/SHA1Test.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <Swiften/Base/ByteArray.h>
-#include <QA/Checker/IO.h>
-
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
-
-#include <Swiften/StringCodecs/SHA1.h>
-
-using namespace Swift;
-
-class SHA1Test : public CppUnit::TestFixture {
-		CPPUNIT_TEST_SUITE(SHA1Test);
-		CPPUNIT_TEST(testGetHash);
-		CPPUNIT_TEST(testGetHash_TwoUpdates);
-		//CPPUNIT_TEST(testGetHash_TwoGetHash);
-		CPPUNIT_TEST(testGetHash_NoData);
-		//CPPUNIT_TEST(testGetHash_InterleavedUpdate);
-		CPPUNIT_TEST(testGetHashStatic);
-		CPPUNIT_TEST(testGetHashStatic_Twice);
-		CPPUNIT_TEST(testGetHashStatic_NoData);
-		CPPUNIT_TEST_SUITE_END();
-
-	public:
-		void testGetHash() {
-			SHA1 sha;
-			sha.update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
-
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha.getHash());
-		}
-
-		void testGetHash_TwoUpdates() {
-			SHA1 sha;
-			sha.update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<"));
-			sha.update(createByteArray("http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
-
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha.getHash());
-		}
-
-		void testGetHash_TwoGetHash() {
-			SHA1 sha;
-			sha.update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
-
-			sha.getHash();
-
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha.getHash());
-		}
-
-		void testGetHash_InterleavedUpdate() {
-			SHA1 sha;
-
-			sha.update(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<"));
-			sha.getHash();
-			sha.update(createByteArray("http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
-
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), sha.getHash());
-		}
-
-
-		void testGetHash_NoData() {
-			SHA1 sha;
-			sha.update(std::vector<unsigned char>());
-
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09"), sha.getHash());
-		}
-
-		void testGetHashStatic() {
-			ByteArray result(SHA1::getHash(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<")));
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), result);
-		}
-
-
-		void testGetHashStatic_Twice() {
-			ByteArray input(createByteArray("client/pc//Exodus 0.9.1<http://jabber.org/protocol/caps<http://jabber.org/protocol/disco#info<http://jabber.org/protocol/disco#items<http://jabber.org/protocol/muc<"));
-			SHA1::getHash(input);
-			ByteArray result(SHA1::getHash(input));
-
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\x42\x06\xb2\x3c\xa6\xb0\xa6\x43\xd2\x0d\x89\xb0\x4f\xf5\x8c\xf7\x8b\x80\x96\xed"), result);
-		}
-
-		void testGetHashStatic_NoData() {
-			ByteArray result(SHA1::getHash(ByteArray()));
-
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09"), result);
-		}
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION(SHA1Test);
diff --git a/Swiften/StringCodecs/UnitTest/SHA256Test.cpp b/Swiften/StringCodecs/UnitTest/SHA256Test.cpp
deleted file mode 100644
index 5bcdd11..0000000
--- a/Swiften/StringCodecs/UnitTest/SHA256Test.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2010 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#include <Swiften/Base/ByteArray.h>
-#include <QA/Checker/IO.h>
-
-#include <cppunit/extensions/HelperMacros.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
-
-#include <Swiften/StringCodecs/SHA256.h>
-
-using namespace Swift;
-
-class SHA256Test : public CppUnit::TestFixture {
-		CPPUNIT_TEST_SUITE(SHA256Test);
-		CPPUNIT_TEST(testGetHashStatic_Empty);
-		CPPUNIT_TEST(testGetHashStatic_Small);
-		CPPUNIT_TEST(testGetHashStatic_Large);
-		CPPUNIT_TEST_SUITE_END();
-
-	public:
-		void testGetHashStatic_Empty() {
-			ByteArray result(SHA256::getHash(createByteArray("")));
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\xe3\xb0\xc4" "B" "\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99" "o" "\xb9" "$'" "\xae" "A" "\xe4" "d" "\x9b\x93" "L" "\xa4\x95\x99\x1b" "xR" "\xb8" "U", 32), result);
-		}
-
-		void testGetHashStatic_Small() {
-			ByteArray result(SHA256::getHash(createByteArray("abc")));
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad", 32), result);
-		}
-
-		void testGetHashStatic_Large() {
-			ByteArray result(SHA256::getHash(createByteArray("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")));
-			CPPUNIT_ASSERT_EQUAL(createByteArray("\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1", 32), result);
-		}
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION(SHA256Test);
diff --git a/Swiften/TLS/Certificate.cpp b/Swiften/TLS/Certificate.cpp
index a796463..ec268c8 100644
--- a/Swiften/TLS/Certificate.cpp
+++ b/Swiften/TLS/Certificate.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -8,7 +8,7 @@
 
 #include <sstream>
 
-#include <Swiften/StringCodecs/SHA1.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 #include <Swiften/StringCodecs/Hexify.h>
 
 namespace Swift {
@@ -19,8 +19,8 @@ const char* Certificate::ID_ON_DNSSRV_OID = "1.3.6.1.5.5.7.8.7";
 Certificate::~Certificate() {
 }
 
-std::string Certificate::getSHA1Fingerprint() const {
-	ByteArray hash = SHA1::getHash(toDER());
+std::string Certificate::getSHA1Fingerprint(Certificate::ref certificate, CryptoProvider* crypto) {
+	ByteArray hash = crypto->getSHA1Hash(certificate->toDER());
 	std::ostringstream s;
 	for (size_t i = 0; i < hash.size(); ++i) {
 		if (i > 0) {
diff --git a/Swiften/TLS/Certificate.h b/Swiften/TLS/Certificate.h
index 9aec86c..f558c12 100644
--- a/Swiften/TLS/Certificate.h
+++ b/Swiften/TLS/Certificate.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -13,6 +13,8 @@
 #include <Swiften/Base/ByteArray.h>
 
 namespace Swift {
+	class CryptoProvider;
+
 	class SWIFTEN_API Certificate {
 		public:
 			typedef boost::shared_ptr<Certificate> ref;
@@ -32,7 +34,7 @@ namespace Swift {
 
 			virtual ByteArray toDER() const = 0;
 
-			virtual std::string getSHA1Fingerprint() const;
+			static std::string getSHA1Fingerprint(Certificate::ref, CryptoProvider* crypto);
 
 		protected:
 			static const char* ID_ON_XMPPADDR_OID;
diff --git a/Swiften/TLS/UnitTest/CertificateTest.cpp b/Swiften/TLS/UnitTest/CertificateTest.cpp
index 5df5639..3352118 100644
--- a/Swiften/TLS/UnitTest/CertificateTest.cpp
+++ b/Swiften/TLS/UnitTest/CertificateTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -12,6 +12,8 @@
 
 #include <Swiften/TLS/Certificate.h>
 #include <Swiften/TLS/SimpleCertificate.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -25,7 +27,7 @@ class CertificateTest : public CppUnit::TestFixture {
 			SimpleCertificate::ref testling = boost::make_shared<SimpleCertificate>();
 			testling->setDER(createByteArray("abcdefg"));
 
-			CPPUNIT_ASSERT_EQUAL(std::string("2f:b5:e1:34:19:fc:89:24:68:65:e7:a3:24:f4:76:ec:62:4e:87:40"), testling->getSHA1Fingerprint());
+			CPPUNIT_ASSERT_EQUAL(std::string("2f:b5:e1:34:19:fc:89:24:68:65:e7:a3:24:f4:76:ec:62:4e:87:40"), Certificate::getSHA1Fingerprint(testling, boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()).get()));
 		}
 };
 
diff --git a/Swiften/VCards/UnitTest/VCardManagerTest.cpp b/Swiften/VCards/UnitTest/VCardManagerTest.cpp
index eecec7b..9f1c8bb 100644
--- a/Swiften/VCards/UnitTest/VCardManagerTest.cpp
+++ b/Swiften/VCards/UnitTest/VCardManagerTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -16,6 +16,8 @@
 #include <Swiften/VCards/VCardMemoryStorage.h>
 #include <Swiften/Queries/IQRouter.h>
 #include <Swiften/Client/DummyStanzaChannel.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
 
 using namespace Swift;
 
@@ -36,9 +38,10 @@ class VCardManagerTest : public CppUnit::TestFixture {
 	public:
 		void setUp() {
 			ownJID = JID("baz@fum.com/dum");
+			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
 			stanzaChannel = new DummyStanzaChannel();
 			iqRouter = new IQRouter(stanzaChannel);
-			vcardStorage = new VCardMemoryStorage();
+			vcardStorage = new VCardMemoryStorage(crypto.get());
 		}
 
 		void tearDown() {
@@ -201,6 +204,7 @@ class VCardManagerTest : public CppUnit::TestFixture {
 		VCardMemoryStorage* vcardStorage;
 		std::vector< std::pair<JID, VCard::ref> > changes;
 		std::vector<VCard::ref> ownChanges;
+		boost::shared_ptr<CryptoProvider> crypto;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(VCardManagerTest);
diff --git a/Swiften/VCards/VCardMemoryStorage.h b/Swiften/VCards/VCardMemoryStorage.h
index ade9c89..86ae1b2 100644
--- a/Swiften/VCards/VCardMemoryStorage.h
+++ b/Swiften/VCards/VCardMemoryStorage.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -15,7 +15,7 @@
 namespace Swift {
 	class VCardMemoryStorage : public VCardStorage {
 		public:
-			VCardMemoryStorage() {}
+			VCardMemoryStorage(CryptoProvider* crypto) : VCardStorage(crypto) {}
 
 			virtual VCard::ref getVCard(const JID& jid) const {
 				VCardMap::const_iterator i = vcards.find(jid);
diff --git a/Swiften/VCards/VCardStorage.cpp b/Swiften/VCards/VCardStorage.cpp
index 900f1e5..fefea83 100644
--- a/Swiften/VCards/VCardStorage.cpp
+++ b/Swiften/VCards/VCardStorage.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -7,17 +7,20 @@
 #include <Swiften/VCards/VCardStorage.h>
 
 #include <Swiften/StringCodecs/Hexify.h>
-#include <Swiften/StringCodecs/SHA1.h>
+#include <Swiften/Crypto/CryptoProvider.h>
 
 namespace Swift {
 
+VCardStorage::VCardStorage(CryptoProvider* crypto) : crypto(crypto) {
+}
+
 VCardStorage::~VCardStorage() {
 }
 
 std::string VCardStorage::getPhotoHash(const JID& jid) const {
 	VCard::ref vCard = getVCard(jid);
 	if (vCard && !vCard->getPhoto().empty()) {
-		return Hexify::hexify(SHA1::getHash(vCard->getPhoto()));
+		return Hexify::hexify(crypto->getSHA1Hash(vCard->getPhoto()));
 	}
 	else {
 		return "";
diff --git a/Swiften/VCards/VCardStorage.h b/Swiften/VCards/VCardStorage.h
index 5fba915..924204c 100644
--- a/Swiften/VCards/VCardStorage.h
+++ b/Swiften/VCards/VCardStorage.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -14,14 +14,19 @@
 
 namespace Swift {
 	class JID;
+	class CryptoProvider;
 
 	class SWIFTEN_API VCardStorage {
 		public:
+			VCardStorage(CryptoProvider*);
 			virtual ~VCardStorage();
 
 			virtual VCard::ref getVCard(const JID& jid) const = 0;
 			virtual void setVCard(const JID&, VCard::ref) = 0;
 
 			virtual std::string getPhotoHash(const JID&) const;
+
+		private:
+			CryptoProvider* crypto;
 	};
 }
-- 
cgit v0.10.2-6-g49f6