Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
KeyChainUtilities.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5// HEADER_UNIT_UNSUPPORTED - Includes JsonSerializer.h which is not in Core module
6
7#include "CoreMinimal.h"
8#include "HAL/FileManager.h"
9#include "Misc/AES.h"
10#include "Misc/IEngineCrypto.h"
11#include "Misc/CoreDelegates.h"
12#include "Misc/Base64.h"
13#include "Serialization/Archive.h"
14#include "Serialization/JsonSerializer.h"
15#include "RSA.h"
16
18{
22
23 bool IsValid() const
24 {
25 return Key.IsValid();
26 }
27};
28
30{
31public:
32
33 FKeyChain() = default;
34
35 FKeyChain(const FKeyChain& Other)
36 {
38 SetEncryptionKeys(Other.GetEncryptionKeys());
39
41 {
42 SetPrincipalEncryptionKey(GetEncryptionKeys().Find(Other.GetPrincipalEncryptionKey()->Guid));
43 }
44 }
45
47 {
49 SetEncryptionKeys(MoveTemp(Other.GetEncryptionKeys()));
50
52 {
53 SetPrincipalEncryptionKey(GetEncryptionKeys().Find(Other.GetPrincipalEncryptionKey()->Guid));
54 }
55
58 Other.SetEncryptionKeys(TMap<FGuid, FNamedAESKey>());
59 }
60
62 {
64 SetEncryptionKeys(Other.GetEncryptionKeys());
65
67 {
68 SetPrincipalEncryptionKey(GetEncryptionKeys().Find(Other.GetPrincipalEncryptionKey()->Guid));
69 }
70 else
71 {
73 }
74
75 return *this;
76 }
77
79 {
81 SetEncryptionKeys(MoveTemp(Other.GetEncryptionKeys()));
82
84 {
85 SetPrincipalEncryptionKey(GetEncryptionKeys().Find(Other.GetPrincipalEncryptionKey()->Guid));
86 }
87 else
88 {
90 }
91
94 Other.SetEncryptionKeys(TMap<FGuid, FNamedAESKey>());
95
96 return *this;
97 }
98
102
105
106 const TMap<FGuid, FNamedAESKey>& GetEncryptionKeys() const { return EncryptionKeys; }
107 TMap<FGuid, FNamedAESKey>& GetEncryptionKeys() { return EncryptionKeys; }
108
109 void SetEncryptionKeys(const TMap<FGuid, FNamedAESKey>& keys) { EncryptionKeys = keys; }
111
112 UE_DEPRECATED(5.1, "Use Get/SetSigningKey instead")
114
115 UE_DEPRECATED(5.1, "Use GetEncryptionKeys instead")
117
118 UE_DEPRECATED(5.1, "Use Get/SetPrincipalEncryptionKey instead")
120};
121
122
124{
125 static FRSAKeyHandle ParseRSAKeyFromJson(TSharedPtr<FJsonObject> InObj)
126 {
127 TSharedPtr<FJsonObject> PublicKey = InObj->GetObjectField(TEXT("PublicKey"));
128 TSharedPtr<FJsonObject> PrivateKey = InObj->GetObjectField(TEXT("PrivateKey"));
129
130 FString PublicExponentBase64, PrivateExponentBase64, PublicModulusBase64, PrivateModulusBase64;
131
132 if (PublicKey->TryGetStringField("Exponent", PublicExponentBase64)
133 && PublicKey->TryGetStringField("Modulus", PublicModulusBase64)
134 && PrivateKey->TryGetStringField("Exponent", PrivateExponentBase64)
135 && PrivateKey->TryGetStringField("Modulus", PrivateModulusBase64))
136 {
137 check(PublicModulusBase64 == PrivateModulusBase64);
138
139 TArray<uint8> PublicExponent, PrivateExponent, Modulus;
140 FBase64::Decode(PublicExponentBase64, PublicExponent);
141 FBase64::Decode(PrivateExponentBase64, PrivateExponent);
142 FBase64::Decode(PublicModulusBase64, Modulus);
143
144 return FRSA::CreateKey(PublicExponent, PrivateExponent, Modulus);
145 }
146 else
147 {
148 return nullptr;
149 }
150 }
151
152 static void LoadKeyChainFromFile(const FString& InFilename, FKeyChain& OutCryptoSettings)
153 {
155 checkf(File != nullptr, TEXT("Specified crypto keys cache '%s' does not exist!"), *InFilename);
156 TSharedPtr<FJsonObject> RootObject;
157 TSharedRef<TJsonReader<UTF8CHAR>> Reader = TJsonReaderFactory<UTF8CHAR>::Create(File);
158 if (FJsonSerializer::Deserialize(Reader, RootObject))
159 {
160 const TSharedPtr<FJsonObject>* EncryptionKeyObject;
161 if (RootObject->TryGetObjectField(TEXT("EncryptionKey"), EncryptionKeyObject))
162 {
163 FString EncryptionKeyBase64;
164 if ((*EncryptionKeyObject)->TryGetStringField(TEXT("Key"), EncryptionKeyBase64))
165 {
166 if (EncryptionKeyBase64.Len() > 0)
167 {
168 TArray<uint8> Key;
169 FBase64::Decode(EncryptionKeyBase64, Key);
170 check(Key.Num() == sizeof(FAES::FAESKey::Key));
171 FNamedAESKey NewKey;
172 NewKey.Name = TEXT("Default");
173 NewKey.Guid = FGuid();
174 FMemory::Memcpy(NewKey.Key.Key, &Key[0], sizeof(FAES::FAESKey::Key));
175 OutCryptoSettings.GetEncryptionKeys().Add(NewKey.Guid, NewKey);
176 }
177 }
178 }
179
180 const TSharedPtr<FJsonObject>* SigningKey = nullptr;
181 if (RootObject->TryGetObjectField(TEXT("SigningKey"), SigningKey))
182 {
183 OutCryptoSettings.SetSigningKey(ParseRSAKeyFromJson(*SigningKey));
184 }
185
186 const TArray<TSharedPtr<FJsonValue>>* SecondaryEncryptionKeyArray = nullptr;
187 if (RootObject->TryGetArrayField(TEXT("SecondaryEncryptionKeys"), SecondaryEncryptionKeyArray))
188 {
189 for (TSharedPtr<FJsonValue> EncryptionKeyValue : *SecondaryEncryptionKeyArray)
190 {
191 FNamedAESKey NewKey;
192 TSharedPtr<FJsonObject> SecondaryEncryptionKeyObject = EncryptionKeyValue->AsObject();
193 FGuid::Parse(SecondaryEncryptionKeyObject->GetStringField(TEXT("Guid")), NewKey.Guid);
194 NewKey.Name = SecondaryEncryptionKeyObject->GetStringField(TEXT("Name"));
195 FString KeyBase64 = SecondaryEncryptionKeyObject->GetStringField(TEXT("Key"));
196
197 TArray<uint8> Key;
198 FBase64::Decode(KeyBase64, Key);
199 check(Key.Num() == sizeof(FAES::FAESKey::Key));
200 FMemory::Memcpy(NewKey.Key.Key, &Key[0], sizeof(FAES::FAESKey::Key));
201
202 check(!OutCryptoSettings.GetEncryptionKeys().Contains(NewKey.Guid) || OutCryptoSettings.GetEncryptionKeys()[NewKey.Guid].Key == NewKey.Key);
203 OutCryptoSettings.GetEncryptionKeys().Add(NewKey.Guid, NewKey);
204 }
205 }
206 }
207 delete File;
208 FGuid EncryptionKeyOverrideGuid;
209 OutCryptoSettings.SetPrincipalEncryptionKey(OutCryptoSettings.GetEncryptionKeys().Find(EncryptionKeyOverrideGuid));
210 }
211
212 static void ApplyEncryptionKeys(const FKeyChain& KeyChain)
213 {
214 if (KeyChain.GetEncryptionKeys().Contains(FGuid()))
215 {
216 FAES::FAESKey DefaultKey = KeyChain.GetEncryptionKeys()[FGuid()].Key;
217 FCoreDelegates::GetPakEncryptionKeyDelegate().BindLambda([DefaultKey](uint8 OutKey[32]) { FMemory::Memcpy(OutKey, DefaultKey.Key, sizeof(DefaultKey.Key)); });
218 }
219
220 for (const TMap<FGuid, FNamedAESKey>::ElementType& Key : KeyChain.GetEncryptionKeys())
221 {
222 if (Key.Key.IsValid())
223 {
224 FCoreDelegates::GetRegisterEncryptionKeyMulticastDelegate().Broadcast(Key.Key, Key.Value.Key);
225 }
226 }
227 }
228}
#define check(expr)
#define checkf(expr, format,...)
#define UE_DEPRECATED(Version, Message)
#define PRAGMA_ENABLE_DEPRECATION_WARNINGS
#define PRAGMA_DISABLE_DEPRECATION_WARNINGS
static constexpr FRSAKeyHandle InvalidRSAKeyHandle
void * FRSAKeyHandle
#define TEXT(x)
Definition Platform.h:1108
UE_NODISCARD FORCEINLINE int32 Len() const
UE_NODISCARD FORCEINLINE const TCHAR * operator*() const UE_LIFETIMEBOUND
virtual FArchive * CreateFileReader(const TCHAR *Filename, uint32 ReadFlags=0)=0
static IFileManager & Get()
static FRSAKeyHandle ParseRSAKeyFromJson(TSharedPtr< FJsonObject > InObj)
static void ApplyEncryptionKeys(const FKeyChain &KeyChain)
static void LoadKeyChainFromFile(const FString &InFilename, FKeyChain &OutCryptoSettings)
bool IsValid() const
Definition AES.h:37
Definition AES.h:20
Definition Guid.h:108
FGuid()
Definition Guid.h:112
FKeyChain()=default
TMap< FGuid, FNamedAESKey > & GetEncryptionKeys()
const TMap< FGuid, FNamedAESKey > & GetEncryptionKeys() const
FKeyChain & operator=(const FKeyChain &Other)
FKeyChain(const FKeyChain &Other)
const FNamedAESKey * GetPrincipalEncryptionKey() const
PRAGMA_DISABLE_DEPRECATION_WARNINGS FRSAKeyHandle GetSigningKey() const
const FNamedAESKey * MasterEncryptionKey
void SetEncryptionKeys(const TMap< FGuid, FNamedAESKey > &keys)
TMap< FGuid, FNamedAESKey > EncryptionKeys
FKeyChain(FKeyChain &&Other)
PRAGMA_ENABLE_DEPRECATION_WARNINGS FRSAKeyHandle SigningKey
void SetSigningKey(FRSAKeyHandle key)
void SetPrincipalEncryptionKey(const FNamedAESKey *key)
FKeyChain & operator=(FKeyChain &&Other)
FAES::FAESKey Key
bool IsValid() const