1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-02-22 20:57:12 +01:00
SqMod/source/Library/Crypt.cpp
Sandu Liviu Catalin 4cac7d2d30 Updated the buffer class to include an optional numeric value to be used as an edit cursor or to mark the used buffer size.
Basic implementation of the system path class and several fuctions to retrieve information about the running system.
2016-03-11 04:14:28 +02:00

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))
SqThrowF("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("SqCRC32"), &HashF< CRC32 >);
hashns.SquirrelFunc(_SC("SqKeccak"), &HashF< Keccak >);
hashns.SquirrelFunc(_SC("SqMD5"), &HashF< MD5 >);
hashns.SquirrelFunc(_SC("SqSHA1"), &HashF< SHA1 >);
hashns.SquirrelFunc(_SC("SqSHA256"), &HashF< SHA256 >);
hashns.SquirrelFunc(_SC("SqSHA3"), &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