diff --git a/Foundation/Foundation_CE_vs90.vcproj b/Foundation/Foundation_CE_vs90.vcproj
index af3ea3de6..a412bccf0 100644
--- a/Foundation/Foundation_CE_vs90.vcproj
+++ b/Foundation/Foundation_CE_vs90.vcproj
@@ -1885,6 +1885,10 @@
RelativePath=".\include\Poco\MD5Engine.h"
>
+
+
diff --git a/Foundation/Foundation_vs71.vcproj b/Foundation/Foundation_vs71.vcproj
index 910ee8ce3..9ef2e8327 100644
--- a/Foundation/Foundation_vs71.vcproj
+++ b/Foundation/Foundation_vs71.vcproj
@@ -1922,6 +1922,9 @@
+
+
diff --git a/Foundation/Foundation_vs80.vcproj b/Foundation/Foundation_vs80.vcproj
index a7ddc0186..de1b2c4fe 100644
--- a/Foundation/Foundation_vs80.vcproj
+++ b/Foundation/Foundation_vs80.vcproj
@@ -2463,6 +2463,10 @@
RelativePath=".\include\Poco\MD5Engine.h"
>
+
+
diff --git a/Foundation/Foundation_vs90.vcproj b/Foundation/Foundation_vs90.vcproj
index f549151e8..24c2b6280 100644
--- a/Foundation/Foundation_vs90.vcproj
+++ b/Foundation/Foundation_vs90.vcproj
@@ -2456,6 +2456,10 @@
RelativePath=".\include\Poco\MD5Engine.h"
>
+
+
diff --git a/Foundation/Foundation_x64_vs90.vcproj b/Foundation/Foundation_x64_vs90.vcproj
index f7b853c32..4fab86836 100644
--- a/Foundation/Foundation_x64_vs90.vcproj
+++ b/Foundation/Foundation_x64_vs90.vcproj
@@ -2458,6 +2458,10 @@
RelativePath=".\include\Poco\MD5Engine.h"
>
+
+
diff --git a/Foundation/include/Poco/PBKDF2Engine.h b/Foundation/include/Poco/PBKDF2Engine.h
new file mode 100644
index 000000000..2a665fd4b
--- /dev/null
+++ b/Foundation/include/Poco/PBKDF2Engine.h
@@ -0,0 +1,171 @@
+//
+// PBKDF2Engine.h
+//
+// $Id: //poco/1.4/Foundation/include/Poco/PBKDF2Engine.h#1 $
+//
+// Library: Foundation
+// Package: Crypt
+// Module: PBKDF2Engine
+//
+// Definition of the PBKDF2Engine class.
+//
+// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Foundation_PBKDF2Engine_INCLUDED
+#define Foundation_PBKDF2Engine_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DigestEngine.h"
+#include "Poco/ByteOrder.h"
+#include
+
+
+namespace Poco {
+
+
+template
+class PBKDF2Engine: public DigestEngine
+ /// This class implementes the Password-Based Key Derivation Function 2,
+ /// as specified in RFC 2898. The underlying DigestEngine (HMACEngine, etc.),
+ /// which must accept the passphrase as constructor argument (std::string),
+ /// must be given as template argument.
+ ///
+ /// PBKDF2 (Password-Based Key Derivation Function 2) is a key derivation function
+ /// that is part of RSA Laboratories' Public-Key Cryptography Standards (PKCS) series,
+ /// specifically PKCS #5 v2.0, also published as Internet Engineering Task Force's
+ /// RFC 2898. It replaces an earlier standard, PBKDF1, which could only produce
+ /// derived keys up to 160 bits long.
+ ///
+ /// PBKDF2 applies a pseudorandom function, such as a cryptographic hash, cipher, or
+ /// HMAC to the input password or passphrase along with a salt value and repeats the
+ /// process many times to produce a derived key, which can then be used as a
+ /// cryptographic key in subsequent operations. The added computational work makes
+ /// password cracking much more difficult, and is known as key stretching.
+ /// When the standard was written in 2000, the recommended minimum number of
+ /// iterations was 1000, but the parameter is intended to be increased over time as
+ /// CPU speeds increase. Having a salt added to the password reduces the ability to
+ /// use precomputed hashes (rainbow tables) for attacks, and means that multiple
+ /// passwords have to be tested individually, not all at once. The standard
+ /// recommends a salt length of at least 64 bits. [Wikipedia]
+ ///
+ /// The PBKDF2 algorithm is implemented as a DigestEngine. The passphrase is specified
+ /// by calling update().
+ ///
+ /// Example (WPA2):
+ /// PBKDF2Engine > pbkdf2(ssid, 4096, 256);
+ /// pbkdf2.update(passphrase);
+ /// DigestEngine::Digest d = pbkdf2.digest();
+{
+public:
+ enum
+ {
+ PRF_DIGEST_SIZE = PRF::DIGEST_SIZE
+ };
+
+ PBKDF2Engine(const std::string& salt, unsigned c = 4096, Poco::UInt32 dkLen = PRF_DIGEST_SIZE):
+ _s(salt),
+ _c(c),
+ _dkLen(dkLen)
+ {
+ _result.reserve(_dkLen + PRF_DIGEST_SIZE);
+ }
+
+ ~PBKDF2Engine()
+ {
+ }
+
+ std::size_t digestLength() const
+ {
+ return _dkLen;
+ }
+
+ void reset()
+ {
+ _p.clear();
+ _result.clear();
+ }
+
+ const DigestEngine::Digest& digest()
+ {
+ Poco::UInt32 i = 1;
+ while (_result.size() < _dkLen)
+ {
+ f(i++);
+ }
+ _result.resize(_dkLen);
+ return _result;
+ }
+
+protected:
+ void updateImpl(const void* data, std::size_t length)
+ {
+ _p.append(reinterpret_cast(data), length);
+ }
+
+ void f(Poco::UInt32 i)
+ {
+ PRF prf(_p);
+ prf.update(_s);
+ Poco::UInt32 iBE = Poco::ByteOrder::toBigEndian(i);
+ prf.update(&iBE, sizeof(iBE));
+ Poco::DigestEngine::Digest up = prf.digest();
+ Poco::DigestEngine::Digest ux = up;
+ poco_assert_dbg(ux.size() == PRF_DIGEST_SIZE);
+ for (unsigned k = 1; k < _c; k++)
+ {
+ prf.reset();
+ prf.update(&up[0], up.size());
+ Poco::DigestEngine::Digest u = prf.digest();
+ poco_assert_dbg(u.size() == PRF_DIGEST_SIZE);
+ for (int ui = 0; ui < PRF_DIGEST_SIZE; ui++)
+ {
+ ux[ui] ^= u[ui];
+ }
+ std::swap(up, u);
+ }
+ _result.insert(_result.end(), ux.begin(), ux.end());
+ }
+
+private:
+ PBKDF2Engine();
+ PBKDF2Engine(const PBKDF2Engine&);
+ PBKDF2Engine& operator = (const PBKDF2Engine&);
+
+ std::string _p;
+ std::string _s;
+ unsigned _c;
+ Poco::UInt32 _dkLen;
+ DigestEngine::Digest _result;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PBKDF2Engine_INCLUDED
diff --git a/Foundation/testsuite/Makefile-Driver b/Foundation/testsuite/Makefile-Driver
index 8e20d10b8..f6e6ed18b 100644
--- a/Foundation/testsuite/Makefile-Driver
+++ b/Foundation/testsuite/Makefile-Driver
@@ -22,7 +22,7 @@ objects = ActiveMethodTest ActivityTest ActiveDispatcherTest \
NDCTest NotificationCenterTest NotificationQueueTest \
PriorityNotificationQueueTest TimedNotificationQueueTest \
NotificationsTestSuite NullStreamTest NumberFormatterTest \
- NumberParserTest PathTest PatternFormatterTest RWLockTest \
+ NumberParserTest PathTest PatternFormatterTest PBKDF2EngineTest RWLockTest \
RandomStreamTest RandomTest RegularExpressionTest SHA1EngineTest \
SemaphoreTest ConditionTest SharedLibraryTest SharedLibraryTestSuite \
SimpleFileChannelTest StopwatchTest \
diff --git a/Foundation/testsuite/TestSuite_CE_vs90.vcproj b/Foundation/testsuite/TestSuite_CE_vs90.vcproj
index 4d73e19c6..9574a7552 100644
--- a/Foundation/testsuite/TestSuite_CE_vs90.vcproj
+++ b/Foundation/testsuite/TestSuite_CE_vs90.vcproj
@@ -942,6 +942,10 @@
RelativePath=".\src\MD5EngineTest.cpp"
>
+
+
@@ -978,6 +982,10 @@
RelativePath=".\src\MD5EngineTest.h"
>
+
+
diff --git a/Foundation/testsuite/TestSuite_vs71.vcproj b/Foundation/testsuite/TestSuite_vs71.vcproj
index 75f3d325b..dddcc36db 100644
--- a/Foundation/testsuite/TestSuite_vs71.vcproj
+++ b/Foundation/testsuite/TestSuite_vs71.vcproj
@@ -670,6 +670,9 @@
+
+
@@ -698,6 +701,9 @@
+
+
diff --git a/Foundation/testsuite/TestSuite_vs80.vcproj b/Foundation/testsuite/TestSuite_vs80.vcproj
index 636184cae..f530a6376 100644
--- a/Foundation/testsuite/TestSuite_vs80.vcproj
+++ b/Foundation/testsuite/TestSuite_vs80.vcproj
@@ -911,6 +911,10 @@
RelativePath=".\src\MD5EngineTest.cpp"
>
+
+
@@ -947,6 +951,10 @@
RelativePath=".\src\MD5EngineTest.h"
>
+
+
diff --git a/Foundation/testsuite/TestSuite_vs90.vcproj b/Foundation/testsuite/TestSuite_vs90.vcproj
index 141c45e6b..5af19b129 100644
--- a/Foundation/testsuite/TestSuite_vs90.vcproj
+++ b/Foundation/testsuite/TestSuite_vs90.vcproj
@@ -897,6 +897,10 @@
RelativePath=".\src\MD5EngineTest.cpp"
>
+
+
@@ -933,6 +937,10 @@
RelativePath=".\src\MD5EngineTest.h"
>
+
+
diff --git a/Foundation/testsuite/TestSuite_x64_vs90.vcproj b/Foundation/testsuite/TestSuite_x64_vs90.vcproj
index 95aede499..b3732cbba 100644
--- a/Foundation/testsuite/TestSuite_x64_vs90.vcproj
+++ b/Foundation/testsuite/TestSuite_x64_vs90.vcproj
@@ -891,6 +891,10 @@
RelativePath=".\src\MD5EngineTest.cpp"
>
+
+
@@ -927,6 +931,10 @@
RelativePath=".\src\MD5EngineTest.h"
>
+
+
diff --git a/Foundation/testsuite/src/CryptTestSuite.cpp b/Foundation/testsuite/src/CryptTestSuite.cpp
index ec602e9ea..2ac79bb46 100644
--- a/Foundation/testsuite/src/CryptTestSuite.cpp
+++ b/Foundation/testsuite/src/CryptTestSuite.cpp
@@ -35,6 +35,7 @@
#include "MD5EngineTest.h"
#include "SHA1EngineTest.h"
#include "HMACEngineTest.h"
+#include "PBKDF2EngineTest.h"
#include "DigestStreamTest.h"
#include "RandomTest.h"
#include "RandomStreamTest.h"
@@ -48,6 +49,7 @@ CppUnit::Test* CryptTestSuite::suite()
pSuite->addTest(MD5EngineTest::suite());
pSuite->addTest(SHA1EngineTest::suite());
pSuite->addTest(HMACEngineTest::suite());
+ pSuite->addTest(PBKDF2EngineTest::suite());
pSuite->addTest(DigestStreamTest::suite());
pSuite->addTest(RandomTest::suite());
pSuite->addTest(RandomStreamTest::suite());
diff --git a/Foundation/testsuite/src/PBKDF2EngineTest.cpp b/Foundation/testsuite/src/PBKDF2EngineTest.cpp
new file mode 100644
index 000000000..0a225c32c
--- /dev/null
+++ b/Foundation/testsuite/src/PBKDF2EngineTest.cpp
@@ -0,0 +1,157 @@
+//
+// PBKDF2EngineTest.cpp
+//
+// $Id: //poco/1.4/Foundation/testsuite/src/PBKDF2EngineTest.cpp#1 $
+//
+// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "PBKDF2EngineTest.h"
+#include "CppUnit/TestCaller.h"
+#include "CppUnit/TestSuite.h"
+#include "Poco/PBKDF2Engine.h"
+#include "Poco/HMACEngine.h"
+#include "Poco/SHA1Engine.h"
+
+
+using Poco::PBKDF2Engine;
+using Poco::HMACEngine;
+using Poco::SHA1Engine;
+using Poco::DigestEngine;
+
+
+PBKDF2EngineTest::PBKDF2EngineTest(const std::string& name): CppUnit::TestCase(name)
+{
+}
+
+
+PBKDF2EngineTest::~PBKDF2EngineTest()
+{
+}
+
+
+void PBKDF2EngineTest::testPBKDF2a()
+{
+ // test vector 1 from RFC 6070
+
+ std::string p("password");
+ std::string s("salt");
+ PBKDF2Engine > pbkdf2(s, 1, 20);
+ pbkdf2.update(p);
+ std::string dk = DigestEngine::digestToHex(pbkdf2.digest());
+ assert (dk == "0c60c80f961f0e71f3a9b524af6012062fe037a6");
+}
+
+
+void PBKDF2EngineTest::testPBKDF2b()
+{
+ // test vector 2 from RFC 6070
+
+ std::string p("password");
+ std::string s("salt");
+ PBKDF2Engine > pbkdf2(s, 2, 20);
+ pbkdf2.update(p);
+ std::string dk = DigestEngine::digestToHex(pbkdf2.digest());
+ assert (dk == "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957");
+}
+
+
+void PBKDF2EngineTest::testPBKDF2c()
+{
+ // test vector 3 from RFC 6070
+
+ std::string p("password");
+ std::string s("salt");
+ PBKDF2Engine > pbkdf2(s, 4096, 20);
+ pbkdf2.update(p);
+ std::string dk = DigestEngine::digestToHex(pbkdf2.digest());
+ assert (dk == "4b007901b765489abead49d926f721d065a429c1");
+}
+
+
+void PBKDF2EngineTest::testPBKDF2d()
+{
+ // test vector 4 from RFC 6070
+
+ std::string p("password");
+ std::string s("salt");
+ PBKDF2Engine > pbkdf2(s, 16777216, 20);
+ pbkdf2.update(p);
+ std::string dk = DigestEngine::digestToHex(pbkdf2.digest());
+ assert (dk == "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984");
+}
+
+
+void PBKDF2EngineTest::testPBKDF2e()
+{
+ // test vector 5 from RFC 6070
+
+ std::string p("passwordPASSWORDpassword");
+ std::string s("saltSALTsaltSALTsaltSALTsaltSALTsalt");
+ PBKDF2Engine > pbkdf2(s, 4096, 25);
+ pbkdf2.update(p);
+ std::string dk = DigestEngine::digestToHex(pbkdf2.digest());
+ assert (dk == "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038");
+}
+
+
+void PBKDF2EngineTest::testPBKDF2f()
+{
+ // test vector 6 from RFC 6070
+
+ std::string p("pass\0word", 9);
+ std::string s("sa\0lt", 5);
+ PBKDF2Engine > pbkdf2(s, 4096, 16);
+ pbkdf2.update(p);
+ std::string dk = DigestEngine::digestToHex(pbkdf2.digest());
+ assert (dk == "56fa6aa75548099dcc37d7f03425e0c3");
+}
+
+
+void PBKDF2EngineTest::setUp()
+{
+}
+
+
+void PBKDF2EngineTest::tearDown()
+{
+}
+
+
+CppUnit::Test* PBKDF2EngineTest::suite()
+{
+ CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("PBKDF2EngineTest");
+
+ CppUnit_addTest(pSuite, PBKDF2EngineTest, testPBKDF2a);
+ CppUnit_addTest(pSuite, PBKDF2EngineTest, testPBKDF2b);
+ CppUnit_addTest(pSuite, PBKDF2EngineTest, testPBKDF2c);
+ CppUnit_addTest(pSuite, PBKDF2EngineTest, testPBKDF2d);
+ CppUnit_addTest(pSuite, PBKDF2EngineTest, testPBKDF2e);
+ CppUnit_addTest(pSuite, PBKDF2EngineTest, testPBKDF2f);
+
+ return pSuite;
+}
diff --git a/Foundation/testsuite/src/PBKDF2EngineTest.h b/Foundation/testsuite/src/PBKDF2EngineTest.h
new file mode 100644
index 000000000..13be75182
--- /dev/null
+++ b/Foundation/testsuite/src/PBKDF2EngineTest.h
@@ -0,0 +1,65 @@
+//
+// PBKDF2EngineTest.h
+//
+// $Id: //poco/1.4/Foundation/testsuite/src/PBKDF2EngineTest.h#1 $
+//
+// Definition of the PBKDF2EngineTest class.
+//
+// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef PBKDF2EngineTest_INCLUDED
+#define PBKDF2EngineTest_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "CppUnit/TestCase.h"
+
+
+class PBKDF2EngineTest: public CppUnit::TestCase
+{
+public:
+ PBKDF2EngineTest(const std::string& name);
+ ~PBKDF2EngineTest();
+
+ void testPBKDF2a();
+ void testPBKDF2b();
+ void testPBKDF2c();
+ void testPBKDF2d();
+ void testPBKDF2e();
+ void testPBKDF2f();
+
+ void setUp();
+ void tearDown();
+
+ static CppUnit::Test* suite();
+
+private:
+};
+
+
+#endif // PBKDF2EngineTest_INCLUDED