UE5中一机一码功能

文章介绍了如何在UnrealEngine项目中使用BlueprintFunctionLibrary实现获取第一个有效硬盘ID、Mac地址,以及使用AES进行加密和解密字符串的功能,包括加密和解密的详细步骤。
摘要由CSDN通过智能技术生成

创建蓝图函数库

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;
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我救我自己

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值