📄 keysplit.c
字号:
/* keysplit.c - Implements support for splitting/rejoining keys
base off of code found in PGPKeys. */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include "pgpBase.h"
#include "pgpKeys.h"
#include "pgpErrors.h"
#include "pgpContext.h"
#include "pgpEnv.h"
#include "pgpPubTypes.h"
#include "pgpFileSpec.h"
#include "pgpShare.h"
#include "pgpShareFile.h"
#include "globals.h"
#include "prototypes.h"
#include "language.h"
#include "fileio.h"
/* should probably move this to a header file later but...*/
typedef struct _SHAREHOLDERSTRUCT {
PGPBoolean bPublicKey;
PGPKeyID keyid;
PGPPublicKeyAlgorithm keyalg;
char szUserID[kPGPMaxUserIDSize];
char *pszPassphrase;
PGPUInt16 uShares;
} SHAREHOLDERSTRUCT, *PSHAREHOLDERSTRUCT;
/* taken from KMShare.c */
#define MAX_SHARES 99
#define MAX_SHARES_LEN 2
PGPError sCreateFilePathFromUserName (char *pszFolder,
char *pszUserID,
PGPUInt16 uNumShares,
char *pszModifier,
char *pszPath,
PGPInt16 iLen);
PGPError sSaveSharesToFile (PSHAREHOLDERSTRUCT pshs,
PGPContextRef context,
PGPShareRef sharesTotal,
PGPKeySetRef keyset,
char *pszFolder);
PGPError sChangeKeyPhrase (PGPContextRef context,
PGPKeySetRef keyset,
PGPKeyRef key,
char *szOld,
PGPByte* pPasskeyOld,
PGPSize sizePasskeyOld,
PGPByte* pPasskey,
PGPSize sizePasskey);
PGPError pgpParseShares(struct pgpmainBones *mainbPtr,
SHAREHOLDERSTRUCT **pshs,
char **ppszUsers,
PGPUInt16 myArgc,
PGPUInt32 *dwThreshold,
PGPUInt32 *dwTotalShares,
PGPUInt32 *dwTotal);
PGPError SplitKey (struct pgpmainBones *mainbPtr, char *pszKeyToSplit, char **ppszUsers, PGPUInt16 myArgc)
{
PGPContextRef context = mainbPtr->pgpContext;
struct pgpargsBones *argsbPtr = mainbPtr->argsbPtr;
struct pgpfileBones *filebPtr = mainbPtr->filebPtr;
struct pgpenvBones *envbPtr = mainbPtr->envbPtr;
PGPKeySetRef workingset = kPGPInvalidRef;
PGPKeySetRef keyset = kPGPInvalidRef;
PGPKeyID keyidToSplit;
PGPPublicKeyAlgorithm keyalgToSplit;
PGPKeyListRef keylist = kPGPInvalidRef;
PGPKeyIterRef keyiter = kPGPInvalidRef;
PGPKeyRef keyToSplit = kPGPInvalidRef;
PGPError err = kPGPError_NoErr;
char *pszPassphrase = NULL;
PGPShareRef shares = kPGPInvalidRef;
PGPUInt32 dwThreshold = 0, dwTotalShares = 0;
PGPBoolean bNeedsFree = FALSE;
PGPByte* pPasskey = NULL;
PGPSize sizePasskey = 0;
char *pszPhraseKeyToSplit = NULL;
PGPByte* pPasskeyToSplit = NULL;
PGPSize sizePasskeyToSplit = 0;
PGPUInt32 numShares = 0;
PGPUInt16 i = 0;
/* should probably modify this structure */
SHAREHOLDERSTRUCT *pshs = NULL;
err = PGPOpenDefaultKeyRings(context, kPGPKeyRingOpenFlags_Mutable, &workingset);
if(IsPGPError(err))
return err;
mainbPtr->workingRingSet = workingset;
/* setup share structure */
err = pgpParseShares(mainbPtr, &pshs, ppszUsers, myArgc, &dwThreshold, &dwTotalShares, &numShares);
if(IsPGPError(err))
{
fprintf(filebPtr->pgpout,
LANG("Error: parameter error!\n"));
goto done;
}
err = pgpGetMatchingKeySet( mainbPtr, pszKeyToSplit, 0, &keyset);
if(IsPGPError(err))
goto done;
err = PGPOrderKeySet( keyset, kPGPUserIDOrdering, &keylist );
pgpAssertNoErr(err);
err = PGPNewKeyIter( keylist, &keyiter );
pgpAssertNoErr(err);
err = PGPKeyIterRewind( keyiter );
pgpAssertNoErr(err);
err = PGPKeyIterNext( keyiter, &keyToSplit);
/*if error, no keys found.*/
if(IsntPGPError(err) && keyToSplit != kPGPInvalidRef)
{
PGPBoolean bIsSecret = FALSE;
/* check to see if key is secret key */
err = PGPGetKeyBoolean(keyToSplit, kPGPKeyPropIsSecret, &bIsSecret);
pgpAssertNoErr(err);
if(!bIsSecret)
{
fprintf(filebPtr->pgpout,
LANG("Error, cannot split public key!\n"));
err = kPGPError_BadParams;
goto done;
}
/* check to see if key has already been split */
err = PGPGetKeyBoolean(keyToSplit, kPGPKeyPropIsSecretShared, &bIsSecret);
pgpAssertNoErr(err);
if(bIsSecret)
{
fprintf(filebPtr->pgpout,
LANG("Error, key has already been split!\n"));
err = kPGPError_BadParams;
goto done;
}
err = pgpGetValidPassphrase( mainbPtr, keyToSplit, &pszPassphrase, &bNeedsFree );
if(IsPGPError(err))
{
err = kPGPError_UserAbort;
goto done;
}
/* get keyid and alg of key to split */
PGPGetKeyIDFromKey(keyToSplit, &keyidToSplit);
PGPGetKeyNumber(keyToSplit, kPGPKeyPropAlgID, &keyalgToSplit);
/* need to allow user to specify the number of shares required
to decrypt/sign with, default to total number of shares */
// create the shares
err = PGPCreateShares (context, keyToSplit,
dwThreshold, dwTotalShares, &shares);
if(IsPGPError(err))
{
fprintf(filebPtr->pgpout,
LANG("Error splitting key!\n"));
goto done;
}
/* get the passkey from the shares */
err = PGPGetPasskeyFromShares (shares, &pPasskey, &sizePasskey);
if(IsPGPError(err))
{
fprintf(filebPtr->pgpout,
LANG("Error splitting key!\n"));
goto done;
}
for(i = 0; i < numShares; i++)
{
if(!pshs[i].bPublicKey)
{
err = pgpPassphraseDialogCmdline(mainbPtr, TRUE,
"Enter passphrase: ", &pshs[i].pszPassphrase);
}
err = sSaveSharesToFile (&pshs[i], context, shares, workingset,
argsbPtr->outputFileName ? argsbPtr->outputFileName : ".");
if(IsPGPError(err))
{
fprintf(filebPtr->pgpout,
LANG("Error splitting key!\n"));
goto done;
}
}
err = sChangeKeyPhrase (context, workingset, keyToSplit,
pszPassphrase[0] == '\0' ? NULL : pszPassphrase,
pPasskeyToSplit, sizePasskeyToSplit,
pPasskey, sizePasskey);
if(IsntPGPError(err) && PGPKeySetNeedsCommit(workingset))
{
PGPCommitKeyRingChanges(workingset);
}
}
else
{
fprintf(filebPtr->pgpout,
LANG("Unable to find specified key to split!\n"));
err = kPGPError_BadParams;
}
done:
if(pshs != NULL)
free(pshs);
if(shares != kPGPInvalidRef)
PGPFreeShares(shares);
if(keyiter != kPGPInvalidRef)
PGPFreeKeyIter(keyiter);
if(keylist != kPGPInvalidRef)
PGPFreeKeyList(keylist);
if(keyset != kPGPInvalidRef)
PGPFreeKeySet(keyset);
if(workingset != kPGPInvalidRef)
{
PGPFreeKeySet(workingset);
mainbPtr->workingRingSet = kPGPInvalidRef;
}
return err;
}
/* Code taken from PGPKeys
* _______________________________________________
*
* split the key
*/
static PGPError
sSaveSharesToFile (
PSHAREHOLDERSTRUCT pshs,
PGPContextRef context,
PGPShareRef sharesTotal,
PGPKeySetRef keyset,
char *pszFolder)
{
PFLFileSpecRef filespec = NULL;
PGPShareFileRef sharefile = NULL;
PGPShareRef sharesHolder = NULL;
PGPOptionListRef encodeOptions = NULL;
PGPError err = kPGPError_NoErr;
int iModifier = 0;
char szPath[MAX_PATH];
char szModifier[MAX_SHARES_LEN+1];
char sz1[32];
char sz2[kPGPMaxUserIDSize + 32];
PGPKeyRef key;
// create file name and filespec
err = sCreateFilePathFromUserName (pszFolder, pshs->szUserID,
pshs->uShares, "", szPath, sizeof(szPath));
if (IsPGPError (err)) goto SaveFileCleanup;
// check for pre-existence of file
while (!_access (szPath, 0)) {
iModifier++;
if (iModifier > MAX_SHARES) {
err = kPGPError_CantOpenFile;
goto SaveFileCleanup;
}
sprintf (szModifier, " %i", iModifier);
err = sCreateFilePathFromUserName (pszFolder, pshs->szUserID,
pshs->uShares, szModifier, szPath, sizeof(szPath));
if (IsPGPError (err)) goto SaveFileCleanup;
}
err = PFLNewFileSpecFromFullPath (PGPGetContextMemoryMgr (context),
szPath, &filespec);
if (IsPGPError (err)) goto SaveFileCleanup;
err = PFLFileSpecCreate (filespec);
if (IsPGPError (err)) goto SaveFileCleanup;
err = PGPNewShareFile (filespec, &sharefile);
if (IsPGPError (err)) goto SaveFileCleanup;
err = PGPSetShareFileUserID (sharefile, pshs->szUserID);
if (IsPGPError (err)) goto SaveFileCleanup;
err = PGPSplitShares (sharesTotal, pshs->uShares, &sharesHolder);
if (IsPGPError (err)) goto SaveFileCleanup;
// if this shareholder has public key, use it
if (pshs->bPublicKey) {
err = PGPSetShareFileOwnerKeyID (sharefile, pshs->keyid);
if (IsPGPError (err)) goto SaveFileCleanup;
err = PGPGetKeyByKeyID (keyset, &(pshs->keyid), pshs->keyalg, &key);
if(IsPGPError(err)) goto SaveFileCleanup;
err = PGPBuildOptionList (context, &encodeOptions,
PGPOEncryptToKey (context, key),
PGPOLastOption (context));
if (IsPGPError (err)) goto SaveFileCleanup;
}
// there is no public key for this shareholder
else {
err = PGPBuildOptionList (context, &encodeOptions,
PGPOConventionalEncrypt (context,
PGPOPassphrase (context, pshs->pszPassphrase),
PGPOLastOption (context)),
PGPOLastOption (context));
if (IsPGPError (err)) goto SaveFileCleanup;
}
err = PGPCopySharesToFile (context, sharefile,
encodeOptions, sharesHolder);
if (IsPGPError (err)) goto SaveFileCleanup;
err = PGPSaveShareFile (sharefile);
SaveFileCleanup:
if (encodeOptions != NULL)
PGPFreeOptionList (encodeOptions);
if (sharesHolder != NULL)
PGPFreeShares (sharesHolder);
if (sharefile != NULL)
PGPFreeShareFile (sharefile);
if (filespec != NULL)
PFLFreeFileSpec (filespec);
return err;
}
/* Code taken from PGPKeys
* ___________________________________________________
*
* Change passphrase of key and all subkeys
*/
static PGPError
sChangeKeyPhrase (
PGPContextRef context,
PGPKeySetRef keyset,
PGPKeyRef key,
char *szOld,
PGPByte* pPasskeyOld,
PGPSize sizePasskeyOld,
PGPByte* pPasskey,
PGPSize sizePasskey)
{
PGPUInt32 u;
PGPKeyListRef keylist;
PGPKeyIterRef keyiter;
PGPSubKeyRef subkey;
PGPError err;
if (szOld) {
err = PGPChangePassphrase (key,
PGPOPassphrase (context, szOld),
PGPOPasskeyBuffer (context, pPasskey, sizePasskey),
PGPOLastOption (context));
}
else if (sizePasskeyOld > 0) {
err = PGPChangePassphrase (key,
PGPOPasskeyBuffer (context, pPasskeyOld, sizePasskeyOld),
PGPOPasskeyBuffer (context, pPasskey, sizePasskey),
PGPOLastOption (context));
}
else {
err = PGPChangePassphrase (key,
PGPOPassphrase (context, ""),
PGPOPasskeyBuffer (context, pPasskey, sizePasskey),
PGPOLastOption (context));
}
if (IsPGPError (err)) return err;
PGPGetKeyNumber (key, kPGPKeyPropAlgID, &u);
switch (u) {
case kPGPPublicKeyAlgorithm_RSA :
break;
case kPGPPublicKeyAlgorithm_DSA :
PGPOrderKeySet (keyset, kPGPAnyOrdering, &keylist);
PGPNewKeyIter (keylist, &keyiter);
PGPKeyIterSeek (keyiter, key);
PGPKeyIterNextSubKey (keyiter, &subkey);
while (subkey) {
if (szOld) {
err = PGPChangeSubKeyPassphrase (subkey,
PGPOPassphrase (context, szOld),
PGPOPasskeyBuffer (context, pPasskey, sizePasskey),
PGPOLastOption (context));
}
else if (sizePasskeyOld > 0) {
err = PGPChangeSubKeyPassphrase (subkey,
PGPOPasskeyBuffer (context,
pPasskeyOld, sizePasskeyOld),
PGPOPasskeyBuffer (context, pPasskey, sizePasskey),
PGPOLastOption (context));
}
else {
err = PGPChangeSubKeyPassphrase (subkey,
PGPOPassphrase (context, ""),
PGPOPasskeyBuffer (context, pPasskey, sizePasskey),
PGPOLastOption (context));
}
PGPKeyIterNextSubKey (keyiter, &subkey);
}
PGPFreeKeyIter (keyiter);
PGPFreeKeyList (keylist);
break;
default :
break;
}
return err;
}
static PGPError
sCreateFilePathFromUserName (
char *pszFolder,
char *pszUserID,
PGPUInt16 uNumShares,
char *pszModifier,
char *pszPath,
PGPInt16 iLen)
{
char sz[kPGPMaxUserIDSize];
char szDefName[16];
char szDefExt[8];
char szShares[16];
PGPInt16 iMinRequiredLen;
PGPInt16 i;
/* prepare number of shares substring */
if (uNumShares == 1) {
sprintf(szShares, "1 Share");
}
else {
sprintf(szShares, "%i Shares", uNumShares);
}
/* get default file name and extension */
sprintf(szDefName, "User");
strcat (szDefName, pszModifier);
sprintf(szDefExt, "shf");
/* check length of destination buffer */
iMinRequiredLen =
strlen (pszFolder) + strlen (szDefExt) + strlen (szDefName) +1;
if (iMinRequiredLen >= iLen)
return kPGPError_CantOpenFile;
/* put folder into path */
/* need to make sure to support path specifiers for all platforms */
strcpy (pszPath, pszFolder);
iLen -= strlen (pszPath);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -