|
||
This example demonstrates how a large data file (approximately 100k) is
read and processed over several iterations in order to produce an HMAC MD5 hash
representation of the file's contents. The key-related classes are defined in
keys.h
.
#include <f32file.h>
#include <legacyselector.h>
#include <cryptohashapi.h>
#include <keys.h>
using namespace CryptoSpi;
//Constant integer to store the number of separate blocks into which
// the large data file is to be incrementally read
const TInt KDataReadBlocks = 20;
//Create and initialise a pointer for the HMAC implementation object
CHash* hmacImpl = NULL;
//If successful, the CreateHashL() method creates a hash implementation
//object which is assigned to the hmacImpl pointer. Please note that the
//key can be passed in when constructing the factory object, but for the
//purpose of demonstration, the CHash::SetKeyL() method is used later.
TRAPD(err,CHashFactory::CreateHashL(hmacImpl,
KMd5Uid,
KHashModeUid,
NULL,
NULL));
if (hmacImpl && (err == KErrNone))
{
//Create a new CCryptoParams object to encapsulate the secret key
//string and key type
CCryptoParams* keyParams = CCryptoParams::NewL();
CleanupStack::PushL(keyParams);
//Add the secret key to the CCryptoParams object by calling the
//CCryptoParams::AddL() method, passing in the key string and
//appropriate key parameter UID
keyParams->AddL(_L8("12345678"), KHmacKeyParameterUid);
//Create a key object (CKey) by passing in an instance of TKeyProperty
//and the previously created CCryptoParams object containing the secret key.
TKeyProperty keyProperty;
CKey* key=CKey::NewL(keyProperty,*keyParams);
CleanupStack::PushL(key);
//Set the key within the HMAC implementation object by calling the
//CHash::SetKeyL() method, passing in the appropriate CKey object
hmacImpl->SetKeyL(*key);
//Set the operation mode within the HMAC implementation object by calling the
//CHash::SetOperationModeL() method, passing in the UID for HMAC mode
hmacImpl->SetOperationModeL(KHmacModeUid);
//Having successfully set up the HMAC factory implementation object, the
//next stage is to read the file from disk over a number of iterations,
//updating the hash message after each read. On the last iteration, the
//message is finalised and the complete MD5 hash of the file is returned
RFs fsSession;
//Create a connection to the file server
User::LeaveIfError(fsSession.Connect());
RFile sourceFile;
CleanupClosePushL(sourceFile);
//Open the source file passing in the file server session handle,
//source file path and file access mode
User::LeaveIfError(sourceFile.Open(fsSession, _L("c:\\testdata\\largeData.dat"), EFileRead));
TInt sourceLength = 0; //Length of the data file
TInt readPosition = 0; //Current position in the data file
TInt readIncrement = 0; //Length of a single block of data
TBool hashComplete = EFalse; //Flag to determine whether the hash is complete
TPtrC8 hashData; //Holds the final hash value
//Retrieve the size of the data file using the RFile::Size() method
User::LeaveIfError(sourceFile.Size(sourceLength));
//Calculate the amount of data to read in each increment by dividing the file
//size by the number of separate blocks to split the file into
readIncrement = sourceLength/KDataReadBlocks;
//Each iteration of the loop reads in a new block of data from the current
//position within the file into a heap based descriptor. The first parse will see
//a call to the Hash() method made to set the initial state of the Hash message.
//After that the Update() method will be called until the last iteration in which a
//call is made to the Final() method along with the last block of data. As a result,
//the resulting HMAC MD5 hashed value is returned within a TPtrC8.
do
{
//Create a heap based descriptor allocating enough memory to store a
//single block of data
HBufC8* sourceData = HBufC8::NewL(readIncrement);
CleanupStack::PushL(sourceData);
//Create a modifiable pointer descriptor and use the Des() method in order
//to read in a new block of data into the heap based descriptor
TPtr8 sourcePtr = sourceData->Des();
//Read the block from the data file at the current position
err = sourceFile.Read(readPosition,sourcePtr,readIncrement);
//Update the current read position within the data file so that the next
//iteration is set
readPosition += readIncrement;
if (readPosition == readIncrement)
{
//Read in the first block from the data file into the HMAC implementation object
hmacImpl->Hash(*sourceData);
}
else if (readPosition >= sourceLength)
{
//Read in the final block, construct the complete HMAC MD5 hash
//value and assign it to a TPtrC8 (hashData)
hashData.Set(hmacImpl->Final(*sourceData));
//Set the Boolean flag to break out of the loop
hashComplete = ETrue;
}
else
{
//Update the message data within the HMAC object with the new block
hmacImpl->Update(*sourceData);
}
//Pop and destroy the heap based descriptor for the next iteration
CleanupStack::PopAndDestroy(sourceData);
}while(hashComplete == EFalse);
//Cleanup the Source RFile
CleanupStack::PopAndDestroy();
//Close the file server session
fsSession.Close();
//Pop from the cleanup stack and destroy the CKey and CCryptoParams objects
CleanupStack::PopAndDestroy(key);
CleanupStack::PopAndDestroy(keyParams);
}
//Destory the remaining HMAC implementation object
delete hmacImpl;
hmacImpl = NULL;