pwmanager.cpp
来自「一款密码保险箱源码」· C++ 代码 · 共 2,201 行 · 第 1/5 页
CPP
2,201 行
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2007 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "StdAfx.h"
#include "PwManager.h"
#include "Crypto/TwofishClass.h"
#include "Crypto/SHA2/SHA2.h"
#include "Crypto/ARCFour.h"
#include "Util/PwUtil.h"
#include "Util/MemUtil.h"
#include "Util/StrUtil.h"
#include "Util/TranslateEx.h"
static const BYTE g_uuidZero[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
static PW_TIME g_pwTimeNever = { 2999, 12, 28, 23, 59, 59 };
static char g_pNullString[4] = { 0, 0, 0, 0 };
CPwManager::CPwManager()
{
m_pEntries = NULL;
m_dwNumEntries = 0;
m_dwMaxEntries = 0;
m_pGroups = NULL;
m_dwNumGroups = 0;
m_dwMaxGroups = 0;
m_pLastEditedEntry = NULL;
m_nAlgorithm = ALGO_AES;
m_dwKeyEncRounds = PWM_STD_KEYENCROUNDS;
memset(m_pMasterKey, 0, 32);
_AllocGroups(PWM_NUM_INITIAL_GROUPS);
_AllocEntries(PWM_NUM_INITIAL_ENTRIES);
m_random.GetRandomBuffer(m_pSessionKey, PWM_SESSION_KEY_SIZE);
}
CPwManager::~CPwManager()
{
this->CleanUp();
}
void CPwManager::InitPrimaryInstance()
{
ASSERT((m_pLastEditedEntry == NULL) && (memcmp(m_pMasterKey, g_pNullString, 4) == 0));
ASSERT((m_nAlgorithm == ALGO_AES) && (m_dwKeyEncRounds == PWM_STD_KEYENCROUNDS));
DWORD dwInitXorShift[4];
m_random.GetRandomBuffer((BYTE *)&dwInitXorShift, 16);
srandXorShift(dwInitXorShift);
ASSERT(sizeof(BYTE) == 1);
}
void CPwManager::CleanUp()
{
_DeleteEntryList(TRUE);
m_dwNumEntries = 0;
m_dwMaxEntries = 0;
_DeleteGroupList(TRUE);
m_dwNumGroups = 0;
m_dwMaxGroups = 0;
m_pLastEditedEntry = NULL;
mem_erase(m_pMasterKey, 32);
}
int CPwManager::SetMasterKey(const TCHAR *pszMasterKey, BOOL bDiskDrive, const TCHAR *pszSecondKey, const CNewRandomInterface *pARI, BOOL bOverwrite)
{
size_t uKeyLen, uKeyLen2 = 0, uFileSize, uRead;
TCHAR szFile[2048];
sha256_ctx sha32;
char *paKey = NULL;
char *paKey2 = NULL;
unsigned char aFileKey[32];
unsigned char aPasswordKey[32];
BOOL bReadNormal;
ASSERT(pszMasterKey != NULL); if(pszMasterKey == NULL) return PWE_INVALID_PARAM;
#ifdef _UNICODE
ASSERT(sizeof(TCHAR) >= 2);
paKey = _StringToAnsi(pszMasterKey);
#else
ASSERT(sizeof(TCHAR) == 1);
size_t sizeANSIKeyBuffer = _tcslen(pszMasterKey) + 1;
paKey = new char[sizeANSIKeyBuffer];
ASSERT(paKey != NULL); if(paKey == NULL) return PWE_NO_MEM;
strcpy_s(paKey, sizeANSIKeyBuffer, pszMasterKey);
#endif
ASSERT(paKey != NULL); if(paKey == NULL) return PWE_NO_MEM;
if(pszSecondKey != NULL)
{
#ifdef _UNICODE
ASSERT(sizeof(TCHAR) >= 2);
paKey2 = _StringToAnsi(pszSecondKey);
#else
ASSERT(sizeof(TCHAR) == 1);
size_t sizeByteBuffer = _tcslen(pszSecondKey) + 1;
paKey2 = new char[sizeByteBuffer];
ASSERT(paKey2 != NULL); if(paKey2 == NULL) return PWE_NO_MEM;
strcpy_s(paKey2, sizeByteBuffer, pszSecondKey);
#endif
ASSERT(paKey2 != NULL); if(paKey2 == NULL) return PWE_NO_MEM;
uKeyLen2 = szlen(paKey2);
ASSERT(uKeyLen2 != 0);
}
uKeyLen = strlen(paKey);
ASSERT(uKeyLen != 0);
if(uKeyLen == 0) { SAFE_DELETE_ARRAY(paKey); return PWE_INVALID_KEY; }
if(bDiskDrive == FALSE)
{
sha256_begin(&sha32);
sha256_hash((unsigned char *)paKey, static_cast<unsigned long>(uKeyLen),
&sha32);
sha256_end((unsigned char *)m_pMasterKey, &sha32);
mem_erase((unsigned char *)paKey, uKeyLen);
SAFE_DELETE_ARRAY(paKey);
return PWE_SUCCESS;
}
else
{
if(pszSecondKey == NULL)
{
mem_erase((unsigned char *)paKey, uKeyLen);
SAFE_DELETE_ARRAY(paKey); // Don't need ASCII key any more from on now
_tcscpy_s(szFile, _countof(szFile), pszMasterKey);
if(szFile[_tcslen(szFile) - 1] == _T('\\'))
_tcscat_s(szFile, _countof(szFile), PWS_DEFAULT_KEY_FILENAME);
if(pARI == NULL) // If pARI is NULL: load key from disk
{
FILE *fp = NULL;
_tfopen_s(&fp, szFile, _T("rb"));
if(fp == NULL) return PWE_NOFILEACCESS_READ_KEY;
fseek(fp, 0, SEEK_END);
uFileSize = (unsigned long)ftell(fp);
fseek(fp, 0, SEEK_SET);
bReadNormal = TRUE;
if(uFileSize == 32)
{
if(fread(m_pMasterKey, 1, 32, fp) != 32)
{
fclose(fp); fp = NULL;
return PWE_FILEERROR_READ;
}
bReadNormal = FALSE;
}
else if(uFileSize == 64)
{
if(LoadHexKey32(fp, m_pMasterKey) == FALSE)
{
fseek(fp, 0, SEEK_SET);
}
else bReadNormal = FALSE;
}
if(bReadNormal == TRUE)
{
sha256_begin(&sha32);
while(1)
{
uRead = (unsigned long)fread((unsigned char *)szFile, 1, 2048, fp);
if(uRead == 0) break;
sha256_hash((unsigned char *)szFile,
static_cast<unsigned long>(uRead), &sha32);
if(uRead != 2048) break;
}
sha256_end((unsigned char *)m_pMasterKey, &sha32);
}
fclose(fp); fp = NULL;
return PWE_SUCCESS;
}
else // pARI is not NULL: save key to disk
{
FILE *fp = NULL;
unsigned char aRandomBytes[32];
_tfopen_s(&fp, szFile, _T("rb")); // Does the file exist already?
if((fp != NULL) && (bOverwrite == FALSE)) { fclose(fp); fp = NULL; return PWE_NOFILEACCESS_READ_KEY; }
if(fp != NULL) { fclose(fp); fp = NULL; } // We must close it before opening for write
if(pARI->GenerateRandomSequence(32, aRandomBytes) == FALSE) return PWE_INVALID_RANDOMSOURCE;
fp = NULL;
_tfopen_s(&fp, szFile, _T("wb"));
if(fp == NULL) return PWE_NOFILEACCESS_WRITE;
if(SaveHexKey32(fp, aRandomBytes) == FALSE) { fclose(fp); fp = NULL; return PWE_FILEERROR_WRITE; }
fclose(fp); fp = NULL;
memcpy(m_pMasterKey, aRandomBytes, 32);
return PWE_SUCCESS;
}
}
else // pszSecondKey != NULL
{
mem_erase((unsigned char *)paKey, uKeyLen);
SAFE_DELETE_ARRAY(paKey); // Don't need ASCII key any more from on now
_tcscpy_s(szFile, _countof(szFile), pszMasterKey);
if(szFile[_tcslen(szFile) - 1] == _T('\\'))
_tcscat_s(szFile, _countof(szFile), PWS_DEFAULT_KEY_FILENAME);
if(pARI == NULL) // If pARI is NULL: load key from disk
{
FILE *fp = NULL;
_tfopen_s(&fp, szFile, _T("rb"));
if(fp == NULL) return PWE_NOFILEACCESS_READ_KEY;
fseek(fp, 0, SEEK_END);
uFileSize = (unsigned long)ftell(fp);
fseek(fp, 0, SEEK_SET);
bReadNormal = TRUE;
if(uFileSize == 32)
{
if(fread(aFileKey, 1, 32, fp) != 32)
{
fclose(fp); fp = NULL;
return PWE_FILEERROR_READ;
}
bReadNormal = FALSE;
}
else if(uFileSize == 64)
{
if(LoadHexKey32(fp, aFileKey) == FALSE)
{
fseek(fp, 0, SEEK_SET);
}
else bReadNormal = FALSE;
}
if(bReadNormal == TRUE)
{
sha256_begin(&sha32);
while(1)
{
uRead = (unsigned long)fread((unsigned char *)szFile, 1, 2048, fp);
if(uRead == 0) break;
sha256_hash((unsigned char *)szFile,
static_cast<unsigned long>(uRead), &sha32);
if(uRead != 2048) break;
}
sha256_end((unsigned char *)aFileKey, &sha32);
}
fclose(fp); fp = NULL;
sha256_begin(&sha32);
sha256_hash((unsigned char *)paKey2,
static_cast<unsigned long>(uKeyLen2), &sha32);
sha256_end((unsigned char *)aPasswordKey, &sha32);
mem_erase((unsigned char *)paKey2, uKeyLen2);
SAFE_DELETE_ARRAY(paKey);
sha256_begin(&sha32);
sha256_hash(aPasswordKey, 32, &sha32);
sha256_hash(aFileKey, 32, &sha32);
sha256_end((unsigned char *)m_pMasterKey, &sha32);
mem_erase((unsigned char *)aPasswordKey, 32);
mem_erase((unsigned char *)aFileKey, 32);
return PWE_SUCCESS;
}
else // pARI is not NULL: save key to disk
{
FILE *fp = NULL;
unsigned char aRandomBytes[32];
_tfopen_s(&fp, szFile, _T("rb")); // Does the file exist already?
if((fp != NULL) && (bOverwrite == FALSE)) { fclose(fp); fp = NULL; return PWE_NOFILEACCESS_READ_KEY; }
if(fp != NULL) { fclose(fp); fp = NULL; } // We must close it before opening for write
if(pARI->GenerateRandomSequence(32, aRandomBytes) == FALSE) return PWE_INVALID_RANDOMSOURCE;
_tfopen_s(&fp, szFile, _T("wb"));
if(fp == NULL) return PWE_NOFILEACCESS_WRITE;
if(SaveHexKey32(fp, aRandomBytes) == FALSE) { fclose(fp); fp = NULL; return PWE_FILEERROR_WRITE; }
fclose(fp); fp = NULL;
ASSERT(uKeyLen2 != 0);
sha256_begin(&sha32);
sha256_hash((unsigned char *)paKey2,
static_cast<unsigned long>(uKeyLen2), &sha32);
sha256_end((unsigned char *)aPasswordKey, &sha32);
mem_erase((unsigned char *)paKey2, uKeyLen2);
SAFE_DELETE_ARRAY(paKey);
sha256_begin(&sha32);
sha256_hash(aPasswordKey, 32, &sha32);
sha256_hash(aRandomBytes, 32, &sha32);
sha256_end((unsigned char *)m_pMasterKey, &sha32);
mem_erase((unsigned char *)aPasswordKey, 32);
mem_erase((unsigned char *)aFileKey, 32);
return PWE_SUCCESS;
}
}
}
// return PWE_UNKNOWN; // Unreachable anyway
}
BOOL CPwManager::SetAlgorithm(int nAlgorithm)
{
ASSERT((nAlgorithm == ALGO_AES) || (nAlgorithm == ALGO_TWOFISH));
if((nAlgorithm != ALGO_AES) && (nAlgorithm != ALGO_TWOFISH)) return FALSE;
m_nAlgorithm = nAlgorithm;
return TRUE;
}
int CPwManager::GetAlgorithm()
{
return m_nAlgorithm;
}
void CPwManager::_AllocEntries(DWORD uEntries)
{
PW_ENTRY *p;
DWORD dwEntries;
ASSERT((uEntries != 0) && (uEntries != DWORD_MAX));
if(uEntries == 0) return;
dwEntries = m_dwNumEntries;
// If we already have allocated enough entries just return
if(uEntries <= m_dwMaxEntries) return;
p = new PW_ENTRY[uEntries];
if(p == NULL) { ASSERT(FALSE); return; }
memset(p, 0, sizeof(PW_ENTRY) * uEntries);
if((m_dwNumEntries > 0) && (m_pEntries != NULL))
{
memcpy(p, m_pEntries, sizeof(PW_ENTRY) * m_dwNumEntries);
_DeleteEntryList(FALSE);
}
m_dwNumEntries = dwEntries;
m_dwMaxEntries = uEntries;
m_pEntries = p;
}
void CPwManager::_AllocGroups(DWORD uGroups)
{
PW_GROUP *p;
DWORD dwGroups;
ASSERT((uGroups != 0) && (uGroups != DWORD_MAX));
if((uGroups == 0) || (uGroups == DWORD_MAX)) return;
dwGroups = m_dwNumGroups;
// If we already have allocated enough entries just return
if(uGroups <= m_dwMaxGroups) return;
p = new PW_GROUP[uGroups];
if(p == NULL) { ASSERT(FALSE); return; }
memset(p, 0, sizeof(PW_GROUP) * uGroups);
if((m_dwNumGroups > 0) && (m_pGroups != NULL))
{
memcpy(p, m_pGroups, sizeof(PW_GROUP) * m_dwNumGroups);
_DeleteGroupList(FALSE);
}
m_dwNumGroups = dwGroups;
m_dwMaxGroups = uGroups;
m_pGroups = p;
}
void CPwManager::_DeleteEntryList(BOOL bFreeStrings)
{
unsigned long uCurrentEntry;
if(m_pEntries == NULL) return; // Nothing to delete
if(bFreeStrings == TRUE)
{
for(uCurrentEntry = 0; uCurrentEntry < m_dwNumEntries; uCurrentEntry++)
{
SAFE_DELETE_ARRAY(m_pEntries[uCurrentEntry].pszTitle);
SAFE_DELETE_ARRAY(m_pEntries[uCurrentEntry].pszURL);
SAFE_DELETE_ARRAY(m_pEntries[uCurrentEntry].pszUserName);
SAFE_DELETE_ARRAY(m_pEntries[uCurrentEntry].pszPassword);
SAFE_DELETE_ARRAY(m_pEntries[uCurrentEntry].pszAdditional);
SAFE_DELETE_ARRAY(m_pEntries[uCurrentEntry].pszBinaryDesc);
SAFE_DELETE_ARRAY(m_pEntries[uCurrentEntry].pBinaryData);
}
}
if(m_dwNumEntries != 0) // Erase ALL data
{
mem_erase((unsigned char *)m_pEntries,
sizeof(PW_ENTRY) * m_dwNumEntries);
}
SAFE_DELETE_ARRAY(m_pEntries);
m_dwNumEntries = 0;
m_dwMaxEntries = 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?