0

I'd like to use a public/private key pair to both sign an assembly, and also to sign some configuration settings that the assembly will receive via USB key.

The rationale is that the assembly will be able to use the public key embedded in it to both verify its own integrity and to verify the settings file when it arrives.

I generate a key pair file using sn.exe and then use the .snk file to sign the assembly.

Then, in code, I use:

byte[] k = Assembly.GetExecutingAssembly().GetName().GetPublicKey();

to access the public key.

At the same time, I use sn.exe -i to store the key pair in a machine store.

My server code uses:

CspParameters cspp = new CspParameters();
cspp.KeyContainerName = "mykey";
cspp.Flags = CspProviderFlags.UseMachineKeyStore;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspp))
  {
    var p = rsa.ExportParameters(true);
    rsa.ImportParameters(p);
    signature = rsa.SignData(toSign, new SHA1CryptoServiceProvider());
  }

to sign the text it is sending to the remote client.

The problem is, the Public Key obtained in code snippet 1 seems to be different than the Public Key stored in the container "mykey" and used by snippet 2.

As a result, when my client runs the VerifyData method, it always returns false.

Signing Code:

public static secobj sign(remobj obj)
{
  // Serialize remote object to string
  var xmlSerializer = new XmlSerializer(typeof(remobj));
  var textWriter = new StringWriter();
  var encoder = new UTF8Encoding();

  xmlSerializer.Serialize(textWriter, obj);
  var toSign = encoder.GetBytes(textWriter.ToString());

  // Sign using stored key in local keystore
  CspParameters cspp = new CspParameters();
  cspp.KeyContainerName = "mykey";
  cspp.Flags = CspProviderFlags.UseMachineKeyStore;
  secobj l = new secobj {D1 = obj.D1, D2 = obj.D2, text = obj.text};
  using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspp))
  {
    var p = rsa.ExportParameters(true);
    rsa.ImportParameters(p);
    l.key = rsa.SignData(toSign, new SHA1CryptoServiceProvider());
  }

  return l;
}

validation code:

public static bool validate(secobj l)
{
  // Obtain the public key from the assembly
  byte[] k = Assembly.GetExecutingAssembly().GetName().GetPublicKey();

  // Set up rsa
  RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  RSAParameters rsap = rsa.ExportParameters(false);

  rsap.Modulus = k;

  rsa.ImportParameters(rsap);

  // Create remote obj from secobj
  var obj = new remobj {D1 = l.D1, D2 = l.D2, text = l.text};

  // Serialize remote obj to string
  var xmlSerializer = new XmlSerializer(typeof(remobj));
  var textWriter = new StringWriter();
  var encoder = new UTF8Encoding();

  xmlSerializer.Serialize(textWriter, obj);
  var toVerify = encoder.GetBytes(textWriter.ToString());

  return rsa.VerifyData(toVerify, new SHA1CryptoServiceProvider(), l.key);

}

I am pretty sure there is a problem with either the signing of the local assembly (I am doing all this in a console app as kind of a test harness at the moment) or with my assignment of the Modulous parameter. Something is going wrong between signing the assembly and validating the signed text anyway.

dylanT
  • 1,080
  • 1
  • 13
  • 26

1 Answers1

0

See structure of the public key of a signed assembly for reference on structure of the assembly's public key.

There are no private key components in the public key, just the public modulus and the public exponent.

Example of using a public key to encrypt : Sign string using given Public Key

Community
  • 1
  • 1
TylerY86
  • 3,737
  • 16
  • 29