コード例 #1
0
ファイル: Encryption.cpp プロジェクト: Fox-Heracles/TodoList
bool CEncryption::Decrypt(const unsigned char* pInput, int nLenInput, const char* szPassword,
						 unsigned char*& pOutput, int& nLenOutput)
{
	bool			bResult = false;
	TD_TLHEADER		hdr;
	RD_UINT8		uFinalKey[32];
	sha256_ctx		sha32;


	ASSERT(NULL != pInput);						if(NULL == pInput)					return FALSE;
	ASSERT(0	!= nLenInput);					if(0	== nLenInput)				return FALSE;
	ASSERT(NULL != szPassword);					if(NULL == szPassword)				return FALSE;
	ASSERT(sizeof(TD_TLHEADER) <= nLenInput);	if(sizeof(TD_TLHEADER) > nLenInput) return FALSE; 

	// Extract header structure from memory file
	memcpy(&hdr, pInput, sizeof(TD_TLHEADER));

	// Hash the header
	sha256_begin(&sha32);
	sha256_hash((unsigned char *)&hdr + 32, sizeof(TD_TLHEADER) - 32, &sha32);
	sha256_end((unsigned char *)uFinalKey, &sha32);

	// Check if hash of header is the same as stored hash
	// to verify integrity of header
	if(0 == memcmp(hdr.aHeaderHash, uFinalKey, 32))
	{
		// Check if we can open this
		if((hdr.dwSignature1 == TD_TLSIG_1) && (hdr.dwSignature2 == TD_TLSIG_2))
		{
			// Allocate enough memory
			pOutput = new unsigned char[nLenInput];
			if(NULL != pOutput)
			{
				unsigned long uKeyLen = strlen(szPassword);

				// Create MasterKey by hashing szPassword
				ASSERT(0 != uKeyLen);
				if(0 != uKeyLen)
				{
					sha256_begin(&sha32);
					sha256_hash((unsigned char *)szPassword, uKeyLen, &sha32);
					sha256_end(m_pMasterKey, &sha32);

					m_dwKeyEncRounds = hdr.dwKeyEncRounds;

					// Generate m_pTransformedMasterKey from m_pMasterKey
					if(TRUE == _TransformMasterKey(hdr.aMasterSeed2))
					{
						// 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);

						bResult = true;
					}
				}
			}
		}
	}

	if (bResult)
	{
		bResult = false;

		Rijndael aes;
		// Initialize Rijndael/AES
		if(RIJNDAEL_SUCCESS == aes.init(Rijndael::CBC, Rijndael::Decrypt, uFinalKey,
			Rijndael::Key32Bytes, hdr.aEncryptionIV) )
		{
			nLenOutput = aes.padDecrypt((RD_UINT8 *)pInput + sizeof(TD_TLHEADER), nLenInput - sizeof(TD_TLHEADER), (RD_UINT8 *)pOutput);

			// Check if all went correct
			ASSERT(0 <= nLenOutput);
			if(0 <= nLenOutput)
			{
				// Check contents correct (with high probability)
				sha256_begin(&sha32);
				sha256_hash((unsigned char *)pOutput, nLenOutput, &sha32);
				sha256_end((unsigned char *)uFinalKey, &sha32);
				if(0 == memcmp(hdr.aContentsHash, uFinalKey, 32))
				{
					bResult = true; // data decrypted successfully
				}
			}
		}
	}

	if (!bResult)
	{
		SAFE_DELETE_ARRAY(pOutput);
	}

	return (bResult);
}
コード例 #2
0
ファイル: Encryption.cpp プロジェクト: Fox-Heracles/TodoList
bool CEncryption::Encrypt(const unsigned char* pInput, int nLenInput, const char* szPassword, 
						 unsigned char*& pOutput, int& nLenOutput)
{
	bool			bResult = false;
	TD_TLHEADER		hdr;
	RD_UINT8		uFinalKey[32];
	unsigned long	uFileSize = 0, uAllocated = 0, pos = 0;
	int				nEncryptedPartSize = 0;

	ASSERT(NULL != pInput);		if(NULL == pInput)		return FALSE;
	ASSERT(0	!= nLenInput);	if(0	== nLenInput)	return FALSE;
	ASSERT(NULL != szPassword); if(NULL == szPassword)	return FALSE;

	uFileSize = nLenInput + sizeof(TD_TLHEADER);

	// Allocate enough memory
	uAllocated = uFileSize + 16;
	pOutput = new unsigned char[uAllocated];
	if(NULL != pOutput)
	{
		unsigned long uKeyLen;

		// Build header structure
		hdr.dwSignature1 = TD_TLSIG_1;
		hdr.dwSignature2 = TD_TLSIG_2;
		hdr.dwKeyEncRounds = m_dwKeyEncRounds;

		// Make up the master key hash seed and the encryption IV
		m_random.GetRandomBuffer(hdr.aMasterSeed, 16);
		m_random.GetRandomBuffer((BYTE *)hdr.aEncryptionIV, 16);
		m_random.GetRandomBuffer(hdr.aMasterSeed2, 32);

		// Create MasterKey by hashing szPassword
		uKeyLen = strlen(szPassword);
		ASSERT(0 != uKeyLen);
		if(0 != uKeyLen)
		{
			sha256_ctx sha32;

			sha256_begin(&sha32);
			sha256_hash((unsigned char *)szPassword, uKeyLen, &sha32);
			sha256_end(m_pMasterKey, &sha32);

			// Generate m_pTransformedMasterKey from m_pMasterKey
			if(TRUE == _TransformMasterKey(hdr.aMasterSeed2))
			{
				// 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);

				// Hash the tasklist contents
				sha256_begin(&sha32);
				sha256_hash((unsigned char *)pInput, nLenInput, &sha32);
				sha256_end((unsigned char *)hdr.aContentsHash, &sha32);

				// Hash the header
				sha256_begin(&sha32);
				sha256_hash((unsigned char *)&hdr + 32, sizeof(TD_TLHEADER) - 32, &sha32);
				sha256_end((unsigned char *)hdr.aHeaderHash, &sha32);
				
				bResult = true;
			}
		}
	}

	if (bResult)
	{
		bResult = false;
		
		// Now we have all to build up the header
		memcpy(pOutput, &hdr, sizeof(TD_TLHEADER));
	
		Rijndael aes;
		// Initialize Rijndael/AES
		if(RIJNDAEL_SUCCESS == aes.init(Rijndael::CBC, Rijndael::Encrypt, uFinalKey,
			Rijndael::Key32Bytes, hdr.aEncryptionIV) )
		{
			nEncryptedPartSize = aes.padEncrypt((RD_UINT8 *)pInput, nLenInput, (RD_UINT8 *)pOutput + sizeof(TD_TLHEADER));

			// Check if all went correct
			ASSERT(0 <= nEncryptedPartSize);
			if(0 <= nEncryptedPartSize)
			{
				bResult = true; // data encrypted successfully
			}

			nLenOutput = sizeof(TD_TLHEADER) + nEncryptedPartSize;
		}
	}

	if (!bResult)
	{
		SAFE_DELETE_ARRAY(pOutput);
	}

	return (bResult);
}
コード例 #3
0
// If bIgnoreCorrupted is TRUE the manager will try to ignore all database file
// errors, i.e. try to read as much as possible instead of breaking out at the
// first error.
// To open a file normally, set bIgnoreCorrupted to FALSE (default).
// To open a file in rescue mode, set it to TRUE.
int CPwManager::OpenDatabase(const TCHAR *pszFile, _Out_opt_ PWDB_REPAIR_INFO *pRepair)
{
	char *pVirtualFile;
	unsigned long uFileSize, uAllocated, uEncryptedPartSize;
	unsigned long pos;
	PW_DBHEADER hdr;
	sha256_ctx sha32;
	UINT8 uFinalKey[32];
	char *p;
	USHORT usFieldType;
	DWORD dwFieldSize;
	PW_GROUP pwGroupTemplate;
	PW_ENTRY pwEntryTemplate;

	BOOST_STATIC_ASSERT(sizeof(char) == 1);

	ASSERT(pszFile != NULL); if(pszFile == NULL) return PWE_INVALID_PARAM;
	ASSERT(pszFile[0] != 0); if(pszFile[0] == 0) return PWE_INVALID_PARAM; // Length != 0

	RESET_PWG_TEMPLATE(&pwGroupTemplate);
	RESET_PWE_TEMPLATE(&pwEntryTemplate);

	if(pRepair != NULL) { ZeroMemory(pRepair, sizeof(PWDB_REPAIR_INFO)); }

	FILE *fp = NULL;
	_tfopen_s(&fp, pszFile, _T("rb"));
	if(fp == NULL) return PWE_NOFILEACCESS_READ;

	// Get file size
	fseek(fp, 0, SEEK_END);
	uFileSize = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	if(uFileSize < sizeof(PW_DBHEADER))
		{ fclose(fp); return PWE_INVALID_FILEHEADER; }

	// Allocate enough memory to hold the complete file
	uAllocated = uFileSize + 16 + 1 + 64 + 4; // 16 = encryption buffer space, 1+64 = string terminating NULLs, 4 unused
	pVirtualFile = new char[uAllocated];
	if(pVirtualFile == NULL) { fclose(fp); return PWE_NO_MEM; }
	memset(&pVirtualFile[uFileSize + 16], 0, 1 + 64);

	fread(pVirtualFile, 1, uFileSize, fp);
	fclose(fp);

	// Extract header structure from memory file
	memcpy(&hdr, pVirtualFile, sizeof(PW_DBHEADER));

	// Check if it's a KDBX file created by KeePass 2.x
	if((hdr.dwSignature1 == PWM_DBSIG_1_KDBX_P) && (hdr.dwSignature2 == PWM_DBSIG_2_KDBX_P))
		{ _OPENDB_FAIL_LIGHT; return PWE_UNSUPPORTED_KDBX; }
	if((hdr.dwSignature1 == PWM_DBSIG_1_KDBX_R) && (hdr.dwSignature2 == PWM_DBSIG_2_KDBX_R))
		{ _OPENDB_FAIL_LIGHT; return PWE_UNSUPPORTED_KDBX; }

	// Check if we can open this
	if((hdr.dwSignature1 != PWM_DBSIG_1) || (hdr.dwSignature2 != PWM_DBSIG_2))
		{ _OPENDB_FAIL_LIGHT; return PWE_INVALID_FILESIGNATURE; }

	if((hdr.dwVersion & 0xFFFFFF00) != (PWM_DBVER_DW & 0xFFFFFF00))
	{
		if((hdr.dwVersion == 0x00020000) || (hdr.dwVersion == 0x00020001) || (hdr.dwVersion == 0x00020002))
		{
			if(pVirtualFile != NULL)
			{
				mem_erase((unsigned char *)pVirtualFile, uAllocated);
				SAFE_DELETE_ARRAY(pVirtualFile);
			}

			return ((CPwCompatImpl::OpenDatabaseV2(this, pszFile) != FALSE) ?
				PWE_SUCCESS : PWE_UNKNOWN);
		}
		else if(hdr.dwVersion <= 0x00010002)
		{
			if(pVirtualFile != NULL)
			{
				mem_erase((unsigned char *)pVirtualFile, uAllocated);
				SAFE_DELETE_ARRAY(pVirtualFile);
			}
			
			return ((CPwCompatImpl::OpenDatabaseV1(this, pszFile) != FALSE) ?
				PWE_SUCCESS : PWE_UNKNOWN);
		}
		else { ASSERT(FALSE); _OPENDB_FAIL; }
	}

	if(hdr.dwGroups == 0) { _OPENDB_FAIL_LIGHT; return PWE_DB_EMPTY; }

	// Select algorithm
	if((hdr.dwFlags & PWM_FLAG_RIJNDAEL) != 0) m_nAlgorithm = ALGO_AES;
	else if((hdr.dwFlags & PWM_FLAG_TWOFISH) != 0) m_nAlgorithm = ALGO_TWOFISH;
	else { ASSERT(FALSE); _OPENDB_FAIL; }

	m_dwKeyEncRounds = hdr.dwKeyEncRounds;

	// Generate m_pTransformedMasterKey from m_pMasterKey
	if(_TransformMasterKey(hdr.aMasterSeed2) == FALSE) { ASSERT(FALSE); _OPENDB_FAIL; }

	ProtectTransformedMasterKey(false);

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

	ProtectTransformedMasterKey(true);

	if(pRepair == NULL)
	{
		// ASSERT(((uFileSize - sizeof(PW_DBHEADER)) % 16) == 0);
		if(((uFileSize - sizeof(PW_DBHEADER)) % 16) != 0)
		{
			_OPENDB_FAIL_LIGHT;
			return PWE_INVALID_FILESIZE;
		}
	}
	else // Repair the database
	{
		if(((uFileSize - sizeof(PW_DBHEADER)) % 16) != 0)
		{
			uFileSize -= sizeof(PW_DBHEADER); ASSERT((uFileSize & 0xF) != 0);
			uFileSize &= ~0xFUL;
			uFileSize += sizeof(PW_DBHEADER);
		}

		ASSERT(((uFileSize - sizeof(PW_DBHEADER)) % 16) == 0);

		pRepair->dwOriginalGroupCount = hdr.dwGroups;
		pRepair->dwOriginalEntryCount = hdr.dwEntries;
	}

	if(m_nAlgorithm == ALGO_AES)
	{
		CRijndael aes;

		// Initialize Rijndael algorithm
		if(aes.Init(CRijndael::CBC, CRijndael::DecryptDir, uFinalKey,
			CRijndael::Key32Bytes, hdr.aEncryptionIV) != RIJNDAEL_SUCCESS)
			{ _OPENDB_FAIL_LIGHT; return PWE_CRYPT_ERROR; }

		// Decrypt! The first bytes aren't encrypted (that's the header)
		uEncryptedPartSize = (unsigned long)aes.PadDecrypt((UINT8 *)pVirtualFile + sizeof(PW_DBHEADER),
			uFileSize - sizeof(PW_DBHEADER), (UINT8 *)pVirtualFile + sizeof(PW_DBHEADER));
	}
	else if(m_nAlgorithm == ALGO_TWOFISH)
	{
		CTwofish twofish;

		if(twofish.Init(uFinalKey, 32, hdr.aEncryptionIV) != true)
			{ _OPENDB_FAIL };

		uEncryptedPartSize = (unsigned long)twofish.PadDecrypt((UINT8 *)pVirtualFile + sizeof(PW_DBHEADER),
			uFileSize - sizeof(PW_DBHEADER), (UINT8 *)pVirtualFile + sizeof(PW_DBHEADER));
	}