说明
参考文章:
1.大佬的实现,老早膜拜 Crypto++_AES加密解密
2.AES加密解密(解决中文乱码问题)
基于两位大佬的实现,自己组装了一个可以对任意字符的加密解密的功能
1.在对字符串进行加密时,要先将源加密字符串添加前后缀,然后转换成TArray ,然后再转换成 base64 .
做这一步主要是因为中文有可能在base64转换过程中产生乱码,但乱码产生是有规律的,会在完整的字符解析前后生成。不会在中间生成。所以先加入前后缀,在base64解码时对其分割,取中间。
2.在对base64格式字符串拼接一个特殊识别字符串。因为ue自带aes加密后解密时,会在末尾产生一部分多余乱码,所以添加了这个末尾后缀,在解密后分割取左边就是原有的base64源数据了
3.再对base64反向解析成string,就是原始数据了
实现
一图胜千言,画的不专业,见谅
.h
UFUNCTION(BlueprintCallable, Category = "AES")
static FString Encrypt(FString InputString, FString decryptKey = "Key");
UFUNCTION(BlueprintCallable, Category = "AES")
static FString Decrypt(FString InputString, FString decryptKey = "Key");
.cpp
#include "Engine.h"
#include "Runtime/Core/Public/Misc/AES.h"
#include "Runtime/Core/Public/Misc/SecureHash.h"
#include "Runtime/Core/Public/Misc/Base64.h"
#include "EncryptSaveGame.h"
#include "Runtime/Engine/Classes/Kismet/GameplayStatics.h"
#include "String"
FString UEncrypt_DecryptBPLibrary::Encrypt(FString InputString, FString decryptKey)
{
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, "source : " + InputString);
// Check inputs
if (InputString.IsEmpty()) return ""; //empty string? do nothing
if (decryptKey.IsEmpty()) return "";
//add source code split signal
FString signStartStr = "=-startCheck-=";
FString signEndStr = "=-endCheck-=";
InputString = signStartStr + InputString;
InputString.Append(signEndStr);
//******chuange source string to Base64 format : string -> tarray<uint8> -> base64
TArray<uint8> content;
std::string _s(TCHAR_TO_UTF8(*InputString));
content.Append((unsigned char*)_s.data(), _s.size());
InputString = FBase64::Encode(content);
// To split correctly final result of decryption from trash symbols
FString SplitSymbol = "somethingSpecialSignal";
InputString.Append(SplitSymbol);
// We need at least 32 symbols key
decryptKey = FMD5::HashAnsiString(*decryptKey);
TCHAR *KeyTChar = decryptKey.GetCharArray().GetData();
ANSICHAR *KeyAnsi = (ANSICHAR*)TCHAR_TO_ANSI(KeyTChar);
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, "1 ");
// Calculate blob size and create blob
uint8* Blob;
uint32 Size;
Size = InputString.Len();
Size = Size + (FAES::AESBlockSize - (Size % FAES::AESBlockSize));
Blob = new uint8[Size];
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, "2 ");
// Convert string to bytes and encrypt
if (StringToBytes(InputString, Blob, Size)) {
FAES::EncryptData(Blob, Size, KeyAnsi);
InputString = FString::FromHexBlob(Blob, Size);
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, "3 ");
delete Blob;
return InputString;
}
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, "4 ");
delete Blob;
return "";
}
FString UEncrypt_DecryptBPLibrary::Decrypt(FString InputString, FString Key)
{
// Check inputs
if (InputString.IsEmpty()) return "";
if (Key.IsEmpty()) return "";
// To split correctly final result of decryption from trash symbols
FString SplitSymbol = "somethingSpecialSignal";
// We need at least 32 symbols key
Key = FMD5::HashAnsiString(*Key);
TCHAR *KeyTChar = Key.GetCharArray().GetData();
ANSICHAR *KeyAnsi = (ANSICHAR*)TCHAR_TO_ANSI(KeyTChar);
// Calculate blob size and create blob
uint8* Blob;
uint32 Size;
Size = InputString.Len();
Size = Size + (FAES::AESBlockSize - (Size % FAES::AESBlockSize));
Blob = new uint8[Size];
// Convert string to bytes and decrypt
if (FString::ToHexBlob(InputString, Blob, Size)) {
FAES::DecryptData(Blob, Size, KeyAnsi);
InputString = BytesToString(Blob, Size);
// Split required data from trash
FString LeftData;
FString RightData;
InputString.Split(SplitSymbol, &LeftData, &RightData, ESearchCase::CaseSensitive, ESearchDir::FromStart);
InputString = LeftData;
//back the base64 code to string , see the encrypt function
TArray<uint8> content;
FBase64::Decode(InputString, content);
InputString=FString(UTF8_TO_TCHAR(content.GetData()));
//split by source code split signal
FString signStartStr = "=-startCheck-=";
FString signEndStr = "=-endCheck-=";
InputString.Split(signStartStr, &LeftData, &RightData, ESearchCase::CaseSensitive, ESearchDir::FromStart);
InputString = RightData;
InputString.Split(signEndStr, &LeftData, &RightData, ESearchCase::CaseSensitive, ESearchDir::FromStart);
delete Blob;
return LeftData;
}
delete Blob;
return "";
}
蓝图调用
结果