📄 pgpdiskpublickeyutils.cpp
字号:
if (derr.IsntError())
{
derr = InsertPGPdiskHeaderInList(itemList,
(PGPdiskFileHeaderInfo *) pubKeyHdr);
}
// Write out the updated headers to the PGPdisk.
if (derr.IsntError())
{
derr = UpdateHeaderItemList(&diskFile, itemList);
}
if (gotItemList)
FreeHeaderItemList(itemList);
if (gotAllKeys)
PGPFreeKeySet(allKeys);
if (diskFile.Opened())
diskFile.Close();
return derr;
}
////////////////////////////////////////////
// Public key encryption/decryption routines
////////////////////////////////////////////
// DecryptPublicKey decrypts data using a public/private key pair.
DualErr
DecryptPublicKey(
PGPKeyRef pubKey,
SecureString *passphrase,
const void *encryptedData,
PGPSize encryptedDataSize,
const CheckBytes *checkBytes,
CASTKey *decryptedKey)
{
CheckBytes decryptedCheckBytes;
DualErr derr;
ExpandedCASTKey *expandedKey;
PGPBoolean allocedDataBuf, gotPrivContext;
PGPByte *data, fingerPrint[128];
PGPPrivateKeyContextRef privContext;
PGPSize decryptedDataSize, fingerPrintSize;
PGPSize maxDecryptedBufferSize, maxEncryptedBufferSize;
PGPSize maxSignatureSize;
PGPUInt8 *secureBuf;
SecureMemory smExpandedKey(sizeof(ExpandedCASTKey));
SecureMemory smSecureBuf(kMaxPassphraseLength);
SecureMemory *pSmCASTKey;
allocedDataBuf = gotPrivContext = FALSE;
pgpAssert(PGPKeyRefIsValid(pubKey));
pgpAssertAddrValid(passphrase, SecureString);
pgpAssertAddrValid(encryptedData, VoidAlign);
pgpAssertAddrValid(checkBytes, checkBytes);
pgpAssertAddrValid(decryptedKey, CASTKey);
// Did we get our locked memory?
derr = smExpandedKey.mInitErr;
if (derr.IsntError())
{
derr = smSecureBuf.mInitErr;
}
if (derr.IsntError())
{
// Get locked memory pointer.
expandedKey = (ExpandedCASTKey *) smExpandedKey.GetPtr();
secureBuf = (PGPUInt8 *) smSecureBuf.GetPtr();
// Get passphrase string.
passphrase->GetString((LPSTR) secureBuf, kMaxStringSize);
// Get key context.
PGPContextRef context = PGPGetKeyContext(pubKey);
// Initialize private context.
derr = PGPNewPrivateKeyContext(pubKey,
kPGPPublicKeyMessageFormat_PGP, &privContext,
PGPOPassphrase(context, (LPCSTR) secureBuf),
PGPOLastOption(context));
gotPrivContext = derr.IsntError();
}
// Get operation sizes.
if (derr.IsntError())
{
derr = PGPGetPrivateKeyOperationSizes(privContext,
&maxDecryptedBufferSize, &maxEncryptedBufferSize,
&maxSignatureSize);
}
// Get key properties.
if (derr.IsntError())
{
pgpClearMemory(fingerPrint, sizeof(fingerPrint));
derr = PGPGetKeyPropertyBuffer(pubKey, kPGPKeyPropFingerprint,
sizeof(fingerPrint), fingerPrint, &fingerPrintSize);
}
// Get space for buffer.
if (derr.IsntError())
{
try
{
pSmCASTKey = new SecureMemory(maxDecryptedBufferSize);
data = (PGPUInt8 *) pSmCASTKey->GetPtr();
}
catch (CMemoryException *ex)
{
derr = DualErr(kPGDMinorError_OutOfMemory);
ex->Delete();
}
allocedDataBuf = derr.IsntError();
}
// Decrypt the data.
if (derr.IsntError())
{
derr = PGPPrivateKeyDecrypt(privContext, encryptedData,
encryptedDataSize, data, &decryptedDataSize);
}
// Check the result.
if (derr.IsntError())
{
if (decryptedDataSize == sizeof(CASTKey))
{
pgpCopyMemory(data, decryptedKey, sizeof(CASTKey));
// Decrypt the check bytes. We encrypted the first eight bytes of
// the fingerprint.
CAST5schedule(expandedKey->keyDWords, decryptedKey->keyBytes);
CAST5decrypt(&checkBytes->theBytes[0],
&decryptedCheckBytes.theBytes[0], expandedKey->keyDWords);
if (!pgpMemoryEqual(&decryptedCheckBytes, fingerPrint,
sizeof(decryptedCheckBytes)))
{
// Should never get here.
derr = DualErr(kPGDMinorError_InvalidParameter);
}
}
else
{
derr = DualErr(kPGDMinorError_InvalidParameter);
}
}
if (gotPrivContext)
PGPFreePrivateKeyContext(privContext);
if (allocedDataBuf)
delete pSmCASTKey;
return derr;
}
// EncryptPublicKey encrypts data using a public/private key pair.
DualErr
EncryptPublicKey(
const CASTKey *decryptedKey,
PGPKeyRef pubKey,
void **encryptedData,
PGPUInt32 *encryptedDataSize,
CheckBytes *checkBytes)
{
DualErr derr;
ExpandedCASTKey *expandedKey;
PGPBoolean allocedDataBuf, gotPubContext;
PGPByte *data, fingerPrint[128];
PGPPublicKeyContextRef pubContext;
PGPSize dataSize, fingerPrintSize, maxDecryptedBufferSize;
PGPSize maxEncryptedBufferSize, maxSignatureSize;
SecureMemory smExpandedKey(sizeof(ExpandedCASTKey));
allocedDataBuf = gotPubContext = FALSE;
pgpAssert(PGPKeyRefIsValid(pubKey));
pgpAssertAddrValid(encryptedData, VoidAlign);
pgpAssertAddrValid(checkBytes, checkBytes);
pgpAssertAddrValid(decryptedKey, CASTKey);
// Did we get our locked memory?
derr = smExpandedKey.mInitErr;
if (derr.IsntError())
{
// Get locked memory pointer.
expandedKey = (ExpandedCASTKey *) smExpandedKey.GetPtr();
// Initialize private GetGlobalPGPContext().
derr = PGPNewPublicKeyContext(pubKey,
kPGPPublicKeyMessageFormat_PGP, &pubContext);
gotPubContext = derr.IsntError();
}
// Get operation sizes.
if (derr.IsntError())
{
derr = PGPGetPublicKeyOperationSizes(pubContext,
&maxDecryptedBufferSize, &maxEncryptedBufferSize,
&maxSignatureSize);
}
// Get key properties.
if (derr.IsntError())
{
pgpClearMemory(fingerPrint, sizeof(fingerPrint));
derr = PGPGetKeyPropertyBuffer(pubKey, kPGPKeyPropFingerprint,
sizeof(fingerPrint), fingerPrint, &fingerPrintSize);
}
// Get space for buffer.
if (derr.IsntError())
{
try
{
data = new PGPByte[maxEncryptedBufferSize];
}
catch (CMemoryException *ex)
{
derr = DualErr(kPGDMinorError_OutOfMemory);
ex->Delete();
}
allocedDataBuf = derr.IsntError();
}
if (derr.IsntError())
{
// Compute the check bytes.
CAST5schedule(expandedKey->keyDWords, decryptedKey->keyBytes);
CAST5encrypt(fingerPrint, &checkBytes->theBytes[0],
expandedKey->keyDWords);
// Perform the encryption.
derr = PGPPublicKeyEncrypt(pubContext, decryptedKey,
sizeof(CASTKey), data, &dataSize);
}
if (derr.IsntError())
{
(* encryptedData) = data;
(* encryptedDataSize) = dataSize;
}
if (gotPubContext)
PGPFreePublicKeyContext(pubContext);
if (derr.IsError())
{
if (allocedDataBuf)
delete[] data;
}
return derr;
}
// GetDecryptedKeyUsingPublicKey decrypts an encrypted session key using info
// from a public key header.
DualErr
GetDecryptedKeyUsingPublicKey(
SecureString *passphrase,
PGPdiskPublicKeyHeader *pubKeyHdr,
CASTKey *decryptedKey)
{
DualErr derr;
PGPBoolean gotAllKeys = FALSE;
PGPByte *encryptedKey, *exportedKeyID;
PGPKeyID keyID;
PGPKeyRef pubKey;
PGPKeySetRef allKeys;
pgpAssertAddrValid(passphrase, SecureString);
pgpAssertAddrValid(pubKeyHdr, PGPdiskPublicKeyHeader);
pgpAssertAddrValid(decryptedKey, CASTKey);
// Load SDK prefs.
derr = PGPsdkLoadDefaultPrefs(GetGlobalPGPContext());
// Load default key ring.
if (derr.IsntError())
{
derr = PGPOpenDefaultKeyRings(GetGlobalPGPContext(), 0, &allKeys);
gotAllKeys = derr.IsntError();
}
// Import key ID.
if (derr.IsntError())
{
exportedKeyID = (PGPByte *) pubKeyHdr + pubKeyHdr->keyIDOffset;
derr = PGPImportKeyID(exportedKeyID, &keyID);
}
// Get actual key.
if (derr.IsntError())
{
derr = PGPGetKeyByKeyID(allKeys, &keyID, pubKeyHdr->algorithm,
&pubKey);
}
// Decrypt the encrypted session key.
if (derr.IsntError())
{
encryptedKey = (PGPByte *) pubKeyHdr + pubKeyHdr->encryptedKeyOffset;
derr = DecryptPublicKey(pubKey, passphrase, encryptedKey,
pubKeyHdr->encryptedKeySize, &pubKeyHdr->checkBytes,
decryptedKey);
}
if (gotAllKeys)
PGPFreeKeySet(allKeys);
return derr;
}
// FindPublicPGPdiskKeyHeader finds a PGPdisk public key header whose private
// key is unlocked by the specified passphrase.
DualErr
FindPublicPGPdiskKeyHeader(
LPCSTR path,
SecureString *passphrase,
PGPdiskPublicKeyHeader **pubKeyHdr)
{
DualErr derr;
PGPBoolean anyKeysNotInRing, foundKey, gotAllKeys;
PGPBoolean gotDiskKeys;
PGPKeyRef curKey;
PGPKeySetRef allKeys;
PGPRecipientSpec *diskRecipKeys;
PGPUInt8 *secureBuf;
PGPUInt32 i, numRecipKeys;
SecureMemory smSecureBuf(kMaxPassphraseLength);
anyKeysNotInRing = foundKey = gotAllKeys = gotDiskKeys = FALSE;
pgpAssertStrValid(path);
pgpAssertAddrValid(passphrase, SecureString);
pgpAssertAddrValid(pubKeyHdr, PGPdiskPublicKeyHeader *);
// Did we get our locked memory?
derr = smSecureBuf.mInitErr;
if (derr.IsntError())
{
// Get locked memory pointer.
secureBuf = (PGPUInt8 *) smSecureBuf.GetPtr();
// Get passphrase string.
passphrase->GetString((LPSTR) secureBuf, kMaxStringSize);
// Load SDK prefs.
derr = PGPsdkLoadDefaultPrefs(GetGlobalPGPContext());
}
// Load default key ring.
if (derr.IsntError())
{
derr = PGPOpenDefaultKeyRings(GetGlobalPGPContext(), 0, &allKeys);
gotAllKeys = derr.IsntError();
}
// Get list of keys from PGPdisk.
if (derr.IsntError())
{
derr = GetPGPdiskRecipKeys(path, allKeys, &diskRecipKeys,
&numRecipKeys);
gotDiskKeys = derr.IsntError();
}
// Find the key that corresponds to the passphrase.
if (derr.IsntError())
{
// For every recipient spec in the list...
for (i = 0; i < numRecipKeys; i++)
{
// ... if it has an associated key ref...
if (diskRecipKeys[i].type == kPGPRecipientSpecType_Key)
{
PGPBoolean canDecrypt = FALSE;
curKey = diskRecipKeys[i].u.key;
PGPGetKeyBoolean(curKey, kPGPKeyPropCanDecrypt, &canDecrypt);
//... and if the given passphrase unlocks it, we're done.
if (canDecrypt && PGPPassphraseIsValid(curKey,
PGPOPassphrase(GetGlobalPGPContext(), (LPCSTR) secureBuf),
PGPOLastOption(GetGlobalPGPContext())))
{
foundKey = TRUE;
break;
}
}
else
{
anyKeysNotInRing = TRUE;
}
}
}
// Get header associated with the key if one was found.
if (derr.IsntError())
{
if (foundKey)
{
derr = GetHeaderForPublicKey(path, curKey, pubKeyHdr);
}
else
{
if (anyKeysNotInRing)
derr = DualErr(kPGDMinorError_IncPassAndKeyNotInRing);
else
derr = DualErr(kPGDMinorError_IncorrectPassphrase);
}
}
if (gotDiskKeys)
FreeRecipientSpecList(diskRecipKeys, numRecipKeys);
if (gotAllKeys)
PGPFreeKeySet(allKeys);
return derr;
}
// CheckIfLockedKeysOnKeyring checks if all the PGPdisk's locked public keys
// are on the local keyring.
DualErr
CheckIfLockedKeysOnKeyring(LPCSTR path, PGPBoolean *pLockedKeysOnKeyring)
{
DualErr derr;
File diskFile;
PGPBoolean gotAllKeys, gotItemList;
PGPBoolean lockedKeysOnKeyring;
PGPByte *exportedKeyID;
PGPdiskFileHeaderItem *curItem, *itemList;
PGPKeyID keyID;
PGPKeyRef pubKey;
PGPKeySetRef allKeys;
gotAllKeys = gotItemList = FALSE;
lockedKeysOnKeyring = TRUE;
pgpAssertStrValid(path);
pgpAssertAddrValid(pLockedKeysOnKeyring, PGPBoolean);
// Open the PGPdisk.
if (derr.IsntError())
{
derr = diskFile.Open(path, kOF_MustExist | kOF_ReadOnly);
}
// Get list of headers.
if (derr.IsntError())
{
derr = GetHeaderItemList(&diskFile, &itemList);
gotItemList = derr.IsntError();
}
// Search for locked keys.
if (derr.IsntError())
{
curItem = itemList->next;
// Open default key rings.
derr = PGPOpenDefaultKeyRings(GetGlobalPGPContext(), 0, &allKeys);
gotAllKeys = derr.IsntError();
while (derr.IsntError() && IsntNull(curItem))
{
if (IsPublicKeyHeader(curItem->hdr))
{
PGPdiskPublicKeyHeader *pubKeyHdr;
pubKeyHdr = (PGPdiskPublicKeyHeader *) curItem->hdr;
// Is it locked?
if (pubKeyHdr->locked)
{
// Import key ID.
exportedKeyID = (PGPByte *) pubKeyHdr +
pubKeyHdr->keyIDOffset;
derr = PGPImportKeyID(exportedKeyID, &keyID);
// Get actual key.
if (derr.IsntError())
{
derr = PGPGetKeyByKeyID(allKeys, &keyID,
pubKeyHdr->algorithm, &pubKey);
// If failed, then bail.
if (derr.IsError())
{
derr = DualErr::NoError;
lockedKeysOnKeyring = FALSE;
break;
}
}
}
}
curItem = curItem->next;
}
}
(* pLockedKeysOnKeyring) = lockedKeysOnKeyring;
if (gotAllKeys)
PGPFreeKeySet(allKeys);
if (gotItemList)
FreeHeaderItemList(itemList);
if (diskFile.Opened())
diskFile.Close();
return derr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -