// // Either keyFile or keyContainer has to be non-null // void LoadPublicKey(string keyFile, string keyContainer) { if (keyContainer != null) { try { private_key = new StrongNameKeyPair(keyContainer); public_key = private_key.PublicKey; } catch { Error_AssemblySigning("The specified key container `" + keyContainer + "' does not exist"); } return; } bool key_file_exists = File.Exists(keyFile); // // For attribute based KeyFile do additional lookup // in output assembly path // if (!key_file_exists && Compiler.Settings.StrongNameKeyFile == null) { // // The key file can be relative to output assembly // string test_path = Path.Combine(Path.GetDirectoryName(file_name), keyFile); key_file_exists = File.Exists(test_path); if (key_file_exists) { keyFile = test_path; } } if (!key_file_exists) { Error_AssemblySigning("The specified key file `" + keyFile + "' does not exist"); return; } using (FileStream fs = new FileStream(keyFile, FileMode.Open, FileAccess.Read)) { byte[] snkeypair = new byte[fs.Length]; fs.Read(snkeypair, 0, snkeypair.Length); // check for ECMA key if (snkeypair.Length == 16) { public_key = snkeypair; return; } try { // take it, with or without, a private key RSA rsa = CryptoConvert.FromCapiKeyBlob(snkeypair); // and make sure we only feed the public part to Sys.Ref byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob(rsa); // AssemblyName.SetPublicKey requires an additional header byte[] publicKeyHeader = new byte[8] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00 }; // Encode public key public_key = new byte[12 + publickey.Length]; Buffer.BlockCopy(publicKeyHeader, 0, public_key, 0, publicKeyHeader.Length); // Length of Public Key (in bytes) int lastPart = public_key.Length - 12; public_key[8] = (byte)(lastPart & 0xFF); public_key[9] = (byte)((lastPart >> 8) & 0xFF); public_key[10] = (byte)((lastPart >> 16) & 0xFF); public_key[11] = (byte)((lastPart >> 24) & 0xFF); Buffer.BlockCopy(publickey, 0, public_key, 12, publickey.Length); } catch { Error_AssemblySigning("The specified key file `" + keyFile + "' has incorrect format"); return; } if (delay_sign) { return; } try { // TODO: Is there better way to test for a private key presence ? CryptoConvert.FromCapiPrivateKeyBlob(snkeypair); private_key = new StrongNameKeyPair(snkeypair); } catch { } } }
// TODO: rewrite this code (to kill N bugs and make it faster) and use standard ApplyAttribute way. public AssemblyName GetAssemblyName(string name, string output) { if (OptAttributes != null) { foreach (Attribute a in OptAttributes.Attrs) { // cannot rely on any resolve-based members before you call Resolve if (a.ExplicitTarget == null || a.ExplicitTarget != "assembly") { continue; } // TODO: This code is buggy: comparing Attribute name without resolving is wrong. // However, this is invoked by CodeGen.Init, when none of the namespaces // are loaded yet. // TODO: Does not handle quoted attributes properly switch (a.Name) { case "AssemblyKeyFile": case "AssemblyKeyFileAttribute": case "System.Reflection.AssemblyKeyFileAttribute": if (RootContext.StrongNameKeyFile != null) { Report.SymbolRelatedToPreviousError(a.Location, a.GetSignatureForError()); Report.Warning(1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module", "keyfile", "System.Reflection.AssemblyKeyFileAttribute"); } else { string value = a.GetString(); if (value != null && value.Length != 0) { RootContext.StrongNameKeyFile = value; } } break; case "AssemblyKeyName": case "AssemblyKeyNameAttribute": case "System.Reflection.AssemblyKeyNameAttribute": if (RootContext.StrongNameKeyContainer != null) { Report.SymbolRelatedToPreviousError(a.Location, a.GetSignatureForError()); Report.Warning(1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module", "keycontainer", "System.Reflection.AssemblyKeyNameAttribute"); } else { string value = a.GetString(); if (value != null && value.Length != 0) { RootContext.StrongNameKeyContainer = value; } } break; case "AssemblyDelaySign": case "AssemblyDelaySignAttribute": case "System.Reflection.AssemblyDelaySignAttribute": RootContext.StrongNameDelaySign = a.GetBoolean(); break; } } } AssemblyName an = new AssemblyName(); an.Name = Path.GetFileNameWithoutExtension(name); // note: delay doesn't apply when using a key container if (RootContext.StrongNameKeyContainer != null) { an.KeyPair = new StrongNameKeyPair(RootContext.StrongNameKeyContainer); return(an); } // strongname is optional if (RootContext.StrongNameKeyFile == null) { return(an); } string AssemblyDir = Path.GetDirectoryName(output); // the StrongName key file may be relative to (a) the compiled // file or (b) to the output assembly. See bugzilla #55320 // http://bugzilla.ximian.com/show_bug.cgi?id=55320 // (a) relative to the compiled file string filename = Path.GetFullPath(RootContext.StrongNameKeyFile); bool exist = File.Exists(filename); if ((!exist) && (AssemblyDir != null) && (AssemblyDir != String.Empty)) { // (b) relative to the outputed assembly filename = Path.GetFullPath(Path.Combine(AssemblyDir, RootContext.StrongNameKeyFile)); exist = File.Exists(filename); } if (exist) { using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read)) { byte[] snkeypair = new byte [fs.Length]; fs.Read(snkeypair, 0, snkeypair.Length); if (RootContext.StrongNameDelaySign) { // delayed signing - DO NOT include private key SetPublicKey(an, snkeypair); } else { // no delay so we make sure we have the private key try { CryptoConvert.FromCapiPrivateKeyBlob(snkeypair); an.KeyPair = new StrongNameKeyPair(snkeypair); } catch (CryptographicException) { if (snkeypair.Length == 16) { // error # is different for ECMA key Report.Error(1606, "Could not sign the assembly. " + "ECMA key can only be used to delay-sign assemblies"); } else { Error_AssemblySigning("The specified file `" + RootContext.StrongNameKeyFile + "' does not have a private key"); } return(null); } } } } else { Error_AssemblySigning("The specified file `" + RootContext.StrongNameKeyFile + "' does not exist"); return(null); } return(an); }