mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
8088ba94c2
Moved the functions that extract base types from strings as static functions under the associated type. Revised some of the base shared code. Fixed some of the functions in the String library that did not take into account the null terminator.
240 lines
8.2 KiB
C++
240 lines
8.2 KiB
C++
// ------------------------------------------------------------------------------------------------
|
|
#include "Library/Crypt.hpp"
|
|
#include "Base/Shared.hpp"
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#include <sqstdstring.h>
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#include <crc32.h>
|
|
#include <keccak.h>
|
|
#include <md5.h>
|
|
#include <sha1.h>
|
|
#include <sha256.h>
|
|
#include <sha3.h>
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
namespace SqMod {
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SQInteger AES256::Typename(HSQUIRRELVM vm)
|
|
{
|
|
static SQChar name[] = _SC("SqAES");
|
|
sq_pushstring(vm, name, sizeof(name));
|
|
return 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
AES256::AES256()
|
|
: m_Context(), m_Buffer()
|
|
{
|
|
aes256_done(&m_Context);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
AES256::AES256(CSStr key)
|
|
: m_Context(), m_Buffer()
|
|
{
|
|
Init(key);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Int32 AES256::Cmp(const AES256 & o) const
|
|
{
|
|
return memcmp(m_Buffer, o.m_Buffer, sizeof(m_Buffer));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CSStr AES256::ToString() const
|
|
{
|
|
return ToStrF("%s", m_Buffer);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CSStr AES256::GetKey() const
|
|
{
|
|
return reinterpret_cast< CSStr >(m_Buffer);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void AES256::Init(CSStr key)
|
|
{
|
|
// Clear current key, if any
|
|
aes256_done(&m_Context);
|
|
// Is the specified key empty?
|
|
if (!key || *key == 0)
|
|
return; // Leave the context with an empty key
|
|
// Obtain the specified key size
|
|
const Uint32 size = (strlen(key) * sizeof(SQChar));
|
|
// See if the key size is accepted
|
|
if (size > sizeof(m_Buffer))
|
|
STHROWF("The specified key is out of bounds: %u > %u", size, sizeof(m_Buffer));
|
|
// Initialize the key buffer to 0
|
|
memset(m_Buffer, 0, sizeof(m_Buffer));
|
|
// Copy the key into the key buffer
|
|
memcpy(m_Buffer, key, size);
|
|
// Initialize the context with the specified key
|
|
aes256_init(&m_Context, m_Buffer);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void AES256::Done()
|
|
{
|
|
aes256_done(&m_Context);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
String AES256::Encrypt(CSStr data)
|
|
{
|
|
// Is there any data to encrypt?
|
|
if (!data || *data == 0)
|
|
return String();
|
|
// Copy the data into an editable string
|
|
String str(data);
|
|
// Make sure that we have a size with a multiple of 16
|
|
if ((str.size() % 16) != 0)
|
|
str.resize(str.size() - (str.size() % 16) + 16);
|
|
// Encrypt in chunks of 16 characters
|
|
for (Uint32 n = 0; n < str.size(); n += 16)
|
|
aes256_encrypt_ecb(&m_Context, reinterpret_cast< Uint8 * >(&str[n]));
|
|
// Return ownership of the encrypted string
|
|
return std::move(str);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
String AES256::Decrypt(CSStr data)
|
|
{
|
|
// Is there any data to decrypt?
|
|
if (!data || *data == 0)
|
|
return String();
|
|
// Copy the data into an editable string
|
|
String str(data);
|
|
// Make sure that we have a size with a multiple of 16
|
|
if ((str.size() % 16) != 0)
|
|
str.resize(str.size() - (str.size() % 16) + 16);
|
|
// Decrypt inc chunks of 16 characters
|
|
for (Uint32 n = 0; n < str.size(); n += 16)
|
|
aes256_decrypt_ecb(&m_Context, reinterpret_cast< Uint8 * >(&str[n]));
|
|
// Remove null characters in case the string was not a multiple of 16 when encrypted
|
|
while (!str.empty() && str.back() == 0)
|
|
str.pop_back();
|
|
// Return ownership of the encrypted string
|
|
return std::move(str);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* Utility to avoid creating encoder instances for each call.
|
|
*/
|
|
template < class T > struct BaseHash
|
|
{
|
|
static T Algo;
|
|
};
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
template < class T > T BaseHash< T >::Algo;
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* Hash the specified value or the result of a formatted string.
|
|
*/
|
|
template < class T > static SQInteger HashF(HSQUIRRELVM vm)
|
|
{
|
|
const Int32 top = sq_gettop(vm);
|
|
// Was the hash value specified?
|
|
if (top <= 1)
|
|
return sq_throwerror(vm, "Missing hash value");
|
|
// Do we have enough values to call the format function?
|
|
else if (top > 2)
|
|
{
|
|
SStr val = NULL;
|
|
SQInteger len = 0;
|
|
// Attempt to generate the specified string format
|
|
SQRESULT ret = sqstd_format(vm, 2, &len, &val);
|
|
// Did the format failed?
|
|
if (SQ_FAILED(ret))
|
|
return ret; // Propagate the exception
|
|
// Hash the resulted string
|
|
String str(BaseHash< T >::Algo(val));
|
|
// Push the string on the stack
|
|
sq_pushstring(vm, str.data(), str.size());
|
|
}
|
|
else
|
|
{
|
|
// Attempt to retrieve the value from the stack as a string
|
|
Var< CSStr > val(vm, 2);
|
|
// See if the obtained value is a valid string
|
|
if (!val.value)
|
|
return sq_throwerror(vm, "Unable to retrieve the value");
|
|
// Hash the resulted string
|
|
String str(BaseHash< T >::Algo(val.value));
|
|
// Push the string on the stack
|
|
sq_pushstring(vm, str.data(), str.size());
|
|
}
|
|
// At this point we have a valid string on the stack
|
|
return 1;
|
|
}
|
|
|
|
// ================================================================================================
|
|
template < class T > static void RegisterWrapper(Table & hashns, CCStr cname)
|
|
{
|
|
typedef HashWrapper< T > Hash;
|
|
hashns.Bind(cname, Class< Hash >(hashns.GetVM(), cname)
|
|
/* Constructors */
|
|
.Ctor()
|
|
/* Metamethods */
|
|
.Func(_SC("_tostring"), &Hash::ToString)
|
|
/* Properties */
|
|
.Prop(_SC("Hash"), &Hash::GetHash)
|
|
/* Functions */
|
|
.Func(_SC("Reset"), &Hash::Reset)
|
|
.Func(_SC("Compute"), &Hash::Compute)
|
|
.Func(_SC("GetHash"), &Hash::GetHash)
|
|
.Func(_SC("Add"), &Hash::AddStr)
|
|
.Func(_SC("AddStr"), &Hash::AddStr)
|
|
);
|
|
}
|
|
|
|
// ================================================================================================
|
|
void Register_Crypt(HSQUIRRELVM vm)
|
|
{
|
|
Table hashns(vm);
|
|
|
|
RegisterWrapper< CRC32 >(hashns, _SC("CRC32"));
|
|
RegisterWrapper< Keccak >(hashns, _SC("Keccak"));
|
|
RegisterWrapper< MD5 >(hashns, _SC("MD5"));
|
|
RegisterWrapper< SHA1 >(hashns, _SC("SHA1"));
|
|
RegisterWrapper< SHA256 >(hashns, _SC("SHA256"));
|
|
RegisterWrapper< SHA3 >(hashns, _SC("SHA3"));
|
|
|
|
hashns.SquirrelFunc(_SC("GetCRC32"), &HashF< CRC32 >);
|
|
hashns.SquirrelFunc(_SC("GetKeccak"), &HashF< Keccak >);
|
|
hashns.SquirrelFunc(_SC("GetMD5"), &HashF< MD5 >);
|
|
hashns.SquirrelFunc(_SC("GetSHA1"), &HashF< SHA1 >);
|
|
hashns.SquirrelFunc(_SC("GetSHA256"), &HashF< SHA256 >);
|
|
hashns.SquirrelFunc(_SC("GetSHA3"), &HashF< SHA3 >);
|
|
|
|
RootTable(vm).Bind(_SC("SqHash"), hashns);
|
|
|
|
RootTable(vm).Bind("SqAES256", Class< AES256 >(vm, "SqAES256")
|
|
/* Constructors */
|
|
.Ctor()
|
|
.Ctor< CSStr >()
|
|
/* Metamethods */
|
|
.Func(_SC("_cmp"), &AES256::Cmp)
|
|
.SquirrelFunc(_SC("_typename"), &AES256::Typename)
|
|
.Func(_SC("_tostring"), &AES256::ToString)
|
|
/* Properties */
|
|
.Prop(_SC("Key"), &AES256::GetKey)
|
|
/* Functions */
|
|
.Func(_SC("Init"), &AES256::Init)
|
|
.Func(_SC("Done"), &AES256::Done)
|
|
.Func(_SC("Encrypt"), &AES256::Encrypt)
|
|
.Func(_SC("Decrypt"), &AES256::Decrypt)
|
|
);
|
|
}
|
|
|
|
} // Namespace:: SqMod
|