Files
UnrealEngineUWP/Engine/Source/Developer/PakFileUtilities/Private/SignedArchiveWriter.cpp
graeme thornton cab1ae24eb Removed signing key generation functionality from unrealpak. Keys should be generated with the CryptoKeys plugin in the editor now
#jira UE-68090


#ROBOMERGE-SOURCE: CL 4760704 via CL 4760706
#rb none

[CL 4760723 by graeme thornton in Main branch]
2019-01-21 09:21:37 -05:00

102 lines
2.6 KiB
C++

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "SignedArchiveWriter.h"
#include "IPlatformFilePak.h"
#include "Misc/SecureHash.h"
#include "HAL/FileManager.h"
FSignedArchiveWriter::FSignedArchiveWriter(FArchive& InPak, const FString& InPakFilename, const FEncryptionKey& InPublicKey, const FEncryptionKey& InPrivateKey)
: BufferArchive(Buffer)
, PakWriter(InPak)
, PakSignaturesFilename(FPaths::ChangeExtension(InPakFilename, TEXT("sig")))
, SizeOnDisk(0)
, PakSize(0)
, PublicKey(InPublicKey)
, PrivateKey(InPrivateKey)
{
Buffer.Reserve(FPakInfo::MaxChunkDataSize);
}
FSignedArchiveWriter::~FSignedArchiveWriter()
{
if (BufferArchive.Tell() > 0)
{
SerializeBufferAndSign();
}
delete &PakWriter;
}
void FSignedArchiveWriter::SerializeBufferAndSign()
{
// Compute a hash for this buffer data
ChunkHashes.Add(ComputePakChunkHash(&Buffer[0], Buffer.Num()));
// Flush the buffer
PakWriter.Serialize(&Buffer[0], Buffer.Num());
BufferArchive.Seek(0);
Buffer.Empty(FPakInfo::MaxChunkDataSize);
}
bool FSignedArchiveWriter::Close()
{
if (BufferArchive.Tell() > 0)
{
SerializeBufferAndSign();
}
FEncryptedSignature EncryptedMasterHash;
FDecryptedSignature DecryptedMasterHash;
DecryptedMasterHash.Data = ComputePakChunkHash((const uint8*)&ChunkHashes[0], ChunkHashes.Num() * sizeof(TPakChunkHash));
FEncryption::EncryptSignature(DecryptedMasterHash, EncryptedMasterHash, PrivateKey);
FArchive* SignatureWriter = IFileManager::Get().CreateFileWriter(*PakSignaturesFilename);
*SignatureWriter << EncryptedMasterHash;
*SignatureWriter << ChunkHashes;
delete SignatureWriter;
return FArchive::Close();
}
void FSignedArchiveWriter::Serialize(void* Data, int64 Length)
{
// Serialize data to a buffer. When the max buffer size is reached, the buffer is signed and
// serialized to disk with its signature
uint8* DataToWrite = (uint8*)Data;
int64 RemainingSize = Length;
while (RemainingSize > 0)
{
int64 BufferPos = BufferArchive.Tell();
int64 SizeToWrite = RemainingSize;
if (BufferPos + SizeToWrite > FPakInfo::MaxChunkDataSize)
{
SizeToWrite = FPakInfo::MaxChunkDataSize - BufferPos;
}
BufferArchive.Serialize(DataToWrite, SizeToWrite);
if (BufferArchive.Tell() == FPakInfo::MaxChunkDataSize)
{
SerializeBufferAndSign();
}
SizeOnDisk += SizeToWrite;
PakSize += SizeToWrite;
RemainingSize -= SizeToWrite;
DataToWrite += SizeToWrite;
}
}
int64 FSignedArchiveWriter::Tell()
{
return PakSize;
}
int64 FSignedArchiveWriter::TotalSize()
{
return PakSize;
}
void FSignedArchiveWriter::Seek(int64 InPos)
{
UE_LOG(LogPakFile, Fatal, TEXT("Seek is not supported in FSignedArchiveWriter."));
}