2004-02-15 04:47:32 +00:00
|
|
|
#include "global.h"
|
|
|
|
|
#include "CryptManager.h"
|
|
|
|
|
#include "RageUtil.h"
|
2004-02-15 05:45:18 +00:00
|
|
|
#include "RageLog.h"
|
2004-02-19 03:56:03 +00:00
|
|
|
#include "PrefsManager.h"
|
2004-02-20 02:28:23 +00:00
|
|
|
#include "RageFile.h"
|
2004-02-15 04:47:32 +00:00
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
#include "crypto/CryptRSA.h"
|
|
|
|
|
#include "crypto/CryptRand.h"
|
2004-02-22 02:15:34 +00:00
|
|
|
#include "crypto/CryptMD5.h"
|
2004-02-17 22:25:13 +00:00
|
|
|
|
2004-02-19 04:01:14 +00:00
|
|
|
static const CString PRIVATE_KEY_PATH = "Data/private.key.rsa";
|
|
|
|
|
static const CString PUBLIC_KEY_PATH = "Data/public.key.rsa";
|
2004-02-17 22:25:13 +00:00
|
|
|
static const int KEY_LENGTH = 1024;
|
|
|
|
|
|
|
|
|
|
CryptManager* CRYPTMAN = NULL; // global and accessable from anywhere in our program
|
|
|
|
|
|
2004-02-15 05:45:18 +00:00
|
|
|
CryptManager::CryptManager()
|
|
|
|
|
{
|
2004-02-20 02:28:23 +00:00
|
|
|
if( !PREFSMAN->m_bSignProfileData )
|
|
|
|
|
return;
|
|
|
|
|
|
2004-02-15 05:45:18 +00:00
|
|
|
//
|
|
|
|
|
// generate keys if none are available
|
|
|
|
|
//
|
2004-02-20 02:28:23 +00:00
|
|
|
if( !DoesFileExist(PRIVATE_KEY_PATH) || !DoesFileExist(PUBLIC_KEY_PATH) )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "Keys missing. Generating new keys" );
|
|
|
|
|
GenerateRSAKey( KEY_LENGTH, PRIVATE_KEY_PATH, PUBLIC_KEY_PATH, "aoksdjaksd" );
|
|
|
|
|
FlushDirCache();
|
|
|
|
|
}
|
2004-02-15 05:45:18 +00:00
|
|
|
}
|
2004-02-15 04:47:32 +00:00
|
|
|
|
2004-02-15 05:45:18 +00:00
|
|
|
CryptManager::~CryptManager()
|
|
|
|
|
{
|
2004-02-15 04:47:32 +00:00
|
|
|
|
2004-02-15 05:45:18 +00:00
|
|
|
}
|
2004-02-15 04:47:32 +00:00
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
void CryptManager::GenerateRSAKey( unsigned int keyLength, CString privFilename, CString pubFilename, CString seed )
|
2004-02-15 04:47:32 +00:00
|
|
|
{
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( PREFSMAN->m_bSignProfileData );
|
|
|
|
|
|
2004-03-14 17:49:38 +00:00
|
|
|
// Does the RNG need to be inited and seeded every time?
|
2004-02-20 02:28:23 +00:00
|
|
|
random_init();
|
|
|
|
|
random_add_noise( seed );
|
2004-02-15 04:47:32 +00:00
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
RSAKey key;
|
|
|
|
|
key.Generate( keyLength );
|
2004-02-15 04:47:32 +00:00
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
RageFile out;
|
|
|
|
|
|
|
|
|
|
CString sPublic;
|
|
|
|
|
key.PublicBlob( sPublic );
|
|
|
|
|
if( !out.Open( pubFilename, RageFile::WRITE ) )
|
|
|
|
|
RageException::Throw( "Error opening %s: %s", pubFilename.c_str(), out.GetError().c_str() );
|
|
|
|
|
out.Write( sPublic );
|
|
|
|
|
out.Close();
|
|
|
|
|
|
|
|
|
|
CString sPrivate;
|
|
|
|
|
key.PrivateBlob( sPrivate );
|
|
|
|
|
if( !out.Open( privFilename, RageFile::WRITE ) )
|
|
|
|
|
RageException::Throw( "Error opening %s: %s", privFilename.c_str(), out.GetError().c_str() );
|
|
|
|
|
out.Write( sPrivate );
|
|
|
|
|
out.Close();
|
2004-02-15 04:47:32 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 02:15:34 +00:00
|
|
|
void CryptManager::SignFileToFile( CString sPath, CString sSignatureFilename )
|
2004-02-15 04:47:32 +00:00
|
|
|
{
|
2004-02-22 02:15:34 +00:00
|
|
|
if( sSignatureFilename == "" )
|
|
|
|
|
sSignatureFilename = sPath + SIGNATURE_APPEND;
|
|
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
LOG->Trace("SignFile(%s)", sPath.c_str());
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( PREFSMAN->m_bSignProfileData );
|
|
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
if( !IsAFile(PRIVATE_KEY_PATH) )
|
2004-02-16 09:23:34 +00:00
|
|
|
return;
|
2004-02-15 05:45:18 +00:00
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
if( !IsAFile(sPath) )
|
2004-02-15 04:47:32 +00:00
|
|
|
return;
|
|
|
|
|
|
2004-02-22 02:15:34 +00:00
|
|
|
const CString sig = Sign( sPath );
|
2004-02-15 04:47:32 +00:00
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
RageFile out;
|
|
|
|
|
if( !out.Open( sSignatureFilename, RageFile::WRITE ) )
|
|
|
|
|
RageException::Throw( "Error opening %s: %s", sSignatureFilename.c_str(), out.GetError().c_str() );
|
|
|
|
|
out.Write( sig );
|
2004-02-15 04:47:32 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 02:15:34 +00:00
|
|
|
bool CryptManager::VerifyFileWithFile( CString sPath, CString sSignatureFilename )
|
2004-02-15 04:47:32 +00:00
|
|
|
{
|
2004-05-03 00:33:45 +00:00
|
|
|
if( !IsAFile(sPath) )
|
|
|
|
|
return false;
|
|
|
|
|
|
2004-02-22 02:15:34 +00:00
|
|
|
if( sSignatureFilename == "" )
|
|
|
|
|
sSignatureFilename = sPath + SIGNATURE_APPEND;
|
|
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
LOG->Trace("VerifyFile(%s)", sPath.c_str());
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( PREFSMAN->m_bSignProfileData );
|
|
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
if( !IsAFile(PUBLIC_KEY_PATH) )
|
2004-02-16 09:23:34 +00:00
|
|
|
return false;
|
2004-02-15 05:45:18 +00:00
|
|
|
|
|
|
|
|
if( !IsAFile(sSignatureFilename) )
|
2004-02-15 04:47:32 +00:00
|
|
|
return false;
|
|
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
CString sig;
|
|
|
|
|
{
|
|
|
|
|
RageFile in;
|
|
|
|
|
if( !in.Open( sSignatureFilename, RageFile::READ ) )
|
|
|
|
|
RageException::Throw( "Error opening %s: %s", sSignatureFilename.c_str(), in.GetError().c_str() );
|
|
|
|
|
in.Read( sig );
|
|
|
|
|
}
|
2004-02-15 04:47:32 +00:00
|
|
|
|
2004-02-22 02:15:34 +00:00
|
|
|
return Verify( sPath, sig );
|
2004-02-15 04:47:32 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 02:15:34 +00:00
|
|
|
CString CryptManager::Sign( CString sPath )
|
2004-02-17 01:16:57 +00:00
|
|
|
{
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( PREFSMAN->m_bSignProfileData );
|
|
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
if( !IsAFile(PRIVATE_KEY_PATH) )
|
2004-02-17 01:16:57 +00:00
|
|
|
return "";
|
|
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
if( !IsAFile(sPath) )
|
2004-02-17 01:16:57 +00:00
|
|
|
return "";
|
|
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
CString data;
|
|
|
|
|
{
|
|
|
|
|
RageFile in;
|
|
|
|
|
if( !in.Open( sPath, RageFile::READ ) )
|
|
|
|
|
RageException::Throw( "Error opening %s: %s", sPath.c_str(), in.GetError().c_str() );
|
|
|
|
|
in.Read( data );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RSAKey key;
|
|
|
|
|
{
|
|
|
|
|
RageFile keyfile;
|
|
|
|
|
if( !keyfile.Open( PRIVATE_KEY_PATH ) )
|
|
|
|
|
RageException::Throw( "Error opening %s: %s", PRIVATE_KEY_PATH.c_str(), keyfile.GetError().c_str() );
|
|
|
|
|
CString private_blob;
|
|
|
|
|
keyfile.Read( private_blob );
|
|
|
|
|
key.LoadFromPrivateBlob( private_blob );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CString sig;
|
|
|
|
|
key.Sign( data, sig );
|
|
|
|
|
|
|
|
|
|
return sig;
|
2004-02-17 01:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 02:15:34 +00:00
|
|
|
bool CryptManager::Verify( CString sPath, CString sSignature )
|
2004-02-17 01:16:57 +00:00
|
|
|
{
|
2004-05-03 00:33:45 +00:00
|
|
|
if( !IsAFile(sPath) )
|
|
|
|
|
return false;
|
|
|
|
|
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( PREFSMAN->m_bSignProfileData );
|
|
|
|
|
|
2004-02-17 01:16:57 +00:00
|
|
|
CString sPubFilename = PUBLIC_KEY_PATH;
|
|
|
|
|
CString sMessageFilename = sPath;
|
|
|
|
|
|
|
|
|
|
if( !IsAFile(sPubFilename) )
|
|
|
|
|
return false;
|
|
|
|
|
|
2004-02-20 02:28:23 +00:00
|
|
|
CString data;
|
|
|
|
|
{
|
|
|
|
|
RageFile in;
|
|
|
|
|
if( !in.Open( sPath, RageFile::READ ) )
|
|
|
|
|
RageException::Throw( "Error opening %s: %s", sPath.c_str(), in.GetError().c_str() );
|
|
|
|
|
in.Read( data );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RSAKey key;
|
|
|
|
|
{
|
|
|
|
|
RageFile keyfile;
|
|
|
|
|
if( !keyfile.Open( PRIVATE_KEY_PATH ) )
|
|
|
|
|
RageException::Throw( "Error opening %s: %s", PRIVATE_KEY_PATH.c_str(), keyfile.GetError().c_str() );
|
|
|
|
|
CString private_blob;
|
|
|
|
|
keyfile.Read( private_blob );
|
|
|
|
|
key.LoadFromPrivateBlob( private_blob );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return key.Verify( data, sSignature );
|
2004-02-17 01:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 02:15:34 +00:00
|
|
|
CString BinaryToHex( const unsigned char *string, int iNumBytes )
|
|
|
|
|
{
|
|
|
|
|
CString s;
|
|
|
|
|
for( int i=0; i<iNumBytes; i++ )
|
|
|
|
|
{
|
|
|
|
|
unsigned val = string[i];
|
|
|
|
|
s += ssprintf( "%x", val );
|
|
|
|
|
}
|
|
|
|
|
return s;
|
|
|
|
|
}
|
2004-02-17 01:16:57 +00:00
|
|
|
|
2004-02-22 02:15:34 +00:00
|
|
|
CString CryptManager::GetMD5( CString fn )
|
2004-02-15 04:47:32 +00:00
|
|
|
{
|
2004-02-22 02:15:34 +00:00
|
|
|
struct MD5Context md5c;
|
|
|
|
|
unsigned char digest[16];
|
|
|
|
|
int iBytesRead;
|
|
|
|
|
unsigned char buffer[1024];
|
|
|
|
|
|
|
|
|
|
RageFile file;
|
|
|
|
|
if( !file.Open( fn, RageFile::READ ) )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "GetMD5: Failed to open file '%s'", fn.c_str() );
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MD5Init(&md5c);
|
|
|
|
|
while( !file.AtEOF() && file.GetError().empty() )
|
|
|
|
|
{
|
|
|
|
|
iBytesRead = file.Read( buffer, sizeof(buffer) );
|
|
|
|
|
MD5Update(&md5c, buffer, iBytesRead);
|
|
|
|
|
}
|
|
|
|
|
MD5Final(digest, &md5c);
|
|
|
|
|
|
|
|
|
|
return BinaryToHex( digest, sizeof(digest) );
|
2004-02-15 04:47:32 +00:00
|
|
|
}
|
2004-02-16 05:35:06 +00:00
|
|
|
|
|
|
|
|
CString CryptManager::GetPublicKeyFileName()
|
|
|
|
|
{
|
2004-02-19 03:56:03 +00:00
|
|
|
ASSERT( PREFSMAN->m_bSignProfileData );
|
|
|
|
|
|
2004-02-16 05:35:06 +00:00
|
|
|
return PUBLIC_KEY_PATH;
|
|
|
|
|
}
|