📄 shamirtest.c
字号:
/*____________________________________________________________________________
ShamirTest.c
Copyright (C) 2003,2004 PGP Corporation
All rights reserved.
FIPS 140-2 Operational Test/ Secret sharing test
$Id: ShamirTest.c 48493 2006-10-12 21:19:56Z vinnie $
____________________________________________________________________________*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if PGP_WIN32
#include <io.h>
#include <direct.h>
#endif
#include "pgpErrors.h"
#include "pgpKeys.h"
#include "pgpShare.h"
#include "pgpShareFile.h"
#include "pgpMemoryMgr.h"
#include "pgpUtilities.h"
#include "optest.h"
#define kPGPShareHeaderSize 4
#define kNumShares 6
#define kShareThreshold 4
static PGPError TestShares(PGPContextRef context)
{
PGPError err = kPGPError_NoErr;
PGPKeyDBRef keyDB = kInvalidPGPKeyDBRef;
PGPKeyDBObjRef theKey = kInvalidPGPKeyDBObjRef;
PGPShareRef share = kInvalidPGPShareRef;
PGPFileSpecRef shareDirSpec = kInvalidPGPFileSpecRef;
PGPSize passKeySize = 0;
PGPByte* passKey = NULL;
PGPKeyID theKeyID;
char buffer[256];
char keyIDstr[kPGPMaxKeyIDStringSize];
PGPSize bufSize;
PGPInt32 version = 0;
int i;
PGPBoolean done = FALSE;
PGPByte fp[64];
PGPSize fplen;
OPTESTPrintF("\tHigh Level Key Share Test\n");
/* Read in the test key and get a ref to it */
err = importKeys(context,gTestKeysPath, kPGPInputFormat_PGP, &keyDB); CKERR;
/* TE03.14.02 - Key Management */
/* Find test Key */
OPTESTPrintF("\t Find Key %s", kAlicesKeyIDString );
err = PGPNewKeyIDFromString( kAlicesKeyIDString, kPGPPublicKeyAlgorithm_Invalid, &theKeyID); CKERR;
err = PGPFindKeyByKeyID( keyDB, &theKeyID, &theKey); CKERR;
/* get the primary key ID (signing key) name */
PGPGetKeyID( theKey, &theKeyID );
PGPGetKeyIDString( &theKeyID, kPGPKeyIDString_Abbreviated, keyIDstr);
PGPGetKeyDBObjDataProperty(theKey,kPGPKeyProperty_Fingerprint, &fp,sizeof(fp), &fplen);
err = PGPGetPrimaryUserIDName(theKey, buffer, sizeof(buffer), &bufSize);
OPTESTPrintF("\"%s\" \n",buffer);
OPTESTPrintF("\t Deconstructing Key into %d shares\n",kNumShares);
err = PGPCreateShares(context, theKey, kShareThreshold, kNumShares, &share); CKERR;
OPTESTPrintF("\t Split into %d shares, %d needed to recombine.\n", PGPGetTotalNumberOfShares( share), PGPGetShareThreshold( share));
OPTESTPrintF("\t Getting passkey for shares\n");
err = PGPGetPasskeyFromShares (share, &passKey, &passKeySize);
if(gVerbose_flag)
{
dumpHex(passKey, passKeySize, 0);
}
OPTESTPrintF("\t Changing Alice's passphrases to new passkey\n");
err = PGPChangePassphrase( theKey,
PGPOPassphrase( context, kAlicesPassPhrase ),
PGPOPasskeyBuffer( context, passKey, passKeySize ),
PGPOLastOption( context ) ); CKERR;
/* we must also change all subkey paasphrases. */
err = PGPGetKeyDBObjNumericProperty( theKey, kPGPKeyProperty_Version, &version ); CKERR;
if( version == kPGPKeyVersion_V4 )
{
PGPKeyIterRef keyIter;
PGPKeyDBObjRef subKey;
err = PGPNewKeyIterFromKeyDB( keyDB, &keyIter ); CKERR;
PGPKeyIterSeek( keyIter, theKey );
while( IsntPGPError ( err ) &&
IsntPGPError( PGPKeyIterNextKeyDBObj( keyIter, kPGPKeyDBObjType_SubKey, &subKey ) ) )
{
err = PGPChangePassphrase( subKey,
PGPOPassphrase( context, kAlicesPassPhrase ),
PGPOPasskeyBuffer( context, passKey, passKeySize ),
PGPOLastOption( context ) );
}
PGPFreeKeyIter( keyIter );
}
PGPFreeData( passKey );
passKey= NULL;
OPTESTPrintF("\t Trying old passphrase...");
if( !PGPPassphraseIsValid(theKey,
PGPOPassphrase( context, kAlicesPassPhrase ),
PGPOLastOption( context )))
{
OPTESTPrintF("no longer valid.\n");
}
else FAIL("passphrase did not change");
OPTESTPrintF("\t Create share %d files, (1 share each)\n", kNumShares);
for(i = 0; i < kNumShares; i++)
{
PGPFileSpecRef shareSpec = kInvalidPGPFileSpecRef;
PGPShareFileRef shareFile = kInvalidPGPShareFileRef;
PGPShareRef sharesHolder = kInvalidPGPShareRef;
PGPOptionListRef optionList = kInvalidPGPOptionListRef;
sprintf(buffer, "%s/share%d", gOutputDirectory, i);
if(makeFile(buffer) ) FAIL("makefile Failed \n");
err = PGPNewFileSpecFromFullPath(context, buffer, &shareSpec) ; CKERR;
if(gVerbose_flag) OPTESTPrintF("\t %s\n", buffer);
err = PGPBuildOptionList (context, &optionList,
PGPOConventionalEncrypt (context,
PGPOPassphrase (context, kAlicesPassPhrase),
PGPOLastOption (context)),
PGPOLastOption (context)); CKERR;
err = PGPNewShareFile ((PFLFileSpecRef)shareSpec, &shareFile); CKERR;
err = PGPSetShareFileUserID (shareFile, (PGPUTF8*)"Optest User"); CKERR;
err = PGPSetShareFileOwnerKeyID(shareFile, theKeyID); CKERR;
err = PGPSetShareFileOwnerFingerprint(shareFile, fplen, fp);CKERR;
err = PGPSplitShares (share, 1, &sharesHolder); CKERR;
err = PGPCopySharesToFile (context, shareFile, optionList, sharesHolder); CKERR;
err = PGPSaveShareFile (shareFile); CKERR;
if (PGPOptionListRefIsValid (optionList))
PGPFreeOptionList (optionList);
if (PGPShareRefIsValid (sharesHolder))
PGPFreeShares (sharesHolder);
if (PGPShareFileRefIsValid (shareFile))
PGPFreeShareFile (shareFile);
if (PGPFileSpecRefIsValid (shareSpec))
PGPFreeFileSpec (shareSpec);
}
/* free up shares */
PGPFreeShares( share );
share = kInvalidPGPShareRef;
OPTESTPrintF("\t Joining shares \n");
for(done = FALSE, i = 0; i < kNumShares && !done; i++)
{
PGPFileSpecRef shareSpec = kInvalidPGPFileSpecRef;
PGPShareFileRef shareFile = kInvalidPGPShareFileRef;
PGPShareRef newShares = kInvalidPGPShareRef;
PGPShareRef tempShares = kInvalidPGPShareRef;
PGPOptionListRef optionList = kInvalidPGPOptionListRef;
PGPKeyID thisKeyID;
sprintf(buffer, "%s/share%d", gOutputDirectory, i);
err = PGPNewFileSpecFromFullPath(context, buffer, &shareSpec) ; CKERR;
if(gVerbose_flag)OPTESTPrintF("\t %s - ", buffer);
err = PGPOpenShareFile((PFLFileSpecRef)shareSpec, &shareFile); CKERR;
err = PGPGetShareFileUserID(shareFile, sizeof(buffer), (PGPUTF8*)buffer, &bufSize); CKERR;
buffer[bufSize] = '\0';
if(gVerbose_flag) OPTESTPrintF("%s - %d share\n", buffer, PGPGetNumSharesInFile(shareFile));
err = PGPGetShareFileSharedKeyID(shareFile, &thisKeyID); CKERR;
err = PGPGetShareFileOwnerFingerprint(shareFile, sizeof(fp), (PGPUTF8*)fp, &fplen); CKERR;
err = PGPBuildOptionList (context, &optionList,
PGPOPassphrase (context, kAlicesPassPhrase),
PGPOLastOption (context)); CKERR;
err = PGPCopySharesFromFile (context, shareFile, optionList, &newShares); CKERR;
if (err == kPGPError_BadPassphrase)
{
/* Ignore bad passphrase errors, just move on to the next share */
err = kPGPError_NoErr;
}
if (PGPShareRefIsValid (newShares))
{
PGPShareID shareID;
err = PGPGetKeyIDFromShares(newShares, &thisKeyID); CKERR;
err = PGPGetShareID(newShares, &shareID); CKERR;
if( PGPCompareKeyIDs(&theKeyID, &thisKeyID) == 0)
{
if (PGPShareRefIsValid (share))
{
err = PGPCombineShares (share, newShares, &tempShares);
if (err == kPGPError_SplitIdenticalShares)
{
err = kPGPError_NoErr;
}
else if (IsPGPError (err))
{
CKERR;
}
else
{
err = PGPFreeShares (share); CKERR;
share = tempShares;
tempShares = kInvalidPGPShareRef;
}
err = PGPFreeShares (newShares); CKERR;
newShares = kInvalidPGPShareRef;
if( PGPGetNumberOfShares( share) >= PGPGetShareThreshold( share))
{
OPTESTPrintF("\t Collected %d shares, only needed %d.\n",
PGPGetNumberOfShares( share),PGPGetShareThreshold( share));
done = TRUE;
}
}
else
{
share = newShares;
newShares = kInvalidPGPShareRef;
}
}
}
if (PGPOptionListRefIsValid (optionList))
PGPFreeOptionList (optionList);
if (PGPShareRefIsValid (newShares))
PGPFreeShares (newShares);
if (PGPShareFileRefIsValid (shareFile))
PGPFreeShareFile (shareFile);
if (PGPFileSpecRefIsValid (shareSpec))
PGPFreeFileSpec (shareSpec);
}
OPTESTPrintF("\t Getting passkey for shares\n");
err = PGPGetPasskeyFromShares (share, &passKey, &passKeySize);
if(gVerbose_flag)
{
dumpHex(passKey, passKeySize, 0);
}
OPTESTPrintF("\t Checking Alice's passphrases with combined passkey\n");
err = PGPPassphraseIsValid( theKey,
PGPOPasskeyBuffer( context, passKey, passKeySize ),
PGPOLastOption( context ) )?kPGPError_NoErr:kPGPError_BadPassphrase; CKERR;
done:
if (PGPFileSpecRefIsValid (shareDirSpec))
PGPFreeFileSpec (shareDirSpec);
if( IsntNull( passKey ) )
PGPFreeData( passKey );
if( PGPShareRefIsValid( share ) )
PGPFreeShares( share );
if( PGPKeyDBRefIsValid( keyDB ) )
PGPFreeKeyDB( keyDB );
return err;
}
/*
Run Secret sharing test
*/
static PGPError TestShamir(PGPContextRef context)
{
PGPError err = kPGPError_NoErr;
PGPUInt32 shareSize;
PGPUInt32 totalSharesSize;
PGPByte * shareBuf = NULL;
PGPUInt32 i;
PGPByte testData[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
PGPByte decodeBuf[sizeof (testData)];
OPTESTPrintF("\tLow Level Shamir Key splitting Test\n");
if(gVerbose_flag)
{
OPTESTPrintF("\t Original Data:\n");
dumpHex(testData , sizeof (testData),0);
OPTESTPrintF("\n");
}
shareSize = kPGPShareHeaderSize + sizeof (testData);
totalSharesSize = shareSize * kNumShares;
shareBuf = (PGPByte *)PGPNewSecureData( PGPGetDefaultMemoryMgr(),
totalSharesSize,
kPGPMemoryMgrFlags_Clear);
/* TE03.14.02 - Split a binary passphrase */
OPTESTPrintF("\t Deconstructing data into %d shares\n",kNumShares);
err = PGPSecretShareData(context,testData, sizeof (testData), kShareThreshold, kNumShares, shareBuf);
CKERR;
if(gVerbose_flag)
{
for( i = 0; i < kNumShares; i++)
{
OPTESTPrintF("\t Share %d:\n", i);
dumpHex(shareBuf+(shareSize *i) , shareSize,0);
}
OPTESTPrintF("\n");
}
OPTESTPrintF("\t Check shares for data leakage against known original message...");
for( i = 0; i < kNumShares; i++)
{
/* check shares for data leakage against known original message */
err = pgpMemoryEqual(shareBuf+(shareSize *i) + kPGPShareHeaderSize,
testData, sizeof (testData))
? kPGPError_SelfTestFailed : kPGPError_NoErr;
CKERR;
}
OPTESTPrintF("OK\n");
/* Reconstruct data */
OPTESTPrintF("\t Attempt to Reconstructing data with not enough shares (%d)\n",kShareThreshold -1 );
err = PGPSecretReconstructData(context, shareBuf, sizeof(testData), kShareThreshold -1, decodeBuf);
if(IsPGPError(err))
{
char str[256];
PGPGetErrorString( err, 256, str);
OPTESTPrintF("\t Failed %d - %s\n",err,str);
}
else
RETERR(kPGPError_SelfTestFailed);
/* Reconstruct data */
OPTESTPrintF("\t Reconstructing data with just %d shares...",kShareThreshold);
err = PGPSecretReconstructData(context, shareBuf, sizeof(testData), kShareThreshold, decodeBuf); CKERR;
OPTESTPrintF("OK\n");
/* check result against known original message */
OPTESTPrintF("\t Check result against known original message...");
err = pgpMemoryEqual(decodeBuf, testData, sizeof (testData))
? kPGPError_NoErr : kPGPError_SelfTestFailed; CKERR;
OPTESTPrintF("OK\n");
done:
if( shareBuf != NULL)
PGPFreeData(shareBuf);
return err;
}
PGPError TestSecretSharing(PGPContextRef context)
{
PGPError err = kPGPError_NoErr;
err = TestShamir(context); CKERR;
OPTESTPrintF("\t --------------------\n\n");
err = TestShares(context); CKERR;
done:
return err;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -