You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
4.1 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
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 3 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, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtBigNum.cpp
*
***/
#include "../Pch.h"
#pragma hdrstop
#include <openssl/rand.h>
#include <algorithm>
static inline void byteswap(size_t size, unsigned char * data)
{
for (size_t i = 0; i < (size / 2); ++i)
std::swap(data[i], data[size - i - 1]);
}
/****************************************************************************
*
* BigNum public methods
*
***/
//===========================================================================
BigNum::BigNum () : m_context(nil)
{
BN_init(&m_number);
}
//===========================================================================
BigNum::BigNum (const BigNum & a) : m_context(nil)
{
BN_init(&m_number);
BN_copy(&m_number, &a.m_number);
}
//===========================================================================
BigNum::BigNum (unsigned a) : m_context(nil)
{
BN_init(&m_number);
BN_set_word(&m_number, a);
}
//===========================================================================
BigNum::BigNum (unsigned bytes, const void * data, bool le) : m_context(nil)
{
BN_init(&m_number);
if (le)
FromData_LE(bytes, data);
else
FromData_BE(bytes, data);
}
//===========================================================================
BigNum::~BigNum ()
{
if (m_context)
BN_CTX_free(m_context);
BN_free(&m_number);
}
//===========================================================================
int BigNum::Compare (dword a) const {
// -1 if (this < a)
// 0 if (this == a)
// 1 if (this > a)
if (BN_is_word(&m_number, a))
return 0;
// This returns 0xFFFFFFFFL if the number is bigger than one word, so
// it doesn't need any size check
if (BN_get_word(&m_number) < a)
return -1;
// Not less or equal, must be greater
return 1;
}
//===========================================================================
void BigNum::FromData_LE (unsigned bytes, const void * data)
{
unsigned char * buffer = TRACKED_NEW unsigned char[bytes];
memcpy(buffer, data, bytes);
byteswap(bytes, buffer);
BN_bin2bn(buffer, bytes, &m_number);
delete [] buffer;
}
//===========================================================================
unsigned char * BigNum::GetData_BE (unsigned * bytes) const
{
*bytes = BN_num_bytes(&m_number);
unsigned char * data = TRACKED_NEW unsigned char[*bytes];
BN_bn2bin(&m_number, data);
return data;
}
//===========================================================================
unsigned char * BigNum::GetData_LE (unsigned * bytes) const
{
*bytes = BN_num_bytes(&m_number);
unsigned char * data = TRACKED_NEW unsigned char[*bytes];
BN_bn2bin(&m_number, data);
byteswap(*bytes, data);
return data;
}
//===========================================================================
void BigNum::Rand (unsigned bits, BigNum * seed)
{
// this = random number with bits or fewer bits
unsigned seedBytes;
unsigned char * seedData = seed->GetData_BE(&seedBytes);
RAND_seed(seedData, seedBytes);
BN_rand(&m_number, bits, 0, 0);
delete [] seedData;
}