创建蓝图函数库
1、获取第一个有效的硬盘ID
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "GetDiskIDClass.generated.h"
/**
*
*/
UCLASS()
class OPENTEST_API UGetDiskIDClass : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
static FString GetFirstDiskID();
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "GetDiskIDClass.h"
#include <comutil.h>
FString UGetDiskIDClass::GetFirstDiskID()
{
FString SerialNumber;
for (int DriveNumber = 0; DriveNumber < 16; ++DriveNumber) {
FString Drive = FString::Printf(TEXT("\\\\.\\PhysicalDrive%d"), DriveNumber);
HANDLE hDevice = CreateFile(*Drive, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice != INVALID_HANDLE_VALUE) {
STORAGE_PROPERTY_QUERY storageQuery;
memset(&storageQuery, 0, sizeof(storageQuery));
storageQuery.PropertyId = StorageDeviceProperty;
storageQuery.QueryType = PropertyStandardQuery;
BYTE buffer[4096];
DWORD bytesReturned = 0;
if (DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &storageQuery, sizeof(storageQuery), &buffer, sizeof(buffer), &bytesReturned, NULL)) {
STORAGE_DESCRIPTOR_HEADER* header = (STORAGE_DESCRIPTOR_HEADER*)buffer;
if (header->Size > 0 && header->Size <= bytesReturned) {
STORAGE_DEVICE_DESCRIPTOR* deviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)buffer;
if (deviceDescriptor->SerialNumberOffset > 0) {
SerialNumber = FString(ANSI_TO_TCHAR((char*)deviceDescriptor + deviceDescriptor->SerialNumberOffset));
}
}
}
CloseHandle(hDevice);
if (!SerialNumber.IsEmpty()) {
return SerialNumber;
}
}
}
// 如果没有找到有效的硬盘ID,返回一个空字符串
return FString("");
}
2、获取第一个有效的Mac地址
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "GetFirstMacAddrClass.generated.h"
/**
*
*/
UCLASS()
class OPENTEST_API UGetFirstMacAddrClass : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
static FString GetFirstMac();
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "GetFirstMacAddrClass.h"
#include <Windows.h>
#include <IPHlpApi.h>
FString UGetFirstMacAddrClass::GetFirstMac()
{
IP_ADAPTER_INFO IpAddresses[16];
ULONG OutBufferLength = sizeof(IP_ADAPTER_INFO) * 16;
// Read the adapters
uint32 RetVal = GetAdaptersInfo(IpAddresses, &OutBufferLength);
if (RetVal == NO_ERROR)
{
PIP_ADAPTER_INFO AdapterList = IpAddresses;
// Walk the set of addresses to find the first valid MAC address
while (AdapterList)
{
// If there is an address to read
if (AdapterList->AddressLength > 0)
{
TArray<uint8> MacAddr;
MacAddr.AddZeroed(AdapterList->AddressLength);
FMemory::Memcpy(MacAddr.GetData(), AdapterList->Address, AdapterList->AddressLength);
FString Address;
for (TArray<uint8>::TConstIterator it(MacAddr); it; ++it)
{
Address += FString::Printf(TEXT("%02x"), *it);
}
// Return the first valid MAC address found
return Address;
}
AdapterList = AdapterList->Next;
}
}
// If no valid MAC address is found, return an empty string
return FString("");
}
3、加密
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "EncryptClass.generated.h"
/**
*
*/
UCLASS()
class OPENTEST_API UEncryptClass : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
static bool EncryptStringWithAES(const FString& InputString, const FString& EncryptionKey, FString& OutEncryptedString);
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "EncryptClass.h"
#define UI UI_ST
#include <openssl/ossl_typ.h>
#include <openssl/evp.h>
#undef UI
bool UEncryptClass::EncryptStringWithAES(const FString& InputString, const FString& EncryptionKey, FString& OutEncryptedString)
{
const unsigned char* iv = (const unsigned char*)"0123456789012345"; // 初始化向量(IV),需要与解密时一致
int keylength = 128; // 加密密钥长度,可以是128、192或256
EVP_CIPHER_CTX* ctx;
ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);
const EVP_CIPHER* cipherType = EVP_aes_128_cbc(); // 选择加密算法
if (EVP_EncryptInit_ex(ctx, cipherType, NULL, (const unsigned char*)TCHAR_TO_UTF8(*EncryptionKey), iv) != 1) {
// 初始化加密上下文失败
return false;
}
int max_output_length = InputString.Len() + EVP_MAX_BLOCK_LENGTH; // 预估加密后的最大长度
unsigned char* encryptedOutput = new unsigned char[max_output_length];
int encryptedLength = 0;
if (EVP_EncryptUpdate(ctx, encryptedOutput, &encryptedLength, (const unsigned char*)TCHAR_TO_UTF8(*InputString), InputString.Len()) != 1) {
// 加密数据失败
EVP_CIPHER_CTX_free(ctx);
delete[] encryptedOutput;
return false;
}
int finalEncryptedLength = 0;
if (EVP_EncryptFinal_ex(ctx, encryptedOutput + encryptedLength, &finalEncryptedLength) != 1) {
// 完成加密失败
EVP_CIPHER_CTX_free(ctx);
delete[] encryptedOutput;
return false;
}
encryptedLength += finalEncryptedLength;
// Convert encrypted data to hex string
FString HexString;
for (int i = 0; i < encryptedLength; ++i) {
FString Hex = FString::Printf(TEXT("%02x"), encryptedOutput[i]);
HexString += Hex;
}
OutEncryptedString = HexString;
EVP_CIPHER_CTX_free(ctx);
delete[] encryptedOutput;
return true;
}
4、解密
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "DecryptClass.generated.h"
/**
*
*/
UCLASS()
class OPENTEST_API UDecryptClass : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
static bool DecryptStringWithAES(const FString& EncryptedString, const FString& EncryptionKey, FString& OutDecryptedString);
};
#include "DecryptClass.h"
#define UI UI_ST
#include <openssl/ossl_typ.h>
#include <openssl/evp.h>
#undef UI
bool UMynewJMClass::DecryptStringWithAES(const FString& EncryptedString, const FString& EncryptionKey,
FString& OutDecryptedString)
{
const unsigned char* iv = (const unsigned char*)"0123456789012345"; // IV, 与加密时一致
int keylength = 128; // 密钥长度,与加密时一致
EVP_CIPHER_CTX* ctx;
ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);
const EVP_CIPHER* cipherType = EVP_aes_128_cbc(); // 选择加密算法
if (EVP_DecryptInit_ex(ctx, cipherType, NULL, (const unsigned char*)TCHAR_TO_UTF8(*EncryptionKey), iv) != 1) {
// 初始化解密上下文失败
return false;
}
int max_output_length = EncryptedString.Len() / 2; // 预估解密后的最大长度
unsigned char* decryptedOutput = new unsigned char[max_output_length];
int decryptedLength = 0;
// 将十六进制字符串转换回原始加密数据
TArray<uint8> EncryptedData;
for (int i = 0; i < EncryptedString.Len(); i += 2) {
FString ByteString = EncryptedString.Mid(i, 2);
uint8 Byte = (uint8)FCString::Strtoi64(*ByteString, nullptr, 16);
EncryptedData.Add(Byte);
}
if (EVP_DecryptUpdate(ctx, decryptedOutput, &decryptedLength, EncryptedData.GetData(), EncryptedData.Num()) != 1) {
// 解密数据失败
EVP_CIPHER_CTX_free(ctx);
delete[] decryptedOutput;
return false;
}
int finalDecryptedLength = 0;
if (EVP_DecryptFinal_ex(ctx, decryptedOutput + decryptedLength, &finalDecryptedLength) != 1) {
// 完成解密失败
EVP_CIPHER_CTX_free(ctx);
delete[] decryptedOutput;
return false;
}
decryptedLength += finalDecryptedLength;
// 将解密后的内容存储在 OutDecryptedData 中
TArray<uint8> DecryptedData;
DecryptedData.SetNumUninitialized(decryptedLength);
FMemory::Memcpy(DecryptedData.GetData(), decryptedOutput, decryptedLength);
// Convert the bytes to a hex string
FString HexString;
for (uint8 Byte : DecryptedData) {
FString Hex = FString::Printf(TEXT("%02x"), Byte); // Convert byte to two-digit hex representation
HexString += Hex;
}
OutDecryptedString = HexString;
EVP_CIPHER_CTX_free(ctx);
delete[] decryptedOutput;
return true;
}
5、注册
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "HexClass.generated.h"
/**
*
*/
UCLASS()
class OPENTEST_API UHexClass : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
static FString HexStringToPlainText(const FString& HexString);
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "HexClass.h"
#include "GenericPlatform/GenericPlatformMisc.h"
#include "Misc/Guid.h"
FString UHexClass::HexStringToPlainText(const FString& HexString)
{
FString PlainText;
// 将十六进制字符串转换为原始文本
for (int i = 0; i < HexString.Len(); i += 2)
{
FString ByteString = HexString.Mid(i, 2);
int32 ByteValue = FCString::Strtoi(*ByteString, nullptr, 16);
PlainText.AppendChar((TCHAR)ByteValue);
}
return PlainText;
}
FString UMyhuanyuanClass::GetMachineId()
{
return FPlatformMisc::GetMachineId().ToString();
}
TArray<uint8> UMyhuanyuanClass::GetAllMacAddress()
{
return FPlatformMisc::GetMacAddress();
}
分割线
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "newfunctionClass.generated.h"
/**
*
*/
UCLASS()
class OPENTEST_API UnewfunctionClass : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable)
static bool NewEncryptStringWithAES(const FString& InputString, const FString& EncryptionKey, FString& OutEncryptedString);
UFUNCTION(BlueprintCallable)
static bool NewDecryptStringWithAES(const FString& EncryptedString, const FString& EncryptionKey, FString& OutDecryptedString);
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "newfunctionClass.h"
#include "Misc/Base64.h"
#define UI UI_ST
#include <OpenSSL/err.h>
#include <openssl/ossl_typ.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#undef UI
bool UnewfunctionClass::NewEncryptStringWithAES(const FString& InputString, const FString& EncryptionKey,
FString& OutEncryptedString)
{
unsigned char iv[EVP_MAX_IV_LENGTH];
// 使用密钥的哈希值作为 IV
unsigned char keyHash[EVP_MAX_IV_LENGTH];
uint32_t keyHashLen = 0;
uint8_t* keyData = (uint8_t*)TCHAR_TO_UTF8(*EncryptionKey);
EVP_MD_CTX* mdCtx;
mdCtx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdCtx, EVP_sha256(), NULL);
EVP_DigestUpdate(mdCtx, keyData, FCStringAnsi::Strlen((char*)keyData));
EVP_DigestFinal_ex(mdCtx, keyHash, &keyHashLen);
EVP_MD_CTX_free(mdCtx);
for (int i = 0; i < EVP_MAX_IV_LENGTH; ++i) {
iv[i] = keyHash[i % keyHashLen]; // 使用密钥哈希值填充 IV
}
EVP_CIPHER_CTX* ctx;
ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);
const EVP_CIPHER* cipherType = EVP_aes_128_cbc(); // 选择加密算法
if (EVP_EncryptInit_ex(ctx, cipherType, nullptr, keyHash, iv) != 1) {
// 初始化加密上下文失败
EVP_CIPHER_CTX_free(ctx);
return false;
}
TArray<uint8> InputData;
InputData.Append((uint8*)TCHAR_TO_UTF8(*InputString), InputString.Len()); // 将输入字符串转换为 UTF8 格式的 TArray<uint8>
int max_output_length = InputData.Num() + EVP_MAX_BLOCK_LENGTH; // 预估加密后的最大长度
unsigned char* encryptedOutput = new unsigned char[max_output_length];
int encryptedLength = 0;
if (EVP_EncryptUpdate(ctx, encryptedOutput, &encryptedLength, InputData.GetData(), InputData.Num()) != 1) {
// 加密数据失败
EVP_CIPHER_CTX_free(ctx);
delete[] encryptedOutput;
return false;
}
int finalEncryptedLength = 0;
if (EVP_EncryptFinal_ex(ctx, encryptedOutput + encryptedLength, &finalEncryptedLength) != 1) {
// 完成加密失败
EVP_CIPHER_CTX_free(ctx);
delete[] encryptedOutput;
return false;
}
encryptedLength += finalEncryptedLength;
// 将加密后的内容转换为十六进制字符串
FString HexString;
for (int i = 0; i < encryptedLength; ++i) {
FString Hex = FString::Printf(TEXT("%02x"), encryptedOutput[i]);
HexString += Hex;
}
OutEncryptedString = HexString;
EVP_CIPHER_CTX_free(ctx);
delete[] encryptedOutput;
return true;
}
bool UnewfunctionClass::NewDecryptStringWithAES(const FString& EncryptedString, const FString& EncryptionKey,
FString& OutDecryptedString)
{
unsigned char iv[EVP_MAX_IV_LENGTH];
// 使用密钥的哈希值作为 IV
unsigned char keyHash[EVP_MAX_IV_LENGTH];
uint32_t keyHashLen = 0;
uint8_t* keyData = (uint8_t*)TCHAR_TO_UTF8(*EncryptionKey);
EVP_MD_CTX* mdCtx;
mdCtx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdCtx, EVP_sha256(), NULL);
EVP_DigestUpdate(mdCtx, keyData, FCStringAnsi::Strlen((char*)keyData));
EVP_DigestFinal_ex(mdCtx, keyHash, &keyHashLen);
EVP_MD_CTX_free(mdCtx);
for (int i = 0; i < EVP_MAX_IV_LENGTH; ++i) {
iv[i] = keyHash[i % keyHashLen]; // 使用密钥哈希值填充 IV
}
EVP_CIPHER_CTX* ctx;
ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);
const EVP_CIPHER* cipherType = EVP_aes_128_cbc(); // 选择解密算法
if (EVP_DecryptInit_ex(ctx, cipherType, nullptr, keyHash, iv) != 1) {
// 初始化解密上下文失败
EVP_CIPHER_CTX_free(ctx);
return false;
}
// 将十六进制编码的字符串转换为字节数据
TArray<uint8> EncodedData;
EncodedData.AddUninitialized(EncryptedString.Len() / 2); // 计算十六进制编码的字符串长度
for (int i = 0; i < EncryptedString.Len() / 2; ++i) {
FString Hex = EncryptedString.Mid(i * 2, 2);
EncodedData[i] = FCString::Strtoi64(*Hex, nullptr, 16);
}
int max_output_length = EncodedData.Num();
unsigned char* decryptedOutput = new unsigned char[max_output_length];
int decryptedLength = 0;
if (EVP_DecryptUpdate(ctx, decryptedOutput, &decryptedLength, EncodedData.GetData(), EncodedData.Num()) != 1) {
// 解密数据失败
EVP_CIPHER_CTX_free(ctx);
delete[] decryptedOutput;
return false;
}
int finalDecryptedLength = 0;
if (EVP_DecryptFinal_ex(ctx, decryptedOutput + decryptedLength, &finalDecryptedLength) != 1) {
// 完成解密失败
EVP_CIPHER_CTX_free(ctx);
delete[] decryptedOutput;
return false;
}
decryptedLength += finalDecryptedLength;
// 将解密后的内容转换为 FString 字符串
OutDecryptedString = FString(reinterpret_cast<char*>(decryptedOutput), decryptedLength);
EVP_CIPHER_CTX_free(ctx);
delete[] decryptedOutput;
return true;
}