C# compiler options for security

The following options control compiler security options. The new MSBuild syntax is shown in Bold. The older csc.exe syntax is shown in code style.

  • PublicSign / -publicsign: Publicly sign the assembly.
  • DelaySign / -delaysign: Delay-sign the assembly using only the public portion of the strong name key.
  • KeyFile / -keyfile : Specify a strong name key file.
  • KeyContainer / -keycontainer: Specify a strong name key container.
  • HighEntropyVA / -highentropyva: Enable high-entropy Address Space Layout Randomization (ASLR)

PublicSign

This option causes the compiler to apply a public key but doesn't actually sign the assembly. The PublicSign option also sets a bit in the assembly that tells the runtime that the file is signed.

<PublicSign>true</PublicSign>

The PublicSign option requires the use of the KeyFile or KeyContainer option. The KeyFile and KeyContainer options specify the public key. The PublicSign and DelaySign options are mutually exclusive. Sometimes called "fake sign" or "OSS sign", public signing includes the public key in an output assembly and sets the "signed" flag. Public signing doesn't actually sign the assembly with a private key. Developers use public sign for open-source projects. People build assemblies that are compatible with the released "fully signed" assemblies when they don't have access to the private key used to sign the assemblies. Since few consumers actually need to check if the assembly is fully signed, these publicly built assemblies are useable in almost every scenario where the fully signed one would be used.

DelaySign

This option causes the compiler to reserve space in the output file so that a digital signature can be added later.

<DelaySign>true</DelaySign>

Use DelaySign- if you want a fully signed assembly. Use DelaySign if you only want to place the public key in the assembly. The DelaySign option has no effect unless used with KeyFile or KeyContainer. The KeyContainer and PublicSign options are mutually exclusive. When you request a fully signed assembly, the compiler hashes the file that contains the manifest (assembly metadata) and signs that hash with the private key. That operation creates a digital signature that is stored in the file that contains the manifest. When an assembly is delay signed, the compiler doesn't compute and store the signature. Instead, the compiler but reserves space in the file so the signature can be added later.

Using DelaySign allows a tester to put the assembly in the global cache. After testing, you can fully sign the assembly by placing the private key in the assembly using the Assembly Linker utility. For more information, see Creating and Using Strong-Named Assemblies and Delay Signing an Assembly.

KeyFile

Specifies the filename containing the cryptographic key.

<KeyFile>filename</KeyFile>

file is the name of the file containing the strong name key. When this option is used, the compiler inserts the public key from the specified file into the assembly manifest and then signs the final assembly with the private key. To generate a key file, type sn -k file at the command line. If you compile with -target:module, the name of the key file is held in the module and incorporated into the assembly created when you compile an assembly with AddModules. You can also pass your encryption information to the compiler with KeyContainer. Use DelaySign if you want a partially signed assembly. In case both KeyFile and KeyContainer are specified in the same compilation, the compiler will first try the key container. If that succeeds, then the assembly is signed with the information in the key container. If the compiler doesn't find the key container, it will try the file specified with KeyFile. If that succeeds, the assembly is signed with the information in the key file and the key information will be installed in the key container. On the next compilation, the key container will be valid. A key file might contain only the public key. For more information, see Creating and Using Strong-Named Assemblies and Delay Signing an Assembly.

KeyContainer

Specifies the name of the cryptographic key container.

<KeyContainer>container</KeyContainer>

container is the name of the strong name key container. When the KeyContainer option is used, the compiler creates a sharable component. The compiler inserts a public key from the specified container into the assembly manifest and signs the final assembly with the private key. To generate a key file, type sn -k file at the command line. sn -i installs the key pair into a container. This option isn't supported when the compiler runs on CoreCLR. To sign an assembly when building on CoreCLR, use the KeyFile option. If you compile with TargetType, the name of the key file is held in the module and incorporated into the assembly when you compile this module into an assembly with AddModules. You can also specify this option as a custom attribute (System.Reflection.AssemblyKeyNameAttribute) in the source code for any Microsoft intermediate language (MSIL) module. You can also pass your encryption information to the compiler with KeyFile. Use DelaySign to add the public key to the assembly manifest but signing the assembly until it has been tested. For more information, see Creating and Using Strong-Named Assemblies and Delay Signing an Assembly.

HighEntropyVA

The HighEntropyVA compiler option tells the Windows kernel whether a particular executable supports high entropy Address Space Layout Randomization (ASLR).

<HighEntropyVA>true</HighEntropyVA>

This option specifies that a 64-bit executable or an executable that is marked by the PlatformTarget compiler option supports a high entropy virtual address space. The option is enabled by default for all .NET Standard and .NET Core versions, and .NET Framework versions starting with .NET Framework 4.5.

The HighEntropyVA option enables compatible versions of the Windows kernel to use higher degrees of entropy when randomizing the address space layout of a process as part of ASLR. Using higher degrees of entropy means a larger number of addresses can be allocated to memory regions such as stacks and heaps. As a result, it's more difficult to guess the location of a particular memory region. The HighEntropyVA compiler option requires the target executable and any modules that it depends on can handle pointer values larger than 4 gigabytes (GB) when they're running as a 64-bit process.