Signing and Verifying Assemblies

for RuBoard

The publisher's public key is embedded in the assembly's metadata along with the other components of the assembly name (text name, version and culture). But it is not enough to simply supply the public key in this fashion. After all, the key is public and therefore nothing would stop another publisher from stamping its assemblies with your key. To enforce the strength of the name , you must be able to verify that the contents of the assembly were indeed generated by the advertised publisher.

It's important that the entire content of the assembly (including external modules for multifile assemblies) are covered by this verification. Otherwise, a malicious third party could modify a valid assembly and redistribute the result. Even innocuous -seeming aspects of the assembly, such as user interface resources, are potential security vulnerabilities if left open to modification by third parties. For example, simply changing the text of a dialog prompt could trick a user into revealing password information, potentially in a publicly visible manner. See Figure 9.4 for an example.

Figure 9.4. Deceiving the user into supplying sensitive information.

graphics/09fig04.jpg

To tie together the publisher identity ”the public key ”and the contents of the assembly, a digital signature is computed and written into the assembly during compilation. The signature is formed by computing a cryptographic hash over the contents of the assembly ( essentially , a very condensed summary of the data) and encoding the result using the publisher's private key. Figure 9.5 illustrates the signing process.

Figure 9.5. Computing a strong name signature.

graphics/09fig05.gif

To perform validation, the signature is decrypted using the publisher public key (found in the assembly metadata), yielding an assembly contents hash. The hash is then recomputed for the current assembly contents and the results compared. If both hashes match, you know that the current assembly contents remain identical with those from the point at which the signature was generated. Furthermore, you know that the generator of the signature was in possession of the private key corresponding to the public key found in the assembly manifest. Figure 9.6 depicts the verification process. Any attempt to modify the assembly contents will change the hash generated on verification, and storing an updated hash for the new contents requires the private key for the hash encryption phase.

Figure 9.6. Verifying a strong name signature.

graphics/09fig06.gif

From this you can see that the reliability of strong name verification is dependent on two factors ”the secrecy of the private key and the ability of the hash to accurately reflect the contents of the assembly. The hashing algorithm used is SHA1, which generates a 20-byte hash code. It is extremely difficult, in fact computationally unfeasible, to discover another byte sequence that will yield the same hash code under this algorithm ”changing even a single bit in the input will yield a radically different hash.

In summary, the act of strong naming requires the addition of two new pieces of data to the assembly:

  • The public key, which becomes visible as part of the assembly's name

  • The signature, which validates the right to use the public key and allows the consistency of the assembly contents to be verified

The structure of a strong name assembly is illustrated in Figure 9.7.

Figure 9.7. The strong name components on an assembly.

graphics/09fig07.gif

The verification of any strong name assemblies is performed automatically when needed by the .NET Framework. Any assembly claiming a strong name but failing verification will fail to install into the global assembly or download cache or will fail to load at runtime.

THE ECMA PUBLIC KEY

One public key is treated specially by the .NET Framework. This is known as the ECMA key after the European Computer Manufacturer's Association, which has determined a standard for the implementation of .NET Framework-like runtimes on other computing platforms. The ECMA key is designed to facilitate porting of the core .NET Framework class libraries to such platforms. To appreciate the problem that the ECMA solves , consider for a moment the strong names of the standard runtime libraries ” mscorlib , System , System.Data , and so on. Each of these assemblies is signed with the Microsoft private key, ensuring that third parties cannot distribute altered copies that could be mistaken for the originals . This, in turn , dictates the public key (because there is a one-to-one correspondence between public and private keys). Because the public key is considered part of the assembly name, it (or rather the public key token form of it) becomes embedded in every reference from every other assembly that has a dependency.

So what happens if a publisher (let's call it Corporation X) wants to implement the core .NET Framework runtime on a new platform? It will need to implement its own versions of the standard core libraries ( mscorlib , System , and so on) and while these new versions can provide all the same functionality and honor all the standardized interfaces of the Microsoft originals, no application targeted at Microsoft's runtime will actually run against them. This is because the application's assemblies will contain references to the original Microsoft core assemblies, strong named with Microsoft's public key. Corporation X cannot strong name its own assemblies with Microsoft's public key, because that would require access to Microsoft's private key ”something it is not likely to be granted.

To solve this problem, the public keys embedded into the core assemblies required by the runtime are not the Microsoft public key at all. In fact, the binary blob used is not strictly a valid public key, but a simple 16-byte placeholder, the so-called ECMA key. The affected assemblies are still signed with the Microsoft private key, but the assemblies' identities are no longer pinned specifically to Microsoft. The ECMA key has the following form (as represented in hexadecimal text):

 00000000000000000400000000000000 

When used as a publisher identity, the ECMA key is treated as a normal public key distinct from the Microsoft public key. It has a public key token computed in exactly the same manner as for all other public keys, and identity operations are performed through byte-by-byte comparison as is normal. However, when its use is required as a cryptographic public key, as is the case during strong name signing and verification, the Microsoft runtime automatically converts the ECMA key into the Microsoft public key. Corporation X would implement its runtime to perform the conversion from ECMA key to the Corporation X public key instead.

In this fashion, assemblies using only core runtime components remain portable between differing platforms. The runtime provider for each platform can still strong name sign its core assemblies to ensure integrity without compromising such portability. The ECMA key doesn't introduce any security weaknesses because it does not allow core assemblies to be signed by an arbitrary private key. Rather, core assemblies must be signed by the private key of the runtime provider whose runtime is being used. Put another way, for any given implementation of the runtime, the core assemblies must be signed by the runtime provider itself.

In summary, the goal of the ECMA key is to allow a slightly more generalized strong name binding than usual, namely allowing binding to the publisher of the runtime in use, rather than to a fixed publisher.

for RuBoard


. NET Framework Security
.NET Framework Security
ISBN: 067232184X
EAN: 2147483647
Year: 2000
Pages: 235

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net