pwmanager.cpp

来自「一款密码保险箱源码」· C++ 代码 · 共 2,201 行 · 第 1/5 页

CPP
2,201
字号
	pos = sizeof(PW_DBHEADER);

	BYTE *pb;

	// Store all groups to memory file
	for(i = 0; i < m_dwNumGroups; i++)
	{
		usFieldType = 0x0001; dwFieldSize = 4;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		memcpy(&pVirtualFile[pos], &m_pGroups[i].uGroupId, 4); pos += 4;

		pb = _StringToUTF8(m_pGroups[i].pszGroupName);
		usFieldType = 0x0002; dwFieldSize = szlen((char *)pb) + 1;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		ASSERT((pb != NULL) && (szlen((char *)pb) == (dwFieldSize - 1)) && ((pos + dwFieldSize) <= uAllocated));
		szcpy(&pVirtualFile[pos], (char *)pb); pos += dwFieldSize;
		SAFE_DELETE_ARRAY(pb);

		usFieldType = 0x0003; dwFieldSize = 5;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		PwTimeToTime(&m_pGroups[i].tCreation, aCompressedTime);
		memcpy(&pVirtualFile[pos], aCompressedTime, 5); pos += 5;

		usFieldType = 0x0004; dwFieldSize = 5;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		PwTimeToTime(&m_pGroups[i].tLastMod, aCompressedTime);
		memcpy(&pVirtualFile[pos], aCompressedTime, 5); pos += 5;

		usFieldType = 0x0005; dwFieldSize = 5;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		PwTimeToTime(&m_pGroups[i].tLastAccess, aCompressedTime);
		memcpy(&pVirtualFile[pos], aCompressedTime, 5); pos += 5;

		usFieldType = 0x0006; dwFieldSize = 5;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		PwTimeToTime(&m_pGroups[i].tExpire, aCompressedTime);
		memcpy(&pVirtualFile[pos], aCompressedTime, 5); pos += 5;

		usFieldType = 0x0007; dwFieldSize = 4;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		memcpy(&pVirtualFile[pos], &m_pGroups[i].uImageId, 4); pos += 4;

		usFieldType = 0x0008; dwFieldSize = 2;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		memcpy(&pVirtualFile[pos], &m_pGroups[i].usLevel, 2); pos += 2;

		usFieldType = 0x0009; dwFieldSize = 4;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		memcpy(&pVirtualFile[pos], &m_pGroups[i].dwFlags, 4); pos += 4;

		usFieldType = 0xFFFF; dwFieldSize = 0;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
	}

	// Store all entries to memory file
	for(i = 0; i < m_dwNumEntries; i++)
	{
		UnlockEntryPassword(&m_pEntries[i]);

		usFieldType = 0x0001; dwFieldSize = 16;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		memcpy(&pVirtualFile[pos], &m_pEntries[i].uuid, 16); pos += 16;

		usFieldType = 0x0002; dwFieldSize = 4;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		memcpy(&pVirtualFile[pos], &m_pEntries[i].uGroupId, 4); pos += 4;

		usFieldType = 0x0003; dwFieldSize = 4;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		memcpy(&pVirtualFile[pos], &m_pEntries[i].uImageId, 4); pos += 4;

		pb = _StringToUTF8(m_pEntries[i].pszTitle);
		usFieldType = 0x0004;
		dwFieldSize = szlen((char *)pb) + 1; // Add terminating NULL character space
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		ASSERT((pb != NULL) && (szlen((char *)pb) == (dwFieldSize - 1)) && ((pos + dwFieldSize) <= uAllocated));
		szcpy(&pVirtualFile[pos], (char *)pb); pos += dwFieldSize;
		SAFE_DELETE_ARRAY(pb);

		pb = _StringToUTF8(m_pEntries[i].pszURL);
		usFieldType = 0x0005;
		dwFieldSize = szlen((char *)pb) + 1; // Add terminating NULL character space
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		ASSERT((pb != NULL) && (szlen((char *)pb) == (dwFieldSize - 1)) && ((pos + dwFieldSize) <= uAllocated));
		szcpy(&pVirtualFile[pos], (char *)pb); pos += dwFieldSize;
		SAFE_DELETE_ARRAY(pb);

		pb = _StringToUTF8(m_pEntries[i].pszUserName);
		usFieldType = 0x0006;
		dwFieldSize = szlen((char *)pb) + 1; // Add terminating NULL character space
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		ASSERT((pb != NULL) && (szlen((char *)pb) == (dwFieldSize - 1)) && ((pos + dwFieldSize) <= uAllocated));
		szcpy(&pVirtualFile[pos], (char *)pb); pos += dwFieldSize;
		SAFE_DELETE_ARRAY(pb);

		pb = _StringToUTF8(m_pEntries[i].pszPassword);
		usFieldType = 0x0007;
		dwFieldSize = szlen((char *)pb) + 1; // Add terminating NULL character space
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		ASSERT((pb != NULL) && (szlen((char *)pb) == (dwFieldSize - 1)) && ((pos + dwFieldSize) <= uAllocated));
		szcpy(&pVirtualFile[pos], (char *)pb); pos += dwFieldSize;
		if(pb != NULL) mem_erase((unsigned char *)pb, szlen((char *)pb));
		SAFE_DELETE_ARRAY(pb);

		pb = _StringToUTF8(m_pEntries[i].pszAdditional);
		usFieldType = 0x0008;
		dwFieldSize = szlen((char *)pb) + 1; // Add terminating NULL character space
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		ASSERT((pb != NULL) && (szlen((char *)pb) == (dwFieldSize - 1)) && ((pos + dwFieldSize) <= uAllocated));
		szcpy(&pVirtualFile[pos], (char *)pb); pos += dwFieldSize;
		SAFE_DELETE_ARRAY(pb);

		usFieldType = 0x0009; dwFieldSize = 5;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		PwTimeToTime(&m_pEntries[i].tCreation, aCompressedTime);
		memcpy(&pVirtualFile[pos], aCompressedTime, 5); pos += 5;

		usFieldType = 0x000A; dwFieldSize = 5;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		PwTimeToTime(&m_pEntries[i].tLastMod, aCompressedTime);
		memcpy(&pVirtualFile[pos], aCompressedTime, 5); pos += 5;

		usFieldType = 0x000B; dwFieldSize = 5;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		PwTimeToTime(&m_pEntries[i].tLastAccess, aCompressedTime);
		memcpy(&pVirtualFile[pos], aCompressedTime, 5); pos += 5;

		usFieldType = 0x000C; dwFieldSize = 5;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		PwTimeToTime(&m_pEntries[i].tExpire, aCompressedTime);
		memcpy(&pVirtualFile[pos], aCompressedTime, 5); pos += 5;

		pb = _StringToUTF8(m_pEntries[i].pszBinaryDesc);
		usFieldType = 0x000D;
		dwFieldSize = szlen((char *)pb) + 1;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		ASSERT((pb != NULL) && (szlen((char *)pb) == (dwFieldSize - 1)) && ((pos + dwFieldSize) <= uAllocated));
		szcpy(&pVirtualFile[pos], (char *)pb); pos += dwFieldSize;
		SAFE_DELETE_ARRAY(pb);

		usFieldType = 0x000E; dwFieldSize = m_pEntries[i].uBinaryDataLen;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;
		if((m_pEntries[i].pBinaryData != NULL) && (dwFieldSize != 0))
			memcpy(&pVirtualFile[pos], m_pEntries[i].pBinaryData, dwFieldSize);
		pos += dwFieldSize;

		usFieldType = 0xFFFF; dwFieldSize = 0;
		memcpy(&pVirtualFile[pos], &usFieldType, 2); pos += 2;
		memcpy(&pVirtualFile[pos], &dwFieldSize, 4); pos += 4;

		LockEntryPassword(&m_pEntries[i]);
	}
	ASSERT((pos <= uFileSize) && ((pos + 33) > uAllocated));

	sha256_begin(&sha32);
	sha256_hash((unsigned char *)pVirtualFile + sizeof(PW_DBHEADER), pos - sizeof(PW_DBHEADER), &sha32);
	sha256_end((unsigned char *)hdr.aContentsHash, &sha32);

	// Now we have everything required to build up the header
	memcpy(pVirtualFile, &hdr, sizeof(PW_DBHEADER));

	// Generate m_pTransformedMasterKey from m_pMasterKey
	if(_TransformMasterKey(hdr.aMasterSeed2) == FALSE)
		{ ASSERT(FALSE); SAFE_DELETE_ARRAY(pVirtualFile); _LoadAndRemoveAllMetaStreams(false); return PWE_CRYPT_ERROR; }

	// Hash the master password with the generated hash salt
	sha256_begin(&sha32);
	sha256_hash(hdr.aMasterSeed, 16, &sha32);
	sha256_hash(m_pTransformedMasterKey, 32, &sha32);
	sha256_end((unsigned char *)uFinalKey, &sha32);

#if 0
	// For debugging purposes, a file containing the plain text is created.
	// This code of course must not be compiled into the final binary.
#pragma message("PLAIN TEXT OUTPUT IS ENABLED!")
#pragma message("DO NOT DISTRIBUTE THIS BINARY!")
	// std::basic_string<TCHAR> tstrClear = pszFile;
	// tstrClear += _T(".plaintext.bin");
	// FILE *fpClear = NULL;
	// _tfopen_s(&fpClear, tstrClear.c_str(), _T("wb"));
	// fwrite(pVirtualFile, 1, uFileSize, fpClear);
	// fclose(fpClear); fpClear = NULL;
#endif

	if(m_nAlgorithm == ALGO_AES)
	{
		CRijndael aes;

		// Initialize Rijndael/AES
		if(aes.Init(CRijndael::CBC, CRijndael::EncryptDir, uFinalKey,
			CRijndael::Key32Bytes, hdr.aEncryptionIV) != RIJNDAEL_SUCCESS)
		{
			SAFE_DELETE_ARRAY(pVirtualFile);
			return PWE_CRYPT_ERROR;
		}

		uEncryptedPartSize = (unsigned long)aes.PadEncrypt((UINT8 *)pVirtualFile +
			sizeof(PW_DBHEADER), pos - sizeof(PW_DBHEADER), (UINT8 *)pVirtualFile +
			sizeof(PW_DBHEADER));
	}
	else if(m_nAlgorithm == ALGO_TWOFISH)
	{
		CTwofish twofish;

		if(twofish.Init(uFinalKey, 32, hdr.aEncryptionIV) == false)
		{
			SAFE_DELETE_ARRAY(pVirtualFile);
			_LoadAndRemoveAllMetaStreams(false);
			return PWE_CRYPT_ERROR;
		}

		uEncryptedPartSize = (unsigned long)twofish.PadEncrypt(
			(UINT8 *)pVirtualFile + sizeof(PW_DBHEADER),
			pos - sizeof(PW_DBHEADER), (UINT8 *)pVirtualFile + sizeof(PW_DBHEADER));
	}
	else
	{
		ASSERT(FALSE);
		_OPENDB_FAIL_LIGHT;
		_LoadAndRemoveAllMetaStreams(false);
		return PWE_INVALID_PARAM;
	}

	// Check if all went correct
	ASSERT((uEncryptedPartSize % 16) == 0);
	if((uEncryptedPartSize > 2147483446) || ((uEncryptedPartSize == 0) &&
		(GetNumberOfGroups() != 0)))
	{
		ASSERT(FALSE);
		SAFE_DELETE_ARRAY(pVirtualFile);
		_LoadAndRemoveAllMetaStreams(false);
		return PWE_CRYPT_ERROR;
	}

	fp = NULL;
	_tfopen_s(&fp, pszFile, _T("wb"));
	if(fp == NULL)
	{
		mem_erase((unsigned char *)pVirtualFile, uAllocated);
		SAFE_DELETE_ARRAY(pVirtualFile);
		_LoadAndRemoveAllMetaStreams(false);
		return PWE_NOFILEACCESS_WRITE;
	}

	// Write memory file to disk
	if(fwrite(pVirtualFile, 1, uEncryptedPartSize + sizeof(PW_DBHEADER), fp) !=
		uEncryptedPartSize + sizeof(PW_DBHEADER))
	{
		mem_erase((unsigned char *)pVirtualFile, uAllocated);
		SAFE_DELETE_ARRAY(pVirtualFile);
		_LoadAndRemoveAllMetaStreams(false);
		return PWE_FILEERROR_WRITE;
	}

	// Close file, erase and delete memory
	fclose(fp); fp = NULL;

	memcpy(&m_dbLastHeader, &hdr, sizeof(PW_DBHEADER));

	mem_erase((unsigned char *)pVirtualFile, uAllocated);
	SAFE_DELETE_ARRAY(pVirtualFile);
	_LoadAndRemoveAllMetaStreams(false);

	return PWE_SUCCESS;
}

DWORD CPwManager::Find(const TCHAR *pszFindString, BOOL bCaseSensitive, DWORD fieldFlags, DWORD nStart)
{
	DWORD i;
	CString strFind;
	CString strEntry;

	if(nStart >= (int)m_dwNumEntries) return DWORD_MAX;
	ASSERT(pszFindString != NULL); if(pszFindString == NULL) return DWORD_MAX;

	strFind = pszFindString;
	if(bCaseSensitive == FALSE) strFind.MakeLower();

	if((strFind.GetLength() == 0) || (strFind == _T("*"))) return nStart;

	for(i = nStart; i < (int)m_dwNumEntries; i++)
	{
		if(fieldFlags & PWMF_TITLE)
		{
			strEntry = m_pEntries[i].pszTitle;
			if(bCaseSensitive == FALSE) strEntry.MakeLower();

			if(strEntry.Find(strFind) != -1) return i;
		}
		if(fieldFlags & PWMF_USER)
		{
			strEntry = m_pEntries[i].pszUserName;
			if(bCaseSensitive == FALSE) strEntry.MakeLower();

			if(strEntry.Find(strFind) != -1) return i;
		}
		if(fieldFlags & PWMF_URL)
		{
			strEntry = m_pEntries[i].pszURL;
			if(bCaseSensitive == FALSE) strEntry.MakeLower();

			if(strEntry.Find(strFind) != -1) return i;
		}
		if(fieldFlags & PWMF_PASSWORD)
		{
			UnlockEntryPassword(&m_pEntries[i]);
			strEntry = m_pEntries[i].pszPassword;
			LockEntryPassword(&m_pEntries[i]);
			if(bCaseSensitive == FALSE) strEntry.MakeLower();

			if(strEntry.Find(strFind) != -1) return i;
		}
		if(fieldFlags & PWMF_ADDITIONAL)
		{
			strEntry = m_pEntries[i].pszAdditional;
			if(bCaseSensitive == FALSE) strEntry.MakeLower();

			if(strEntry.Find(strFind) != -1) return i;
		}
		if(fieldFlags & PWMF_GROUPNAME)
		{
			DWORD dwGroupIndex = GetGroupByIdN(m_pEntries[i].uGroupId);
			ASSERT(dwGroupIndex != DWORD_MAX);
			strEntry = GetGroup(dwGroupIndex)->pszGroupName;
			if(bCaseSensitive == FALSE) strEntry.MakeLower();

			if(strEntry.Find(strFind) != -1) return i;
		}
	}

	return DWORD_MAX;
}

void CPwManager::MoveInternal(DWORD dwFrom, DWORD dwTo)
{
	LONG i, dir;
	PW_ENTRY pe;

	if(dwFrom == dwTo) return; // Nothing to do
	if(dwFrom >= m_dwNumEntries) return; // Invalid index
	if(dwTo >= m_dwNumEntries) return; // Invalid index

	// Set moving direction
	if(dwFrom < dwTo) dir = 1;
	else dir = -1;

	i = (LONG)dwFrom;
	while(1)
	{
		if(i == (LONG)dwTo) break;

		pe = m_pEntries[i];
		m_pEntries[i] = m_pEntries[i+dir];
		m_pEntries[i+dir] = pe;

		i += dir;
	}
}

BOOL CPwManager::MoveGroup(DWORD dwFrom, DWORD dwTo)
{
	LONG i, dir;
	PW_GROUP pg;

	ASSERT((dwFrom != DWORD_MAX) && (dwTo != DWORD_MAX));

	if(dwFrom == dwTo) return TRUE;
	if(dwFrom >= m_dwNumGroups) return FALSE;
	if(dwTo >= m_dwNumGroups) return FALSE;

	// Set moving direction
	if(dwFrom < dwTo) dir = 1;
	else dir = -1;

	i = (LONG)dwFrom;

	while(1)
	{
		if(i == (LONG)dwTo) break;

		pg = m_pGroups[i];
		m_pGroups[i] = m_pGroups[i+dir];
		m_pGroups[i+dir] = pg;

		i += dir;
	}

	FixGroupTree();

	return TRUE;
}

void CPwManager::MoveInGroup(DWORD idGroup, DWORD dwFrom, DWORD dwTo)
{
	if((dwFrom >= m_dwNumEntries) || (dwFrom == DWORD_MAX)) return;
	if((dwTo >= m_dwNumEntries) || (dwTo == DWORD_MAX)) return;
	if(dwFrom == dwTo) return;

	DWORD dwFromEx = GetEntryByGroupN(idGroup, dwFrom);
	DWORD dwToEx = GetEntryByGroupN(idGroup, dwTo);

	if((dwFromEx == DWORD_MAX) || (dwToEx == DWORD_MAX)) return;

	MoveInternal(dwFromEx, dwToEx);
}

BOOL CPwManager::GetGroupTree(DWORD idGroup, DWORD *pGroupIndexes) const
{
	DWORD i, dwGroupPos;
	USHORT usLevel;

	ASSERT(pGroupIndexes != NULL); if(pGroupIndexes == NULL) return FALSE;

	dwGroupPos = GetGroupByIdN(idGroup);
	ASSERT(dwGroupPos != DWORD_MAX); if(dwGroupPos == DWORD_MAX) return FALSE;

	i = dwGroupPos;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?