2

I'm working on a project that aims to simplify writing assemblies dynamically, and one thing I've been trying to work out is how to sign the assembly with a strong name, without relying on a secondary program to construct the strong name (such as sn.exe). The documentation mentions that it uses SHA1 as a hash algorithm, but as to how you set the strong name properly, I haven't been able to deduce yet.

I've tried creating a strong name with a SHA1 result from a random byte-array, but in setting the PublicKey and PublicKeyToken to what it implies (the public key is the hash of the byte array I created, or the byte-array I created) and setting the public key token to the last eight bytes of the SHA hash, I get errors when calling the AssemblyBuilder.Save() method.

Every time I get an exception saying the public key is invalid. Is there something I've missed in this?

Thanks in advance.

  • How are you creating the private key for signing? – Jason Malinowski Jan 13 '12 at 21:09
  • http://lhq.rpgsource.net/text/CreatingThePublicKey.html <-- That, using the Item1 or Item2 as the PublicKey via AssemblyName.SetPublicKey(byte[]), and setting the PublicKeyToken via AssemblyName.SetPublicKeyToken(byte[]) using Item3 of the tuple. – Allen Clark Copeland Jr Jan 13 '12 at 21:28

3 Answers3

3

You could try using the ICLRStrongName interface. There's no managed API to do the same thing, so you'll have to use P/Invoke to call them from your managed assembly. I imagine it'd be a whole lot easier just to call the Strong Name Tool from your program with custom switches rather than re-implementing it, but the unmanaged API would be one way to go if you definitely don't want to use the sn.exe.

keyboardP
  • 68,824
  • 13
  • 156
  • 205
  • Could you explain how I would go about obtaining this interface? From my research previously into the managed reflection API, I'm not sure where you'd get the MsCorEE.dll, other than building it yourself. I'm a hobbyist born from a managed world, so C++'s structure is quite irksome, in my view, to work with. – Allen Clark Copeland Jr Jan 13 '12 at 21:24
  • **Addendum** Nevermind, the Mscoree.dll interfaces are included via mscoree.tlb in the Windows Kit, 8.0, in the 'Windows Kits\8.0\Lib\win8\um\x86 directory'. I'll check to see how I'll use this interface, and report the results. – Allen Clark Copeland Jr Jan 13 '12 at 21:32
  • I'm not familiar with the API myself, but this post (and the one it links to in the first line) might help even if it is quite old http://blogs.msdn.com/b/shawnfa/archive/2004/06/18/159711.aspx – keyboardP Jan 13 '12 at 21:36
  • Thanks, I'm going through and building a managed wrapper around the ICLRStrongName interface right now, I'll post back with the results once I've got more to tell. – Allen Clark Copeland Jr Jan 13 '12 at 21:52
1

Public strong name keys aren't random bytes. They're an RSA key, meaning that those bytes must be of a certain form (a modulus that is a semi-prime and an exponent). To generate a key, I'd follow keyboardP's advice and use the ICLRStrongName interface to generate public keys properly.

Jason Malinowski
  • 18,148
  • 1
  • 38
  • 55
1

Strong names use RSA public/private key pairs.

You need to set the KeyPair property on the AssemblyName to a StrongNameKeyPair to produce a signed assembly.

This question describes how to construct an RSA key pair: How to Generate Unique Public and Private Key via RSA

To construct the StrongNameKeyPair you need an array of bytes in .snk format describing the RSA key pair. This format doesn't seem to be documented, though this article has reverse-engineered it: http://www.developerfusion.com/article/84422/the-key-to-strong-names/

To be honest, using ICLRStrongName::StrongNameKeyGen as suggested by @keyboardP would be much simpler, because it will create the key pair and put it in the right format. Even if it does require a bit of P/invoking.

Community
  • 1
  • 1
arx
  • 16,686
  • 2
  • 44
  • 61
  • This answer seemed to end up being the most effective, using RSACryptoServiceProvider and pulling the necessary exponent, modulus, prime, et al members, and writing a data blob that represented the file format for StrongNameKeyPair, was far simpler than handling all the COM marshaling inter-op for ICLRStrongName. – Allen Clark Copeland Jr Jan 16 '12 at 17:12