2006-08-17 Sebastien Pouliot <sebastien@ximian.com>
authorSebastien Pouliot <sebastien@ximian.com>
Thu, 17 Aug 2006 12:10:16 +0000 (12:10 -0000)
committerSebastien Pouliot <sebastien@ximian.com>
Thu, 17 Aug 2006 12:10:16 +0000 (12:10 -0000)
* sn.cs: Add support for PKCS#12/PFX password protected files (just
like available in fx 2.0).
* TESTS: Add a test sequence to verify changes in SN.
* Makefile: Distribute TESTS in tarballs.

svn path=/trunk/mcs/; revision=63904

mcs/tools/security/ChangeLog
mcs/tools/security/Makefile
mcs/tools/security/TESTS
mcs/tools/security/sn.cs

index ffc900d87613ebc0f65c35f59ee41183e57c4432..dd8f8bdaf5bb15e3ba7e8b54635a4f2a53906b20 100644 (file)
@@ -1,3 +1,10 @@
+2006-08-17  Sebastien Pouliot  <sebastien@ximian.com>
+
+       * sn.cs: Add support for PKCS#12/PFX password protected files (just
+       like available in fx 2.0).
+       * TESTS: Add a test sequence to verify changes in SN.
+       * Makefile: Distribute TESTS in tarballs.
+
 2006-07-31  Sebastien Pouliot  <sebastien@ximian.com>
 
        * sn.cs: Catch exceptions, including reporting invalid number of 
index a6cae4c904d451d9254e7117b4935fe83bf3cc79..898a17b7d909a51a9c1f1d67c342cedd3f038f0b 100644 (file)
@@ -11,7 +11,7 @@ SECURITY_SOURCES = AssemblyInfo.cs $(topdir)/build/common/Consts.cs StrongNameMa
 
 PROGRAM_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)
 
-DISTFILES = README $(SECURITY_SOURCES)
+DISTFILES = README TESTS $(SECURITY_SOURCES)
 
 ifeq (net_1_1_bootstrap, $(PROFILE))
 all-local: $(topdir)/class/lib/$(PROFILE)/sn.exe
index 9315ca2f9499048b65d3d9e96739436546480f48..121e9364bfc2cdcfc4610f3d0e385dc500c021aa 100644 (file)
@@ -1,5 +1,7 @@
 Mono's Security Tools - TESTS
-Last updated: June 13, 2006
+Last updated: August 17, 2006
+
+-------------------------------------------------------------------------------
 
 * AUTHENTICODE
 
@@ -160,5 +162,169 @@ and Windows to ensure maximum compatibility.
 
 
 [1] this step must be done on Windows using MS Authenticode(r) tools.
---------------------
-sebastien@ximian.com
+
+-------------------------------------------------------------------------------
+
+* STRONGNAME
+
+Here's a minimal test sequence for any change in SN source code (or in the 
+RSA source code). If/when possible all verification should also be done using
+the MS runtime and tools to ensure full interoperability.
+
+0. Setup
+
+       % cd /mcs/tools/security
+       % make
+       % sudo make install
+       % echo "class Program { static void Main () { System.Console.WriteLine (\"hello world\"); } }" > tmp.cs
+       % mcs tmp.cs -out:tmp.exe
+       % sn -v tmp.exe
+
+       [...]
+       tmp.exe is not a strongly named assembly.
+
+
+1. Create a SNK file (default size is 1024 bits)
+
+       % sn -k 1024.snk
+
+       [...]
+       A new 1024 bits strong name keypair has been generated in file '1024.snk'.
+
+       % mcs -delaysign+ -keyfile:1024.snk tmp.cs -out:tmp1024.exe
+       % sn -v tmp1024.exe
+
+       [...]
+       Assembly tmp1024.exe isn't strongnamed
+
+       % mcs -keyfile:1024.snk tmp.cs -out:tmp1024.exe
+       % sn -v tmp1024.exe
+
+       [...]
+       Assembly tmp1024.exe is strongnamed.
+
+
+2. Create a large SNK file (supported by Fx 2.0 and later)
+
+       % sn -k 2048 2048.snk
+
+       [...]
+       A new 2048 bits strong name keypair has been generated in file '2048.snk'.
+
+       % mcs -delaysign+ -keyfile:2048.snk tmp.cs -out:tmp2048.exe
+       % sn -v tmp2048.exe
+
+       [...]
+       Assembly tmp2048.exe isn't strongnamed
+
+       % sn -R tmp2048.exe 2048.snk
+
+       [...]
+       Assembly tmp2048.exe signed.
+
+       % sn -v tmp2048.exe
+
+       [...]
+       Assembly tmp2048.exe is strongnamed.
+
+
+3. Create a PFX (PKCS#12) file
+
+       % makecert -r -n "CN=mono" -p12 tmp.pfx mono
+
+       [...]
+       Success
+
+       % sn -p tmp.pfx tmp.pub
+
+       [...]
+       Enter password for private key (will be visible when typed): mono
+       Public Key extracted to file tmp.pub
+
+       % sn -tp tmp.pub
+
+       Public Key:
+       0024000004800000940000000602000000240000525341310004000011000000137d8a780901ce
+       3ceeb3aa9c813d9027d96e8be0cae633d0f64e584eb50685adb063b72fe3395f681ffda8a7c940
+       d0a8c76b1670c3a54cd354af82fe3995f6784a30c14a106d02f4150d0b370479a2cae574f4bce1
+       bf97a41e59f855a3d0062918861e55afacf9e4934365ea61718ba460dcb46143fee7278414a683
+       85336ace
+
+       Public Key Token: de950f189632e7d9
+
+       *** Note: your public won't match this one - but it will identical to
+       ***       the one we'll extract from the EXE in a few steps...
+
+       % mcs -delaysign+ -keyfile:tmp.pub tmp.cs -out:tmppfx.exe
+       % sn -R tmppfx.exe tmp.pfx
+
+       [...]
+       Enter password for private key (will be visible when typed): mono
+       Assembly tmppfx.exe signed.
+
+       % sn -v tmppfx.exe
+
+       [...]
+       Assembly tmppfx.exe is strongnamed.
+
+
+4. Test using the "well known" files
+
+       % sn -tp ../../class/mono.snk
+
+       [...]
+
+       Public Key:
+       002400000480000094000000060200000024000052534131000400000100010079159977d2d03a
+       8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c
+       3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fd
+       dafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef00
+       65d016df
+
+       Public Key Token: 0738eb9f132ed756
+
+
+       % sn -Tp ../../class/lib/default/Mono.Security.dll
+
+       [...]
+
+       Public Key:
+       002400000480000094000000060200000024000052534131000400000100010079159977d2d03a
+       8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c
+       3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fd
+       dafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef00
+       65d016df
+
+       Public Key Token: 0738eb9f132ed756
+
+
+       % sn -p ../../class/mono.snk tmp.pub
+
+       [...]
+       Public Key extracted to file tmp.pub
+
+       % md5sum tmp.pub
+
+       b35461067e0e8e00941d68bd55e38582  tmp.pub
+
+
+       % sn -tp tmp.pub
+
+       [...]
+
+       Public Key:
+       002400000480000094000000060200000024000052534131000400000100010079159977d2d03a
+       8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c
+       3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fd
+       dafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef00
+       65d016df
+
+       Public Key Token: 0738eb9f132ed756
+
+
+5. Cleanup
+
+       % rm tmp*.*
+
+-------------------------------------------------------------------------------
+Send any bug or suggestions to sebastien at ximian.com
index 42ba9ca957901c70f75f8665ad139097d429e499..9031d1a1c557a41dede341e7a6a66555e5865e2a 100644 (file)
@@ -16,6 +16,7 @@ using System.Text;
 
 using Mono.Security;
 using Mono.Security.Cryptography;
+using Mono.Security.X509;
 
 [assembly: AssemblyTitle("Mono StrongName")]
 [assembly: AssemblyDescription("StrongName utility for signing assemblies")]
@@ -116,6 +117,29 @@ namespace Mono.Tools {
                        }
                        return sb.ToString ();
                }
+
+               static RSA GetKeyFromFile (string filename)
+               {
+                       byte[] data = ReadFromFile (filename);
+                       try {
+                               // for SNK files (including the ECMA pseudo-key)
+                               return new StrongName (data).RSA;
+                       }
+                       catch {
+                               if (data [0] != 0x30)
+                                       throw;
+                               // this could be a PFX file
+                               Console.Write ("Enter password for private key (will be visible when typed): ");
+                               PKCS12 pfx = new PKCS12 (data, Console.ReadLine ());
+                               // works only if a single key is present
+                               if (pfx.Keys.Count != 1)
+                                       throw;
+                               RSA rsa = (pfx.Keys [0] as RSA);
+                               if (rsa == null)
+                                       throw;
+                               return rsa;
+                       }
+               }
 #if false
                // is assembly signed (or delayed signed) ?
                static bool IsStrongNamed (Assembly assembly) 
@@ -199,7 +223,7 @@ namespace Mono.Tools {
                        }
 
                        // Note: MustVerify is based on the original token (by design). Public key
-                       // remapping won't affect if the assebmly is verified or not.
+                       // remapping won't affect if the assembly is verified or not.
                        if (forceVerification || StrongNameManager.MustVerify (an)) {
                                RSA rsa = CryptoConvert.FromCapiPublicKeyBlob (publicKey, 12);
                                StrongName sn = new StrongName (rsa);
@@ -375,8 +399,8 @@ namespace Mono.Tools {
                                                Console.WriteLine ("Output CVS file is {0} (hexadecimal format)", args [i]);
                                        break;
                                case "-p":
-                                       // Extract public key from SNK file
-                                       sn = new StrongName (ReadFromFile (args [i++]));
+                                       // Extract public key from SNK or PKCS#12/PFX file
+                                       sn = new StrongName (GetKeyFromFile (args [i++]));
                                        WriteToFile (args[i], sn.PublicKey);
                                        if (!quiet)
                                                Console.WriteLine ("Public Key extracted to file {0}", args [i]);
@@ -392,8 +416,7 @@ namespace Mono.Tools {
                                        break;
                                case "-R":
                                        string filename = args [i++];
-                                       sn = new StrongName (ReadFromFile (args [i]));
-                                       if (! ReSign (filename, sn.RSA))
+                                       if (! ReSign (filename, GetKeyFromFile (args [i])))
                                                return 1;
                                        break;
                                case "-Rc":