📄 cpgpdiskuser.cpp
字号:
{
CString userName;
GetUserName(userName);
tempUser.Create(newCipher, userName, passphrase, IsReadOnly());
tempUser.SetIsAdminUser(IsAdminUser());
}
Assign(tempUser);
}
void
CPGPdiskUser::ChangePassphrase(const char *newPassphrase)
{
pgpAssert(IsAssigned());
pgpAssertStrValid(newPassphrase);
if (!IsCipheringEnabled() || !HasSymmetricKey())
THROW_PGPERROR(kPGPError_BadParams);
mPCipher->EncryptPassphraseKey(newPassphrase,
GetAsUserWithSym()->keyInfo);
}
void
CPGPdiskUser::Create(
const CCipherContext& cipher,
const CPGPKey& pubKey,
PGPBoolean readOnly,
PGPBoolean isLocked)
{
pgpAssert(cipher.IsInitialized());
// Encrypt decypted key using the private key of the public key.
CPGPKey subKey;
if (!pubKey.GetKeyForUsage(subKey))
THROW_PGPERROR(kPGPError_PublicKeyUnimplemented);
Crypto::CheckBytes checkBytes;
CSecureArray<PGPByte> encryptedKey;
PGPUInt32 encryptedKeySize;
EncryptUsingPublicKey(subKey, cipher, encryptedKey, encryptedKeySize,
checkBytes);
// Get key IDs.
CPGPKeyID keyID;
pubKey.GetKeyID(keyID);
CPGPKeyID subKeyID;
subKey.GetKeyID(subKeyID);
// Import the key.
ImportRawPublicKey(keyID, subKeyID, encryptedKey.Get(),
encryptedKeySize, checkBytes, readOnly, isLocked);
}
void
CPGPdiskUser::Create(
const CCipherContext& cipher,
const char *userName,
const char *passphrase,
PGPBoolean readOnly)
{
pgpAssertStrValid(userName);
pgpAssertStrValid(passphrase);
// Initialize key info structure with session key.
Crypto::PassphraseKeyInfo keyInfo;
cipher.EncryptPassphraseKey(passphrase, keyInfo);
// Import symmetric key.
ImportRawSymmetricKey(keyInfo, userName, readOnly);
}
void
CPGPdiskUser::Import(const void *buf, PGPUInt32 size)
{
pgpAssertAddrValid(buf, VoidAlign);
if (size < sizeof(OnDiskUserInfo))
THROW_PGPERROR(kPGPError_BadParams);
Clear();
// First get header.
mUserBytes.Resize(sizeof(OnDiskUserInfo));
pgpCopyMemory(buf, mUserBytes.Get(), sizeof(OnDiskUserInfo));
// Validate header.
if (GetAsUserInfo()->userMagic != OnDiskUserInfo::kUserMagic)
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
if (!HasPublicKey() && !HasSymmetricKey())
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
PGPUInt32 userSize = GetAsUserInfo()->userSize;
if (userSize > OnDiskUserInfo::kMaxBytesDiskUser)
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
// Copy in entire user.
mUserBytes.Resize(userSize);
pgpCopyMemory(buf, mUserBytes.Get(), userSize);
if (HasPublicKey())
{
if (GetAsUserWithPub()->encryptedKeyOffset +
GetAsUserWithPub()->encryptedKeySize > userSize)
{
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
}
if (GetAsUserWithPub()->encryptedKeyOffset <
sizeof(OnDiskUserWithPub))
{
// beta header with no subkey ID
mUserBytes.Resize(sizeof(OnDiskUserWithPub) +
GetAsUserWithPub()->encryptedKeySize);
pgpCopyMemory(
mUserBytes.Get() +
GetAsUserWithPub()->encryptedKeyOffset,
mUserBytes.Get() +
sizeof(OnDiskUserWithPub),
GetAsUserWithPub()->encryptedKeySize);
GetAsUserWithPub()->encryptedKeyOffset =
sizeof(OnDiskUserWithPub);
GetAsUserInfo()->userSize =
GetAsUserWithPub()->encryptedKeyOffset +
GetAsUserWithPub()->encryptedKeySize;
GetAsUserWithPub()->subKeyID =
GetAsUserWithPub()->keyID;
pgpClearMemory(GetAsUserWithPub()->checkBytes.bytes,
sizeof(GetAsUserWithPub()->checkBytes.bytes));
}
mKeyID = GetAsUserWithPub()->keyID;
mSubKeyID = GetAsUserWithPub()->subKeyID;
}
mIsAssigned = TRUE;
}
void
CPGPdiskUser::Export(void *buf, PGPUInt32 availSize) const
{
pgpAssert(IsAssigned());
pgpAssertAddrValid(buf, VoidAlign);
if (availSize < GetSizeForExport())
THROW_PGPERROR(kPGPError_BufferTooSmall);
pgpCopyMemory(mUserBytes.Get(), buf, GetSizeForExport());
}
void
CPGPdiskUser::ImportRawSymmetricKey(
const Crypto::PassphraseKeyInfo& keyInfo,
const char *userName,
PGPBoolean readOnly)
{
pgpAssertStrValid(userName);
Clear();
// Allocate on disk user bytes.
PGPUInt32 onDiskSize = sizeof(OnDiskUserWithSym);
mUserBytes.Resize(onDiskSize);
mUserBytes.Wipe();
// Initialize fields.
GetAsUserInfo()->userMagic = OnDiskUserInfo::kUserMagic;
GetAsUserInfo()->userType = OnDiskUserInfo::kUserWithSymType;
GetAsUserInfo()->userSize = onDiskSize;
GetAsUserInfo()->readOnly = readOnly;
GetAsUserInfo()->locked = FALSE;
GetAsUserWithSym()->keyInfo = keyInfo;
UString::SmartStringCopy(GetAsUserWithSym()->userName, userName,
kPGPdiskMaxUserNameSize);
mIsAssigned = TRUE;
}
void
CPGPdiskUser::ImportRawPublicKey(
const PGPKeyID& keyID,
const PGPKeyID& subKeyID,
const PGPByte *pEncryptedKey,
PGPUInt32 lengthEncKey,
const Crypto::CheckBytes& checkBytes,
PGPBoolean readOnly,
PGPBoolean locked)
{
pgpAssertAddrValid(pEncryptedKey, PGPByte);
Clear();
// Allocate on disk user bytes.
PGPUInt32 onDiskSize = sizeof(OnDiskUserWithPub) + lengthEncKey;
mUserBytes.Resize(onDiskSize);
mUserBytes.Wipe();
// Initialize fields.
GetAsUserInfo()->userMagic = OnDiskUserInfo::kUserMagic;
GetAsUserInfo()->userType = OnDiskUserInfo::kUserWithPubType;
GetAsUserInfo()->userSize = onDiskSize;
GetAsUserInfo()->readOnly = readOnly;
GetAsUserInfo()->locked = locked;
GetAsUserWithPub()->keyID = keyID;
GetAsUserWithPub()->subKeyID = subKeyID;
GetAsUserWithPub()->encryptedKeyOffset = sizeof(OnDiskUserWithPub);
GetAsUserWithPub()->encryptedKeySize = lengthEncKey;
GetAsUserWithPub()->checkBytes = checkBytes;
PGPByte *pData = mUserBytes.Get() +
GetAsUserWithPub()->encryptedKeyOffset;
pgpCopyMemory(pEncryptedKey, pData, lengthEncKey);
mKeyID = keyID;
mSubKeyID = subKeyID;
mIsAssigned = TRUE;
}
void
CPGPdiskUser::ImportRawPublicKey(
const PGPByte *pKeyID,
PGPSize lengthKeyID,
const PGPByte *pEncryptedKey,
PGPSize lengthEncKey,
const Crypto::CheckBytes& checkBytes,
PGPPublicKeyAlgorithm pubAlgorithm,
PGPBoolean readOnly,
PGPBoolean locked)
{
pgpAssertAddrValid(pKeyID, PGPByte);
pgpAssertAddrValid(pEncryptedKey, PGPByte);
Clear();
// This overload means we are being given old-style key ID. Convert it.
PGPByte *pRealKeyID = const_cast<PGPByte *>(pKeyID);
PGPSize realLength = lengthKeyID;
if ((realLength == 5) || (realLength == 9))
{
realLength--;
pRealKeyID++;
}
CPGPKeyID keyID;
keyID.SetKeyIDFromBytes(pRealKeyID, realLength, pubAlgorithm);
ImportRawPublicKey(keyID, keyID, pEncryptedKey, lengthEncKey,
checkBytes, readOnly, locked);
}
void
CPGPdiskUser::Assign(const CPGPdiskUser& user)
{
if (&user == this)
return;
pgpAssert(user.IsAssigned());
Clear();
mPContext = user.mPContext;
CArray<PGPUInt8> exportedUser(user.GetSizeForExport());
user.Export(exportedUser.Get(), exportedUser.Size());
Import(exportedUser.Get(), exportedUser.Size());
}
void
CPGPdiskUser::Clear()
{
if (IsAssigned() && IsCipheringEnabled())
DisableCiphering();
mUserBytes.Wipe();
mPGPKeyPresent = FALSE;
mIsAssigned = FALSE;
}
void
CPGPdiskUser::Init()
{
mPContext = NULL;
mPCipher = NULL;
mCipheringEnabled = FALSE;
mIsAssigned = FALSE;
mPGPKeyPresent = FALSE;
}
void
CPGPdiskUser::SetIsAdminUser(PGPBoolean isAdminUser)
{
pgpAssert(IsAssigned());
GetAsUserInfo()->adminUser = isAdminUser;
}
void
CPGPdiskUser::ImportPublicKey() const
{
pgpAssert(mIsAssigned);
// Get actual key.
try
{
mPGPKey.FindKeyByKeyID(Context()->PGPKeyDB(), mKeyID);
mPGPSubKey.FindKeyByKeyID(Context()->PGPKeyDB(), mSubKeyID);
mPGPKeyPresent = TRUE;
}
catch (CComboError&)
{
mPGPKeyPresent = FALSE;
}
}
void
CPGPdiskUser::VerifyPubKeyCheckBytes(
const void *compareMainData,
const void *compareData,
const Crypto::CheckBytes& checkBytes,
const CCipherContext& cipher) const
{
pgpAssertAddrValid(compareData, VoidAlign);
pgpAssert(cipher.IsInitialized());
CArray<PGPUInt8> encBuf(cipher.GetEncryptSize());
encBuf.Wipe();
// if checkbytes are zero, ignore
if (pgpMemoryEqual(checkBytes.bytes, encBuf.Get(),
pgpMin(encBuf.Size(), sizeof(checkBytes.bytes))))
{
return;
}
cipher.Encrypt(compareData, encBuf.Get());
if (!pgpMemoryEqual(checkBytes.bytes, encBuf.Get(),
pgpMin(encBuf.Size(), sizeof(checkBytes.bytes))))
{
// This second try is for 6.5x PGPdisks that compare
// their checkbytes against the fingerprint of the
// master key for some odd reason -wjb
encBuf.Wipe();
cipher.Encrypt(compareMainData, encBuf.Get());
if (!pgpMemoryEqual(checkBytes.bytes, encBuf.Get(),
pgpMin(encBuf.Size(), sizeof(checkBytes.bytes))))
{
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
}
}
}
void
CPGPdiskUser::GeneratePubKeyCheckBytes(
const void *compareData,
const CCipherContext& cipher,
Crypto::CheckBytes& checkBytes) const
{
pgpAssertAddrValid(compareData, VoidAlign);
pgpAssert(cipher.IsInitialized());
CArray<PGPByte> encBuf(cipher.GetEncryptSize());
encBuf.Wipe();
cipher.Encrypt(compareData, encBuf.Get());
pgpClearMemory(checkBytes.bytes, sizeof(checkBytes.bytes));
pgpCopyMemory(encBuf.Get(), checkBytes.bytes, pgpMin(encBuf.Size(),
sizeof(checkBytes.bytes)));
}
void
CPGPdiskUser::DecryptUsingPublicKey(
const CPGPKey& pubMainKey,
const CPGPKey& pubKey,
const char *passphrase,
int passkeylen,
const PGPByte *pEncryptedData,
PGPSize encryptedDataSize,
const Crypto::PassphraseSalt& salt,
const Crypto::CheckBytes& checkBytes,
CCipherContext& cipher) const
{
pgpAssertAddrValid(pEncryptedData, VoidAlign);
pgpAssert(cipher.IsInitialized());
// Initialize private key context.
CPGPPrivateKeyContext privContext(pubKey, passphrase, passkeylen);
// Get operation sizes.
PGPSize maxDecryptedBufferSize, maxEncryptedBufferSize, maxSignatureSize;
privContext.GetPrivateKeyOperationSizes(maxDecryptedBufferSize,
maxEncryptedBufferSize, maxSignatureSize);
// Get key properties.
CArray<PGPByte> fingerPrint(128);
PGPSize fingerPrintSize;
fingerPrint.Wipe();
pubKey.GetDataProp(kPGPKeyProperty_Fingerprint, fingerPrint.Get(),
fingerPrint.Size(), fingerPrintSize);
// Get Main key properties.
CArray<PGPByte> mainFingerPrint(128);
PGPSize mainFingerPrintSize;
mainFingerPrint.Wipe();
pubMainKey.GetDataProp(kPGPKeyProperty_Fingerprint, mainFingerPrint.Get(),
mainFingerPrint.Size(), mainFingerPrintSize);
// Decrypt the session key.
CSecureArray<PGPByte> decKeyData;
PGPUInt32 decryptedDataSize;
decKeyData.Resize(maxDecryptedBufferSize);
privContext.PrivateKeyDecrypt(pEncryptedData, encryptedDataSize,
decKeyData.Get(), decryptedDataSize);
// Check the result.
if (decryptedDataSize > cipher.GetKeySize())
THROW_PGPERROR(kPGPClientError_CorruptDiskHeader);
CSecureObject<Crypto::SymmetricKey> pDecryptedKey;
pgpCopyMemory(decKeyData.Get(), pDecryptedKey->bytes, decryptedDataSize);
// Initialize cipher context.
cipher.AttachSymmetricKey(*pDecryptedKey, salt);
// Check check bytes.
VerifyPubKeyCheckBytes(mainFingerPrint.Get(),
fingerPrint.Get(), checkBytes, cipher);
}
void
CPGPdiskUser::EncryptUsingPublicKey(
const CPGPKey& pubKey,
const CCipherContext& cipher,
CSecureArray<PGPByte>& encryptedKey,
PGPUInt32& encryptedKeySize,
Crypto::CheckBytes& checkBytes) const
{
// Initialize public key context.
CPGPPublicKeyContext pubContext(pubKey);
// Get operation sizes.
PGPSize maxDecryptedBufferSize, maxEncryptedBufferSize, maxSignatureSize;
pubContext.GetPublicKeyOperationSizes(maxDecryptedBufferSize,
maxEncryptedBufferSize, maxSignatureSize);
// Get fingerprint.
PGPByte fingerPrint[128];
PGPSize fingerPrintSize;
pgpClearMemory(fingerPrint, sizeof(fingerPrint));
pubKey.GetDataProp(kPGPKeyProperty_Fingerprint, fingerPrint,
sizeof(fingerPrint), fingerPrintSize);
// Get session key.
CSecureObject<Crypto::SymmetricKey> pDecryptedKey;
cipher.GetSymmetricKey(*pDecryptedKey);
// Encrypt the session key.
pgpAssert(cipher.GetKeySize() < maxDecryptedBufferSize - 10);
encryptedKey.Resize(maxEncryptedBufferSize);
pubContext.PublicKeyEncrypt(pDecryptedKey, cipher.GetKeySize(),
encryptedKey.Get(), encryptedKeySize);
// Compute the check bytes.
GeneratePubKeyCheckBytes(fingerPrint, cipher, checkBytes);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -