虚幻引擎国密sm4加密插件

前言

最近需要搞一个基于虚幻引擎的国密sm4加密插件,记录下研究的过程。

插件编写

这里计划写一个插件来进行适配,插件编写可以参考 https://docs.unrealengine.com/5.1/zh-CN/integrating-third-party-libraries-into-unreal-engine/

教程主要是针对编译好的库,如何引用头文件,以及引入lib库等。
我这里还有一种方案,如何第三方库比较轻量,可以把这个文件夹包含进来。

Unreal Build Tool (UBT) 会根据你的项目文件结构自动发现并编译源代码文件。在 Unreal Engine 项目中组织代码时,遵循一定的目录结构是很重要的,这不仅有助于 UBT 正确地识别和编译代码,还能使项目保持清晰和易于管理。以下是一些组织示例,展示了如何安排你的C++和C源代码文件。

虽然Unreal Engine主要使用C++,你仍然可以在项目中包含C源代码文件。将C文件放在合适的目录下(例如Private目录),并确保它们的命名和组织与你的C++文件一致。UBT会自动编译这些C源文件,并将它们链接到最终的可执行文件或库中。即我们将文件放置在Private目录下即可自动编译了。

我们是基于MIRACL进行构建,所以直接把整个文件拷贝到Private目录即可。

3b8d18ae8573b1ecb8773abd894e4002.png

另外,还需要在build.sc中添加如下内容bEnableUndefinedIdentifierWarnings = false;

e0f1a93ed973a03001823ac58baac998.png

不然会有一个报错,报错如下

错误 C4668 没有将“INLINE_ASM”定义为预处理器宏,用“0”替换“#if/#elif”

设置private目录设置为环境目录

在 Unreal Engine 的 Build.cs 文件中,你无法直接将 Private 目录下的一个子目录设置为“环境目录”(即直接影响编译器的包含路径),因为 Unreal Build Tool (UBT) 自动处理源代码文件的查找和编译,它默认包含了 Public 和 Private 目录及其所有子目录作为编译时的包含路径。

然而,你可以通过修改 Build.cs 文件来显式地添加额外的包含路径(Include Paths),这些路径可以是项目内的任何目录,包括位于 Private 目录下的子目录。这样做可以让编译器在编译过程中查找头文件时,包括这些额外指定的目录。

如何添加额外的包含路径 在你的模块的 Build.cs 文件中,你可以使用 PublicIncludePaths 和 PrivateIncludePaths 属性来添加额外的头文件搜索路径。例如,如果你想要添加 Private/SomeSubDirectory 作为一个包含路径,你可以这样做:

PublicIncludePaths.AddRange(
    new string[] {
        Path.Combine(ModuleDirectory, "Private/SomeSubDirectory")
    }
);

PrivateIncludePaths.AddRange(
    new string[] {
        Path.Combine(ModuleDirectory, "Private/SomeSubDirectory")
    }
);

这将指示编译器在查找头文件时,也搜索 Private/SomeSubDirectory 目录。请注意,PublicIncludePaths 是对模块外部可见的路径,而 PrivateIncludePaths 是仅在模块内部使用的路径。在大多数情况下,将私有子目录添加到 PrivateIncludePaths 就足够了。

sm4填充

SM4加密算法是一种分组加密标准,它使用128位的分组大小和128位的密钥长度。在SM4加密中,无论输入数据的大小如何,每次处理的数据块都是固定的128位(16字节)。这意味着输入到SM4加密函数的数据需要被分割成16字节的块。如果最后一个数据块不足16字节,通常需要进行填充(padding)以确保其大小为16字节。

所以PKCS#7填充的基本原理是在数据的末尾添加一定数量的字节,使得填充后的数据长度符合块的整数倍。填充的字节值等于缺少的字节数量。

基于上面两个可以判断出sm4的填充的值永远都是固定的。都是补足为16字节。

16进制字符串互转

由于我的需求是输入16进制字符串的加密数据,所以编写了一个16进制互转的库函数

TArray<uint8> USMFunctionLibrary::HexStringToBytes(const FString& HexString)
{
    TArray<uint8> Bytes;
    // 确保输入字符串长度是偶数
    if (HexString.Len() % 2 != 0)
    {
        UE_LOG(LogTemp, Warning, TEXT("HexStringToBytes requires an even-length input string."));
        return Bytes;
    }
    // 每两个字符表示一个字节
    for (int32 Index = 0; Index < HexString.Len(); Index += 2)
    {
        // 截取两个字符的子字符串
        FString ByteSubstring = HexString.Mid(Index, 2);
        // 将子字符串转换为16进制数值
        uint8 ByteValue = FParse::HexNumber(*ByteSubstring);
        // 添加到字节数组
        Bytes.Add(ByteValue);
    }
    return Bytes;
}

FString USMFunctionLibrary::BytesToHexString(const TArray<uint8>& Bytes)
{
    FString HexString;
    for (uint8 Byte : Bytes)
    {
        // 对于每个字节,将其转换为16进制字符串并追加到结果字符串中
        HexString += FString::Printf(TEXT("%02X"), Byte);
    }
    return HexString;
}

解密算法编写

由于sm4每次只能加密16个字节,所以我们需要对加密的内容进行分割,每次加密16个字节,另外还需要对其进行填充,以保证其可以满足每次16字节的加密。整个实现思路如下

FString USMFunctionLibrary::Sm4Encrypt(FString HexStringKey, FString Input)
{
    auto key = HexStringToBytes(HexStringKey);
    auto inputLen =  Input.Len();
    auto letf16 = inputLen % 16;
    auto addLength = 16 - letf16;
    auto totalLen = inputLen + addLength;
    TArray<uint8> CipherBytes;
    CipherBytes.Init(0, totalLen);

    FTCHARToUTF8 Convert(*Input);
    const uint8* UTF8Data = (uint8*)Convert.Get();

    TArray<uint8> PlainBytes;
    PlainBytes.Empty(16);

    int index = 0;
    for (int i = 0; i < totalLen; i++)
    {
        if (i >= inputLen)
        {
            PlainBytes.Add(addLength);
        }
        else
        {
            PlainBytes.Add(UTF8Data[i]);
        }
        
        if (16 == PlainBytes.Num())
        {
            SM4_Encrypt(key.GetData(), PlainBytes.GetData(), CipherBytes.GetData()+ index*16);
            index++;
            PlainBytes.Empty(16);
        }
    }
 return BytesToHexString(CipherBytes);
}

总结

这个插件目前根据业务需求,我只实现了sm4的解密算法,实际上可以实现全套sm的加解密,这个可以后续进行完善。想要插件源码,可以加入我的知识星球。https://t.zsxq.com/18NDXtAue

我的知识星球

请关注公众号g0415shenw 加入知识星球。
星球地址 https://t.zsxq.com/15EvfoA7n
星球有本人经验心得全部总结 涵盖音视频,gb28181、虚幻引擎、其他编程工具等等。另外还可以在星球提问,我会尽力答复,等于给您多了一个引路人。

  • 29
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值