Переглянути джерело

Moved from SNSyncd.


git-svn-id: https://svn.microneil.com/svn/CodeDweller/trunk@24 d34b734f-a00e-4b39-a726-e4eeb87269ab
wx
adeniz 11 роки тому
джерело
коміт
6402f0a4f7
2 змінених файлів з 207 додано та 0 видалено
  1. 157
    0
      onetimepad.cpp
  2. 50
    0
      onetimepad.hpp

+ 157
- 0
onetimepad.cpp Переглянути файл

@@ -0,0 +1,157 @@
// onetimepad.cpp
// Copyright (C) 2006-2007 MicroNeil Research Corporation

#include "onetimepad.hpp"
#include "timing.hpp"

/*
class OneTimePad { // One Time Pad generator.
private:
MANGLER PagGenerator; // MANGLER as a PRNG.
PadBuffer Entropy(int Length = 1024); // System entropy source.

public:
** OneTimePad(); // Constructor initializes w/ Entropy.
** PadBuffer Pad(int Length); // Get a pad of Length.
** void addEntropy(); // Add entropy from the system source.
** void addEntropy(PadBuffer Entropy); // Add entropy from this source.

};
*/

////////////////////////////////////////////////////////////////////////////////
// Platform specific strong entropy sourcing.

#ifdef WIN32

//// WIN32 Strong Entropy Source == CryptGenRandom() ///////////////////////////

#include <windows.h>
#include <wincrypt.h>

PadBuffer OneTimePad::Entropy(int Length) { // Get a PadBuffer full of randomness.
PadBuffer Buffer(Length, 0); // Start by initializing the buffer.
HCRYPTPROV provider = 0; // We will need a handle for the source.

if( // Try a two different sources.
!CryptAcquireContext( // If we can get a hardware source
&provider, NULL, NULL, PROV_INTEL_SEC, CRYPT_VERIFYCONTEXT)) { // from an intel CPU then use that first.

if( // If we can't use get that
!CryptAcquireContext( // entropy source for some reason then
&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { // try to use the RSA source. That should
// always work, but if it doesn't we need
provider = 0; // to know about it so we'll have a zero
} // handle.
}

if(0 != provider) { // If we did get a good source then
CryptGenRandom (provider, Length, (BYTE*)&Buffer[0]); // grab the random bit required and
CryptReleaseContext(provider,0); // then let the provider go.
StrongEntropyFlag = true; // We DID get strong entropy.
}
else { // If we did not get a good source
StrongEntropyFlag = false; // then we are not strong.
}

return Buffer; // Return the data we got.
}

#else

//// *NIX Strong Entropy Source == /dev/urandom ////////////////////////////////

#include <fstream>

PadBuffer OneTimePad::Entropy(int Length) { // Get Length bytes of strong entropy.
PadBuffer Buffer(Length, 0); // Initialize a buffer to hold them.
try { // Handle this in a try block.
ifstream Source("/dev/urandom", ios::binary); // Open /dev/urandom if possible.
Source.read(reinterpret_cast<char*>(&Buffer[0]), Length); // Read data into the buffer.
if(!Source.bad() && Source.gcount() == Length) { // If we got what we came for then
StrongEntropyFlag = true; // we have strong cryptography.
} else { // If we didn't then we are not
StrongEntropyFlag = false; // strong, and don't have things
} // to make us go.
Source.close(); // We're done, so close the stream.
}

catch(...) { // If we had an exception then we
StrongEntropyFlag = false; // did not get strong entropy.
}
return Buffer; // Return the buffer.
}

#endif

// End Platform Specific Bits
////////////////////////////////////////////////////////////////////////////////

// Lightweight entropy is built from a combination of the time in ms UTC that
// the application was started, the number of milliseconds since that time in
// milliseconds, the number and times of calls to addLightweightEntropy(), and
// the state of the MANGLER engine at each call -- that state is effected by
// the combined previous use of the MANGLER and any other entropy that was
// added including the timing of those events (since they all trigger the
// addLightweightEntropy() function.

Timer OneTimePadRunTimer; // Millisecond entropy source.
msclock LightweightEntropyBuffer; // Lightweight entropy bucket.

void OneTimePad::addLightweightEntropy() { // Add entropy based on the
msclock StartFill = OneTimePadRunTimer.getStartClock(); // initial start time of the app
msclock ElapsedFill = OneTimePadRunTimer.getElapsedTime(); // and the number of millisecs since.
msclock CombinedFill = StartFill ^ ElapsedFill; // XOR the two together to combine.
CombinedFill = CombinedFill ^ LightweightEntropyBuffer; // Pick up some previous state entropy.
unsigned char* PrimerBuffer = (unsigned char*) &CombinedFill; // Treat the value as a bunch of bytes.
unsigned char* EntropyBuffer = (unsigned char*) &LightweightEntropyBuffer; // Likewise with the entropy buffer.
for(int i = 0; i < sizeof(msclock); i++) { // Fold bytes into the mangler one
EntropyBuffer[i] += // byte at a time, capturing the
PadGenerator.Encrypt( // the results and using one extra
PadGenerator.Encrypt(PrimerBuffer[i])); // round per byte to increase the
} // amount of guessing an attacker
} // needs to do.

void OneTimePad::addEntropy() { // Add strong entropy if available.
PadBuffer Fill = Entropy(); // Grab the entropy bits to add.
for(int i = 0; i < Fill.size(); i++) { // Pump them in one byte at a
PadGenerator.Encrypt( // time and then run an extra
PadGenerator.Encrypt(Fill.at(i))); // round per byte to increase the
} // amount of guessing an attacker
} // needs to do.

void OneTimePad::addEntropy(PadBuffer Entropy) { // Add entropy from a given source.
addLightweightEntropy(); // Start with some lightweight entropy.
for(int i = 0; i < Entropy.size(); i++) { // Then loop through the provided
PadGenerator.Encrypt( // entropy and mix it in with one
PadGenerator.Encrypt(Entropy.at(i))); // extra round per byte to increase
} // the amount of guessing an attacker
} // needs to do.

PadBuffer OneTimePad::Pad(int Length) { // Grab a pad of a specific length.
addLightweightEntropy(); // Add some lightweight entropy.
PadBuffer Output; Output.reserve(Length); // Create a buffer the right size.
unsigned char x; // Starting with an uninitialized
for(int i = 0; i < Length; i++) // char, fill the buffer with
Output.push_back(x = PadGenerator.Encrypt(x)); // random bytes from the mangler.
return Output; // Return the new pad.
}

void* OneTimePad::fill(void* Object, int Size) { // Fill *Object with random bytes.
PadBuffer FillData = Pad(Size); // Get a Pad of the correct size.
unsigned char* Ptr = reinterpret_cast<unsigned char*>(Object); // Reinterpret the pointer type.
for(int i = 0; i < Size; i++) Ptr[i] = FillData.at(i); // Fill the object with the Pad.
return Object; // Return the object.
}

bool OneTimePad::isStrong() { return StrongEntropyFlag; } // Tell them if I'm strong!

OneTimePad::OneTimePad() { // Initialize the one time pad.
addLightweightEntropy(); // Add lightweight entropy.
addEntropy(); // Add cryptographic entropy.
unsigned char x; // Starting with an uninitialized
for(int i = 0; i < 1024; i++) { // character, run 1024 rounds to
x = PadGenerator.Encrypt(x); // reduce the predictability of the
} // initial Mangler state.
} // The OneTimePad object is ready.


+ 50
- 0
onetimepad.hpp Переглянути файл

@@ -0,0 +1,50 @@
// onetimepad.hpp
// Copyright (C) 2006 - 2007 MicroNeil Research Corporation
//
// This module leverages the Mangler encryption engine to create
// cryptographically strong one-time pads and random numbers upon request.
// The engine is seeded by /dev/urandom on *nix machines and by CryptGenRandom
// on win32 machines. Additionally, each call to get new data introduces a
// small amount of entropy based on the jitter in timing between calls and the
// amount of time the application has been running since the generator was
// started. Additional entropy can be provided by the application or again from
// one of the core entropy generators (/dev/urandom or CryptGenRandom).
#ifndef onetimepad_included
#define onetimepad_included
#include <vector>
#include "mangler.hpp"
using namespace std;
typedef vector<unsigned char> PadBuffer;
class OneTimePad { // One Time Pad generator.
private:
MANGLER PadGenerator; // MANGLER as a PRNG.
void addLightweightEntropy(); // Add light weight entropy bits.
PadBuffer Entropy(int Length = 1024); // System entropy source.
void* fill(void* Object, int Size); // Internal method to fill an object.
bool StrongEntropyFlag; // True if strong entropy is used.
public:
OneTimePad(); // Constructor initializes w/ Entropy.
bool isStrong(); // True if strong entropy is available.
PadBuffer Pad(int Length); // Get a pad of Length.
void addEntropy(); // Add entropy from the system source.
void addEntropy(PadBuffer Entropy); // Add entropy from this source.
template <typename T> // Fill any kind of object
T& fill(T& Object) { // with random bytes.
fill((void*) &Object, sizeof(Object)); // Get a void ptr to it, fill it,
return Object; // and return it to the caller.
}
};
#endif

Завантаження…
Відмінити
Зберегти