added Poco::PBKDF2Engine

This commit is contained in:
Guenter Obiltschnig
2014-03-02 22:55:21 +01:00
parent e49252e122
commit 7175be3f52
15 changed files with 453 additions and 1 deletions

View File

@@ -1885,6 +1885,10 @@
RelativePath=".\include\Poco\MD5Engine.h" RelativePath=".\include\Poco\MD5Engine.h"
> >
</File> </File>
<File
RelativePath=".\include\Poco\PBKDF2Engine.h"
>
</File>
<File <File
RelativePath=".\include\Poco\Random.h" RelativePath=".\include\Poco\Random.h"
> >

View File

@@ -1922,6 +1922,9 @@
<File <File
RelativePath=".\include\Poco\MD5Engine.h"> RelativePath=".\include\Poco\MD5Engine.h">
</File> </File>
<File
RelativePath=".\include\Poco\PBKDF2Engine.h">
</File>
<File <File
RelativePath=".\include\Poco\Random.h"> RelativePath=".\include\Poco\Random.h">
</File> </File>

View File

@@ -2463,6 +2463,10 @@
RelativePath=".\include\Poco\MD5Engine.h" RelativePath=".\include\Poco\MD5Engine.h"
> >
</File> </File>
<File
RelativePath=".\include\Poco\PBKDF2Engine.h"
>
</File>
<File <File
RelativePath=".\include\Poco\Random.h" RelativePath=".\include\Poco\Random.h"
> >

View File

@@ -2456,6 +2456,10 @@
RelativePath=".\include\Poco\MD5Engine.h" RelativePath=".\include\Poco\MD5Engine.h"
> >
</File> </File>
<File
RelativePath=".\include\Poco\PBKDF2Engine.h"
>
</File>
<File <File
RelativePath=".\include\Poco\Random.h" RelativePath=".\include\Poco\Random.h"
> >

View File

@@ -2458,6 +2458,10 @@
RelativePath=".\include\Poco\MD5Engine.h" RelativePath=".\include\Poco\MD5Engine.h"
> >
</File> </File>
<File
RelativePath=".\include\Poco\PBKDF2Engine.h"
>
</File>
<File <File
RelativePath=".\include\Poco\Random.h" RelativePath=".\include\Poco\Random.h"
> >

View File

@@ -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 <algorithm>
namespace Poco {
template <class PRF>
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<HMACEngine<SHA1Engine> > 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<const char*>(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

View File

@@ -22,7 +22,7 @@ objects = ActiveMethodTest ActivityTest ActiveDispatcherTest \
NDCTest NotificationCenterTest NotificationQueueTest \ NDCTest NotificationCenterTest NotificationQueueTest \
PriorityNotificationQueueTest TimedNotificationQueueTest \ PriorityNotificationQueueTest TimedNotificationQueueTest \
NotificationsTestSuite NullStreamTest NumberFormatterTest \ NotificationsTestSuite NullStreamTest NumberFormatterTest \
NumberParserTest PathTest PatternFormatterTest RWLockTest \ NumberParserTest PathTest PatternFormatterTest PBKDF2EngineTest RWLockTest \
RandomStreamTest RandomTest RegularExpressionTest SHA1EngineTest \ RandomStreamTest RandomTest RegularExpressionTest SHA1EngineTest \
SemaphoreTest ConditionTest SharedLibraryTest SharedLibraryTestSuite \ SemaphoreTest ConditionTest SharedLibraryTest SharedLibraryTestSuite \
SimpleFileChannelTest StopwatchTest \ SimpleFileChannelTest StopwatchTest \

View File

@@ -942,6 +942,10 @@
RelativePath=".\src\MD5EngineTest.cpp" RelativePath=".\src\MD5EngineTest.cpp"
> >
</File> </File>
<File
RelativePath=".\src\PBKDF2EngineTest.cpp"
>
</File>
<File <File
RelativePath=".\src\RandomStreamTest.cpp" RelativePath=".\src\RandomStreamTest.cpp"
> >
@@ -978,6 +982,10 @@
RelativePath=".\src\MD5EngineTest.h" RelativePath=".\src\MD5EngineTest.h"
> >
</File> </File>
<File
RelativePath=".\src\PBKDF2EngineTest.h"
>
</File>
<File <File
RelativePath=".\src\RandomStreamTest.h" RelativePath=".\src\RandomStreamTest.h"
> >

View File

@@ -670,6 +670,9 @@
<File <File
RelativePath=".\src\MD5EngineTest.cpp"> RelativePath=".\src\MD5EngineTest.cpp">
</File> </File>
<File
RelativePath=".\src\PBKDF2EngineTest.cpp">
</File>
<File <File
RelativePath=".\src\RandomStreamTest.cpp"> RelativePath=".\src\RandomStreamTest.cpp">
</File> </File>
@@ -698,6 +701,9 @@
<File <File
RelativePath=".\src\MD5EngineTest.h"> RelativePath=".\src\MD5EngineTest.h">
</File> </File>
<File
RelativePath=".\src\PBKDF2EngineTest.h">
</File>
<File <File
RelativePath=".\src\RandomStreamTest.h"> RelativePath=".\src\RandomStreamTest.h">
</File> </File>

View File

@@ -911,6 +911,10 @@
RelativePath=".\src\MD5EngineTest.cpp" RelativePath=".\src\MD5EngineTest.cpp"
> >
</File> </File>
<File
RelativePath=".\src\PBKDF2EngineTest.cpp"
>
</File>
<File <File
RelativePath=".\src\RandomStreamTest.cpp" RelativePath=".\src\RandomStreamTest.cpp"
> >
@@ -947,6 +951,10 @@
RelativePath=".\src\MD5EngineTest.h" RelativePath=".\src\MD5EngineTest.h"
> >
</File> </File>
<File
RelativePath=".\src\PBKDF2EngineTest.h"
>
</File>
<File <File
RelativePath=".\src\RandomStreamTest.h" RelativePath=".\src\RandomStreamTest.h"
> >

View File

@@ -897,6 +897,10 @@
RelativePath=".\src\MD5EngineTest.cpp" RelativePath=".\src\MD5EngineTest.cpp"
> >
</File> </File>
<File
RelativePath=".\src\PBKDF2EngineTest.cpp"
>
</File>
<File <File
RelativePath=".\src\RandomStreamTest.cpp" RelativePath=".\src\RandomStreamTest.cpp"
> >
@@ -933,6 +937,10 @@
RelativePath=".\src\MD5EngineTest.h" RelativePath=".\src\MD5EngineTest.h"
> >
</File> </File>
<File
RelativePath=".\src\PBKDF2EngineTest.h"
>
</File>
<File <File
RelativePath=".\src\RandomStreamTest.h" RelativePath=".\src\RandomStreamTest.h"
> >

View File

@@ -891,6 +891,10 @@
RelativePath=".\src\MD5EngineTest.cpp" RelativePath=".\src\MD5EngineTest.cpp"
> >
</File> </File>
<File
RelativePath=".\src\PBKDF2EngineTest.cpp"
>
</File>
<File <File
RelativePath=".\src\RandomStreamTest.cpp" RelativePath=".\src\RandomStreamTest.cpp"
> >
@@ -927,6 +931,10 @@
RelativePath=".\src\MD5EngineTest.h" RelativePath=".\src\MD5EngineTest.h"
> >
</File> </File>
<File
RelativePath=".\src\PBKDF2EngineTest.h"
>
</File>
<File <File
RelativePath=".\src\RandomStreamTest.h" RelativePath=".\src\RandomStreamTest.h"
> >

View File

@@ -35,6 +35,7 @@
#include "MD5EngineTest.h" #include "MD5EngineTest.h"
#include "SHA1EngineTest.h" #include "SHA1EngineTest.h"
#include "HMACEngineTest.h" #include "HMACEngineTest.h"
#include "PBKDF2EngineTest.h"
#include "DigestStreamTest.h" #include "DigestStreamTest.h"
#include "RandomTest.h" #include "RandomTest.h"
#include "RandomStreamTest.h" #include "RandomStreamTest.h"
@@ -48,6 +49,7 @@ CppUnit::Test* CryptTestSuite::suite()
pSuite->addTest(MD5EngineTest::suite()); pSuite->addTest(MD5EngineTest::suite());
pSuite->addTest(SHA1EngineTest::suite()); pSuite->addTest(SHA1EngineTest::suite());
pSuite->addTest(HMACEngineTest::suite()); pSuite->addTest(HMACEngineTest::suite());
pSuite->addTest(PBKDF2EngineTest::suite());
pSuite->addTest(DigestStreamTest::suite()); pSuite->addTest(DigestStreamTest::suite());
pSuite->addTest(RandomTest::suite()); pSuite->addTest(RandomTest::suite());
pSuite->addTest(RandomStreamTest::suite()); pSuite->addTest(RandomStreamTest::suite());

View File

@@ -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<HMACEngine<SHA1Engine> > 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<HMACEngine<SHA1Engine> > 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<HMACEngine<SHA1Engine> > 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<HMACEngine<SHA1Engine> > 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<HMACEngine<SHA1Engine> > 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<HMACEngine<SHA1Engine> > 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;
}

View File

@@ -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