Signing Unreal Pak files

I was looking for information on signing Unreal’s Pak files and couldn’t find a concise description of the steps required and information needed. Now that I have it solved, I’m making it available here.

For reference we are on version 4.17 of Unreal.

Background

Epic uses 128 bit RSA keys for signing their Pak files and 128 bit AES for encryption. The keys are added to the *Encryption.ini files for your project (like DefaultEncryption.ini) found in your <project>/Config directory.

For example, Shooter Game (in the Unreal Engine samples) has:

[Core.Encryption]
rsa.privateexp=0x00001ba1f34768c63eb83190c79732e1
rsa.modulus=0x00001ba1f34768c63fbf623ca6273ccf
rsa.publicexp=0x000003f29077ea6576ac995dd35ebe21
aes.key=e3VqgSMhuaPw75fm0PdGZCN3ASwpVOk5Ij7iLf8VOEdqGL6aw05JeX0RHMgBvypd

Once these are available you also need a few extra options to turn it on (possibly in the same file or the platform specific versions):

[Core.Encryption]
EncryptPak=True
SignPak=True

Generating these keys can be done with UnrealPak but it takes an extraordinary amount of time (I had it run over night on a 48 core machine and it had yet to finish). There is a faster way.

Because we generate diffs of our Pak files for faster downloads we have EncryptPak set to false to ensure we get good diffs.

Note these values are embedded into the binary by the UnrealBuildTool when compiling the client and server so what is generated by the UnrealPak tool MUST match the binaries you build.

Generate Keys

There is an easy way to generate the RSA keys however and the method is described at https://blog.shines.me.uk/generating-rsa-public-modulus-public-exponent-private-exponent-as-hexdecimals/ but I’ll recreate it here for reference with values for our specific problem.

The tool used is OpenSSL.exe and is in the Unreal Engine depot/repository.

  1. Generate the RSA keys with:
    • Engine\Binaries\DotNET\IOS\openssl.exe genrsa -out private.pem 128
  2. Get the text output of the RSA keys:
    • Engine\Binaries\DotNET\IOS\openssl.exe asn1parse < private.pem
  3. This generates output like:
    •  0:d=0 hl=2 l= 98 cons: SEQUENCE
       2:d=1 hl=2 l= 1 prim: INTEGER :00
       5:d=1 hl=2 l= 17 prim: INTEGER :E81F2D386E6E6D1866CDA3BDC3FC1C49
       24:d=1 hl=2 l= 3 prim: INTEGER :010001
       29:d=1 hl=2 l= 16 prim: INTEGER :74C902CA6A9D3A5B60469D0FA7CEDF91
       47:d=1 hl=2 l= 9 prim: INTEGER :F685403DD05C42C5
       58:d=1 hl=2 l= 9 prim: INTEGER :F10C2F3F19BFBBB5
       69:d=1 hl=2 l= 9 prim: INTEGER :8AB7E4B463E0E6B9
       80:d=1 hl=2 l= 8 prim: INTEGER :445592F34D86685D
       90:d=1 hl=2 l= 8 prim: INTEGER :7C4BC4D20A5642ED
  4. The modulus is entry 5:
    • 5:d=1 hl=2 l= 17 prim: INTEGER :E81F2D386E6E6D1866CDA3BDC3FC1C49
  5. The public exponent is entry 24 (and will need to be pre-padded with zeroes to 32 characters to be parsed correctly):
    • 24:d=1 hl=2 l= 3 prim: INTEGER :010001
  6. The private exponent is entry 29:
    • 29:d=1 hl=2 l= 16 prim: INTEGER :74C902CA6A9D3A5B60469D0FA7CEDF91
  7. These values fill the fields in the *Encryption.ini.

You can automate this and make it part of the build process too so the keys are rotated given that the keys are relatively small and potentially easily factorable (but may cause severe issues with Downloadable Content if you are planning that instead).

You can also add two other options to your *Game.ini:

[/Script/UnrealEd.ProjectPackagingSettings]
bEncryptIniFiles=True
bEncryptPakIndex=True

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.