Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / CLR / June 2004

Tip: Looking for answers? Try searching our database.

Signing Assembly with StrongNameSignatureGeneration()

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Jacek - 09 Jun 2004 08:18 GMT
Hi All!

My managed C# app has to sign edited assemblies after finishing its work. I
have tried to use .NET Framework unamnaged API function
StrongNameSignatureGeneration() which apparently works (success as return
result) but not with all scenarios described in MSDN
documentation and moreover the signing result seems to be incorrect!

Scenario 1.
I can not reproduce scenario where passing null pointer to ppbSignatureBlob
causes function to sign assembly file instead of returning
signature blob in ppbSignatureBlob.

Scenario 2. (with signature blob retrieval)
The test for signing result is as follows:
1. PEFile with StrongName signature is created (valid assembly which can be
loaded and executed by CLR).
2. PEFile is parsed and StrongNameSignature pointed by CLIHead is zeroed -
exactly 128 bytes at FilePointer calculated from Signature RVA.
3. StrongNameSignatureGeneration function is called on modified PEFile (the
step 2 could be ommited to my knowledge as signature area is
not hashed during signing - code analysis of strongname.cpp of SSCLI).
4. After retrieving signature blob in ppbSignatureBlob it is written into
PEFile at FilePointer address of original signature.
Assembly signed in that way does not pass verification with sn tool.

When this same is done with sn tool -R (resign) option on this same assembly
different signature blob is obtained than with API call
(signature blob generated by StrongNameSignatureGeneration and sn tools are
not simple start - end reversal)!
This can be easily traced with any hex dumps of file content. Furthermore
file signed with sn -R passes sn verification test.

My questions:
1. How can I force StrongNameSignatureGeneration to sign file?
2. What's wrong with signature generated by StrongNameSignatureGeneration
function when retrieving it via blob?

My code follows.
Thanks for any hints to the problem.

Jacek

DllImport prototype declaration is as follows:

[DllImport("mscoree.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern bool StrongNameSignatureGeneration(
 [In, MarshalAs(UnmanagedType.LPWStr)] String wszFilePath,
 [In, MarshalAs(UnmanagedType.LPWStr)] String wszKeyContainer,
 [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] byte[]
pbKeyBlob,)
 [In,MarshalAs(UnmanagedType.U4 )] uint cbKeyBlob,
 [Out] out IntPtr ppbSignatureBlob,
 [Out,MarshalAs(UnmanagedType.U4 )] out uint pcbSignatureBlob);

Function is called in the following way (it should be sufficient to comment
out  buff = Marshal.AllocHGlobal(128) to reproduce file signing
scenario but it does not work - signature is returned in buff instead of
being written to assembly file);:

public static byte[] SignatureGeneration(String AssemblyFilePath, String
KeyFile)
{
    byte[] retVal = null;
    IntPtr buff = IntPtr.Zero;
    uint kl;
    FileStream fs = null;
    try
    {
         fs = new FileStream(KeyFile, FileMode.Open);
         byte[] keypair = new byte[fs.Length];
         int read = fs.Read(keypair, 0, (int)fs.Length);
         if ((long) read != fs.Length) throw new
System.IO.IOException("Error while reading file.");

         buff = Marshal.AllocHGlobal(128);

         if (!Interop.StrongNameSignatureGeneration(
          AssemblyFilePath, String.Empty, keypair, (uint) keypair.Length,
out buff, out kl))
         {
              int result = Marshal.GetHRForLastWin32Error();
              Marshal.ThrowExceptionForHR(result);
         }
         retVal = new byte[kl];
         if (buff != IntPtr.Zero) Marshal.Copy(buff, retVal, 0,
retVal.Length);
    }
    finally
    {
         if (buff != IntPtr.Zero) Marshal.FreeHGlobal(buff);
         if (fs != null) fs.Close();
    }
    return retVal;
}
Jacek - 10 Jun 2004 16:39 GMT
Finally I have found solution and thought it could be of interest to others.

Unfortunately I was unable to use StrongNameSignatureGeneration to sign
anything so I have tested recently released libraries of Mono Beta 2 (Ximian
CLR, CLI implemetation comprising large parts of .NET as well with numerous
very useful extensions) and found Mono.Security.StrongName class which can
be used for signing and verification of assemblies.

This works perfectly!!! Assemblies signed pass verification by sn.exe tools
of both Mono and .NET distributions.
Shame on MS for not being able to provide appriopriate support for such a
basic part of infrastructure.

Jacek

Code of method employing Mono.StrongName class to sign assemblies follows:

 internal void ResignAssemblyMono()
 {

   FileStream fs = null;
   try
   {
    fs = new FileStream("C:\KeyPairFile", FileMode.Open);
    byte[] keypair = new byte[fs.Length];
    int result = fs.Read(keypair, 0, (int) fs.Length);
    if (result != keypair.Length) throw new System.IO.IOException("Error
while reading file.");
    StrongName sn = new StrongName(keypair);
    if (!sn.Sign(this.file)) throw new Exception ("Failed to sign file: " +
Path.GetFileName(this.file));
   }
   finally
   {
    if (fs != null) fs.Close();
   }

 }

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
[quoted text clipped - 102 lines]
> =cu1V
> -----END PGP SIGNATURE-----
Jacek - 11 Jun 2004 10:44 GMT
Hi Again!

I have to withdraw my complaints about MSFT, as there exist working solution
for using StrongNameSignatureGeneration() from C#.
Please check for SDK sample TlbGen in Technologies\Interop folder.
StrongName class declares imports of different API functions and
ResignAssembly method implements assembly resigning.
Tests are passed so I am positive about this solution. However, due to
P/Invoke independant nature of Mono implemenation I prefer to use that one.

Jacek

PS P/Invoke declarations are made in a weird way which is surely not
recommended by MS in all P/Invoke documentation I have read and it was a lot
on that subject. i.e. pointers to C style byte arrays are declared as int
instead of IntPtr, btw they are not used at all.

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
[quoted text clipped - 102 lines]
> =cu1V
> -----END PGP SIGNATURE-----

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.