⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 globrand.cpp

📁 伯克利做的SFTP安全文件传输协议
💻 CPP
字号:
// globrand.cc// code for globrand.h// copyright SafeTP Development Group, Inc., 2000  Terms of use are as specified in license.txt#include "globrand.h"        // this module#include "keyutils.h"        // LoadKey, SaveKey#include "entropy.h"         // a source of entropy#include "exc.h"             // xBase#include "ssha.h"            // SHA#include "warn.h"            // warning#include "nonport.h"         // LOCKER, portable{Lock,Unlock}// ------------------ HashedRandomPool -----------------enum {  SEED_LENGTH = 384,          // use the same value mentioned in randpool.h  POOL_MDC_KEY_LENGTH = 64,   // MD5's block size  TOTAL_SEED_LENGTH = SEED_LENGTH + POOL_MDC_KEY_LENGTH};HashedRandomPool::HashedRandomPool()  : basePool(SEED_LENGTH),    notSeeded(true){  forceRehash();}void HashedRandomPool::forceRehash(){  outPtr = BUFSIZE;}byte HashedRandomPool::GetByte(){  if (notSeeded) {    warning((WarnLevel)(WARN_SECURITY | WARN_DEBUG),            "Random pool has not been seeded.");    // even though the condition is really still true,    // it's pointless to continue to spew warnings    notSeeded = false;  }  // test to see if we have to refill the output buffer  if (outPtr >= BUFSIZE) {    xassert(outPtr == BUFSIZE);     // shouldn't go beyond    // grab bytes directly from the pool    basePool.GetBlock(outBuffer, BUFSIZE);    // hash them in-place    xassert((int)BUFSIZE == (int)SHA::DIGESTSIZE);    SHA sha;    sha.CalculateDigest(outBuffer, outBuffer, BUFSIZE);    // reset output ptr to begin at the beginning    outPtr = 0;  }  // return next byte  return outBuffer[outPtr++];}DataBlock HashedRandomPool::getSeed(){  // pull out (without hashing) a number of bytes  // sufficient to get the pool bytes *plus* the  // (internal to basePool) MDC key bytes  DataBlock ret(TOTAL_SEED_LENGTH);  basePool.GetBlock(ret.getData(), TOTAL_SEED_LENGTH);  ret.setDataLen(TOTAL_SEED_LENGTH);  return ret;}void HashedRandomPool::seed(DataBlock const &seed){  // just shove the bytes into the base pool and  // assume it will properly distribute entropy  // (a reasonable assumption, I believe)  basePool.Put(seed.getDataC(), seed.getDataLen());  // calling forceRehash would not accomplish much  // (I think..), so I don't  notSeeded = false;}void HashedRandomPool::Put(byte const *bytes, int length){  basePool.Put(bytes, length);  notSeeded = false;}// --------------- functions ----------------------// just some name..// thread safety: I think it's a good idea to protect accesses// to this file toochar const seedKeyName[] = "randomSeed";// thread safety: *requires* all access to be protected by the lock;// static declaration prevents even the linker from find it!// USE INSTEAD: GlobalRandomPool, pool() method (see e.g. cryputil.cpp)static HashedRandomPool globalRandomPool;// read seed from persistent statevoid readRandomSeed(bool complain){   {    // scope this to avoid nested locking in addEntropy    LOCKER    // read it    DataBlock seed;    string temp(seedKeyName);    if (LoadKey(temp, seed)) {      // stuff it into the pool      globalRandomPool.seed(seed);    }    else {      if (complain) {        // this is going to happen the first time, but should        // *only* happen the first time        warning(WARN_SECURITY,                "The random seed file is missing.  Creating a new one now.");      }    }  }  // on the presumption that calling this fn is done at the start of  // the program, there may be entropy in there (this, at very least,  // also prevents the seed from being *totally* predictable if the  // seed key file is missing)  addEntropy();  // SM: There appears to be a bad interaction with loading and then  //     saving immediately.  It's possible that this effect is not  //     specific to our PRNG.  //SaveKey(temp, seed);}bool isRandomSeedThere(){  LOCKER  return sm_testKey(seedKeyName);}// save seed to persistent statevoid saveRandomSeed(){  string temp(seedKeyName);  DataBlock oldseed;  // SM: I've decided there is some risk in this policy, and since  //     losing entropy from multiple processes is much less important  //     than losing all/most entropy due to another effect I think  //     is present# if 0  // we first seed our pool with what is on disk, so that additional  // entropy added by other instances of this process is not lost; we  // rely on basePool's ability to fold-in new bytes *without* evicting  // entropy already in the system (it can; it XORs the new with the old)  if (LoadKey(temp, oldseed)) {    // stuff it into the pool    globalRandomPool.seed(oldseed);    }# endif //0  addEntropy(); // get in some more entropy  // protect file access  LOCKER  // retrieve the seed  DataBlock seed = globalRandomPool.getSeed();  // write it out  if (!SaveKey(temp, seed)) {    THROW(xBase("failed to save random seed"));  }}// add a specific value that may be entropicvoid addEntropy(long value){  // let's use the locking method external clients are expected  // to use, in part to test it  GlobalRandomPool grp;  // in the unlikely chance an adversary can choose 'value', which  // could (conceivably) be used to attack the random pool,  // we'll go to the trouble of hashing it now  SHA sha;  byte digest[SHA::DIGESTSIZE];  // hash the bytes  sha.CalculateDigest(digest, (byte*)&value, sizeof(value));  // fold in the hashed bytes  grp.pool().Put(digest, SHA::DIGESTSIZE);}// add entropyvoid addEntropy(){  // read things like time of day, current mouse position, etc.  long e = getEntropy();  addEntropy(e);}// alternate interfaceDataBlock getRandomBytes(int bytes){  GlobalRandomPool grp;  DataBlock ret(bytes);  grp.pool().GetBlock(ret.getData(), bytes);  ret.setDataLen(bytes);  return ret;}// ----------------- the global random pool ----------------GlobalRandomPool::GlobalRandomPool(){  portableLock();}GlobalRandomPool::~GlobalRandomPool(){  portableUnlock();}HashedRandomPool &GlobalRandomPool::pool(){  return globalRandomPool;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -