个人使用 UE4 C++ 函数库(AES-ECB加密注册机)
加密使用CryptoPP5.6.5
build.cs
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore","CryptoPP"});
include
#include <ThirdParty/CryptoPP/5.6.5/include/modes.h>
#include <ThirdParty/CryptoPP/5.6.5/include/hex.h>
#include <ThirdParty/CryptoPP/5.6.5/include/aes.h>
using namespace std;
using namespace CryptoPP;
.h
// 复制到剪贴板
UFUNCTION(BlueprintCallable, Category = "Registry")
static void CopyToClipboard(FString text);
// 获得机器码
UFUNCTION(BlueprintPure, Category = "Registry")
static void GetUniqueId(FString& UniqueId);
// 获取HashAnsiString后的机器码
UFUNCTION(BlueprintPure, Category = "Registry")
static void GetHashAnsiId(FString& HashAnsiId);
// 作用为使用AES-ECB加密解密
UFUNCTION(BlueprintCallable, meta = (DisplayName = "ECB_AESEncryptData", Keywords = "ECB_AESEncryptData", aes_key = "default"), Category = "Registry")
static FString ECB_AESEncryptData(FString aes_content, FString aes_key);
UFUNCTION(BlueprintCallable, meta = (DisplayName = "ECB_AESDecryptData", Keywords = "ECB_AESDecryptData", aes_key = "default"), Category = "Registry")
static FString ECB_AESDecryptData(FString aes_content, FString aes_key, bool& result);
.cpp
void cryptoTest::CopyToClipboard(FString text)
{
FPlatformMisc::ClipboardCopy(*text);
}
void cryptoTest::GetUniqueId(FString& UniqueId)
{
FString tempid;
TArray<uint8> MacAddr = FPlatformMisc::GetMacAddress();
for(TArray<uint8>::TConstIterator it(MacAddr); it; ++it)
{
tempid += FString::Printf(TEXT("%02x"), *it);
}
UniqueId = tempid;
}
void cryptoTest::GetHashAnsiId(FString& HashAnsiId)
{
FString tempid;
TArray<uint8> MacAddr = FPlatformMisc::GetMacAddress();
for(TArray<uint8>::TConstIterator it(MacAddr); it; ++it)
{
tempid += FString::Printf(TEXT("%02x"), *it);
}
HashAnsiId = FMD5::HashAnsiString(*tempid);
}
//会报错,先不用
FString cryptoTest::ECB_AESEncryptData(FString aes_content, FString aes_key)
{
std::string sKey = TCHAR_TO_UTF8(*aes_key);
const char* plainText = TCHAR_TO_ANSI(*aes_content);
std::string outstr;
if(aes_key == "default" || aes_key.IsEmpty())
{
//设定默认秘钥,只要是32位的16进制数随便写
sKey = "01010101010101010101010101010101";
}
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
AES::Encryption aesEncryption((byte*)key, AES::MAX_KEYLENGTH);
ECB_Mode_ExternalCipher::Encryption ecbEncryption(aesEncryption);
//StreamTransformationFilter ecbEncryptor(ecbEncryption, new HexEncoder(new StringSink(outstr)));
StreamTransformationFilter ecbEncryptor(
ecbEncryption,
new HexEncoder(new StringSink(outstr)),
BlockPaddingSchemeDef::BlockPaddingScheme::ZEROS_PADDING,
true
);
ecbEncryptor.Put((byte*)plainText, strlen(plainText));
ecbEncryptor.MessageEnd();
FString returnValue = UTF8_TO_TCHAR(outstr.c_str());
return returnValue;
}
FString cryptoTest::ECB_AESDecryptData(FString aes_content, FString aes_key, bool& result)
{
std::string sKey = TCHAR_TO_UTF8(*aes_key);
std::string outstr;
std::string cipherText = TCHAR_TO_UTF8(*aes_content);
result = false;
if(aes_key == "default" || aes_key.IsEmpty())
{
//设定默认秘钥,只要是32位的16进制数随便写
sKey = "01010101010101010101010101010101";
}
//判断是否为空指针
if(aes_content.IsEmpty())
{
result = false;
return "0";
}
//判断是否为16为长度倍数
if(cipherText.size() % 16 != 0)
{
// CipherText is not a multiple of 2, which means it is not a valid hexadecimal string
result = false;
return "0";
}
//验证是否为16进制字符
// Check if all characters in the cipherText are valid hexadecimal characters
for(char c : cipherText)
{
if(!isxdigit(c))
{
result = false;
return "0";
}
}
try
{
//填key
SecByteBlock key(AES::MAX_KEYLENGTH);
memset(key, 0x30, key.size());
sKey.size() <= AES::MAX_KEYLENGTH ? memcpy(key, sKey.c_str(), sKey.size()) : memcpy(key, sKey.c_str(), AES::MAX_KEYLENGTH);
ECB_Mode<AES >::Decryption ecbDecryption((byte*)key, AES::MAX_KEYLENGTH);
//加上 "true" 后可以验证,但是如果验证失败可能会闪退
//HexDecoder decryptor(new StreamTransformationFilter(ecbDecryption, new StringSink(outstr)));
HexDecoder decryptor(new StreamTransformationFilter(
ecbDecryption, new StringSink(outstr),
BlockPaddingSchemeDef::BlockPaddingScheme::ZEROS_PADDING,
true
));
decryptor.Put((byte*)cipherText.c_str(), cipherText.size());
decryptor.MessageEnd();
result = true;
}
catch(const Exception& e)
{
// An exception occurred, set the result to false and log the error
outstr = "0";
UE_LOG(LogTemp, Error, TEXT("ECB_AESDecryptData failed: %s"), ANSI_TO_TCHAR(e.what()));
result = false;
}
FString returnValue = UTF8_TO_TCHAR(outstr.c_str());
return returnValue;
}
警告: 这是一个解密函数,但当输入值(cipherText)非法时,该函数可能会导致UE4闪退,因此请提前对输入的值进行判断
HexDecoder decryptor(new StreamTransformationFilter(
ecbDecryption, new StringSink(outstr),
BlockPaddingSchemeDef::BlockPaddingScheme::ZEROS_PADDING,
true
));
当编译失败时,有可能是因为导入出现问题,可以在.cpp文件中使用以下代码包裹CryptoPP并重试
THIRD_PARTY_INCLUDES_START
#if PLATFORM_WINDOWS
#include <ThirdParty/CryptoPP/5.6.5/include/modes.h>
#include <ThirdParty/CryptoPP/5.6.5/include/hex.h>
#include <ThirdParty/CryptoPP/5.6.5/include/aes.h>
#elif PLATFORM_MAC
#elif PLATFORM_LINUX
#endif
THIRD_PARTY_INCLUDES_END
示例: