📄 util.cpp
字号:
/// \file Util.cpp//-----------------------------------------------------------------------------#include "sha1.h"#include "BlowFish.h"#include "PwsPlatform.h"#include <stdio.h>#include "Util.h"// for now#define String CString#define SecString CMyString// used by CBC routines...static voidxormem(unsigned char* mem1, unsigned char* mem2, int length){ for (int x=0;x<length;x++) mem1[x] ^= mem2[x];}//-----------------------------------------------------------------------------/* Note: A bunch of the encryption-related routines may not be Unicode compliant. Which really isn't a huge problem, since they are actually using MFC routines anyway*///-----------------------------------------------------------------------------//Overwrite the memoryvoidtrashMemory(SHA1_CTX& context){ trashMemory((unsigned char*)context.state, sizeof context.state); trashMemory((unsigned char*)context.count, sizeof context.count); trashMemory((unsigned char*)context.buffer, sizeof context.buffer);}voidtrashMemory(unsigned char* buffer, long length, int numiter) // default 30{ // {kjp} no point in looping around doing nothing is there? if ( length != 0 ) { for (int x=0; x<numiter; x++) { memset(buffer, 0x00, length); memset(buffer, 0xFF, length); memset(buffer, 0x00, length); } }}voidtrashMemory( LPTSTR buffer, long length, int numiter ){ trashMemory( (unsigned char *) buffer, length * sizeof(buffer[0]), numiter );}//Generates a passkey-based hash from stuff - used to validate the passkeyvoidGenRandhash(const CMyString &a_passkey, const unsigned char* a_randstuff, unsigned char* a_randhash){ const LPCSTR pkey = (const LPCSTR)a_passkey; /* I'm not quite sure what this is doing, so as I figure out each piece, I'll add more comments {jpr} */ /* tempSalt <- H(a_randstuff + a_passkey) */ SHA1_CTX keyHash; SHA1Init(&keyHash); SHA1Update(&keyHash, a_randstuff, StuffSize); SHA1Update(&keyHash, (const unsigned char*)pkey, a_passkey.GetLength()); unsigned char tempSalt[20]; // HashSize SHA1Final(tempSalt, &keyHash); /* tempbuf <- a_randstuff encrypted 1000 times using tempSalt as key? */ BlowFish Cipher(tempSalt, sizeof(tempSalt)); unsigned char tempbuf[StuffSize]; memcpy((char*)tempbuf, (char*)a_randstuff, StuffSize); for (int x=0; x<1000; x++) Cipher.Encrypt(tempbuf, tempbuf); /* hmm - seems we're not done with this context we throw the tempbuf into the hasher, and extract a_randhash */ SHA1Update(&keyHash, tempbuf, StuffSize); SHA1Final(a_randhash, &keyHash); trashMemory(keyHash);}unsigned charnewrand(){ int r; while ((r = rand()) % 257 == 256) ; // 257?!? return (unsigned char)r;}/* * RangeRand(len) * * Returns a random number in the range 0 to (len-1). * For example, RangeRand(256) returns a value from 0 to 255. */unsigned intRangeRand(size_t len){ unsigned int r; unsigned int ceil = UINT_MAX - (UINT_MAX % len) - 1; while ((r = rand()) > ceil) ; return(r%len);}/* * Returns a BlowFish object set up for encryption or decrytion. * * The main issue here is that the BlowFish key is SHA1(passphrase|salt) * Aside from saving duplicate code, we win here by minimizing the exposure * of the actual key. * The lose is that the BlowFish object is now dynamically allocated. * This could be fixed by having a ctor of BlowFish that works without a key, * which would be set by another member function, but I doubt that it's worth the bother. * * Note that it's the caller's responsibility to delete the BlowFish object allocated here */BlowFish *MakeBlowFish(const unsigned char *pass, int passlen, const unsigned char *salt, int saltlen){ unsigned char passkey[20]; // SHA1 digest is 20 bytes - why isn't there a constant for this?#if !defined(POCKET_PC) VirtualLock(passkey, sizeof(passkey));#endif SHA1_CTX context; SHA1Init(&context); SHA1Update(&context, pass, passlen); SHA1Update(&context, salt, saltlen); SHA1Final(passkey, &context); BlowFish *retval = new BlowFish(passkey, sizeof(passkey)); trashMemory(passkey, sizeof(passkey)); trashMemory(context);#if !defined(POCKET_PC) VirtualUnlock(passkey, sizeof(passkey));#endif return retval;}int_writecbc(FILE *fp, const unsigned char* buffer, int length, unsigned char type, const unsigned char *pass, int passlen, const unsigned char* salt, int saltlen, unsigned char* cbcbuffer){ int numWritten = 0; int BlockLength = ((length+7)/8)*8; if (BlockLength == 0) BlockLength = 8; BlowFish *Algorithm = MakeBlowFish(pass, passlen, salt, saltlen); // First encrypt and write the length of the buffer unsigned char lengthblock[8]; memset(lengthblock, 0, 8); putInt32( lengthblock, length ); // following new for format 2.0 - lengthblock bytes 4-7 were unused before. lengthblock[sizeof(length)] = type; xormem(lengthblock, cbcbuffer, 8); // do the CBC thing Algorithm->Encrypt(lengthblock, lengthblock); memcpy(cbcbuffer, lengthblock, 8); // update CBC for next round numWritten = fwrite(lengthblock, 1, 8, fp); trashMemory(lengthblock, 8); // Now, encrypt and write the buffer unsigned char curblock[8]; for (int x=0;x<BlockLength;x+=8) { if ((length == 0) || ((length%8 != 0) && (length-x<8))) { //This is for an uneven last block memset(curblock, 0, 8); memcpy(curblock, buffer+x, length % 8); } else memcpy(curblock, buffer+x, 8); xormem(curblock, cbcbuffer, 8); Algorithm->Encrypt(curblock, curblock); memcpy(cbcbuffer, curblock, 8); numWritten += fwrite(curblock, 1, 8, fp); } trashMemory(curblock, 8); delete Algorithm; return numWritten;}/* * Reads an encrypted record into buffer. * The first block of the record contains the encrypted record length * We have the usual ugly problem of fixed buffer lengths in C/C++. * Don't want to use CStrings, for future portability. * Best solution would be STL strings, but not enough experience with them (yet) * So for the meantime, we're going to allocate the buffer here, to ensure that it's long * enough. * *** THE CALLER MUST delete[] IT AFTER USE *** UGH++ * * (unless buffer_len is zero) * * An alternative to STL strings would be to accept a buffer, and allocate a replacement * iff the buffer is too small. This is serious ugliness, but should be considered if * the new/delete performance hit is too big. */int_readcbc(FILE *fp, unsigned char* &buffer, unsigned int &buffer_len, unsigned char &type, const unsigned char *pass, int passlen, const unsigned char* salt, int saltlen, unsigned char* cbcbuffer){ int numRead = 0; unsigned char lengthblock[8]; unsigned char lcpy[8]; buffer_len = 0; numRead = fread(lengthblock, 1, sizeof lengthblock, fp); if (numRead != 8) return 0; memcpy(lcpy, lengthblock, 8); BlowFish *Algorithm = MakeBlowFish(pass, passlen, salt, saltlen); Algorithm->Decrypt(lengthblock, lengthblock); xormem(lengthblock, cbcbuffer, 8); memcpy(cbcbuffer, lcpy, 8); int length = getInt32( lengthblock ); // new for 2.0 -- lengthblock[4..7] previously set to zero type = lengthblock[sizeof(int)]; // type is first byte after the length trashMemory(lengthblock, 8); trashMemory(lcpy, 8); if (length < 0) { delete Algorithm; buffer = NULL; buffer_len = 0; return 0; } int BlockLength = ((length+7)/8)*8; // Following is meant for lengths < 8, // but results in a block being read even // if length is zero. This is wasteful, // but fixing it would break all existing databases. if (BlockLength == 0) BlockLength = 8; buffer_len = length; buffer = new unsigned char[BlockLength]; // so we lie a little... unsigned char tempcbc[8]; numRead += fread(buffer, 1, BlockLength, fp); for (int x=0;x<BlockLength;x+=8) { memcpy(tempcbc, buffer+x, 8); Algorithm->Decrypt(buffer+x, buffer+x); xormem(buffer+x, cbcbuffer, 8); memcpy(cbcbuffer, tempcbc, 8); } trashMemory(tempcbc, 8); delete Algorithm; if (length == 0) { // delete[] buffer here since caller will see zero length delete[] buffer; } return numRead;}/** * Returns the current length of a file. */long fileLength( FILE *fp ){ long pos; long len; pos = ftell( fp ); fseek( fp, 0, SEEK_END ); len = ftell( fp ); fseek( fp, pos, SEEK_SET ); return len;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -