0

I am setting up AS2 communication for signing files to a customer. As I understand signing to work through AS2 communication, we will sign the data we send with our private key, and they will verify it with our public key.

My problem: My IT department has given me a .cer and a .key file. The .cer file has no private key in it, and obviously the .key file is the private key. The customer will add the .cer file to their trusted root to verify our messages. I am having trouble understanding how to sign my data with the .key file. It's not something I can add to a Personal certificate store, so I can't simply get the certificate and do this:

//Open my Personal cert store.
X509Store my = new X509Store(StoreName.My, StoreLocation.LocalMachine);
my.Open(OpenFlags.ReadOnly);

RSACryptoServiceProvider csp = null;

foreach (X509Certificate2 cert in my.Certificates)
{
    if (cert.Subject.Contains("My certificate subject"))
    {
        // We found it. 
        // Get its associated CSP and private key
        csp = (RSACryptoServiceProvider)cert.PrivateKey;
    }
}

// Hash the data
SHA256Managed sha256 = new SHA256Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] hash = sha256.ComputeHash(arMessage);

// Sign the hash
return csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));

How do I get my private key as a RSACryptoServiceProvider directly using the .key file, since a .key file can't be stored in the certificate store?

Vahlkron
  • 464
  • 3
  • 15

2 Answers2

2

I know only how to proceed with PFX files, but converting your KEY file to PFX should not be a problem. See this post:

Is it possible to convert an SSL certificate from a .key file to a .pfx?

Later on, you can manually open the certificate file using this method:

// This you should know
var certPath = @"path-to-file.pfx";
var certPass = @"password-goes-here";

// Create a collection object and populate it using the PFX file
X509Certificate2Collection collection = new X509Certificate2Collection();

collection.Import(certPath, certPass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);

//Then you can iterate over the collection:
foreach (X509Certificate2 cert in collection)
{
     // Bingo

     // Here you can do whatever you want with "cert"
}
Community
  • 1
  • 1
Adrian Salazar
  • 5,279
  • 34
  • 51
  • This looks very promising. I'll take a stab at it. Thank you very much! – Vahlkron Feb 01 '16 at 16:17
  • This does in fact do exactly what I need. It gets me my Private Key in the code. Now, I have issues after that, but this does completely answer my question. Thank you! – Vahlkron Feb 01 '16 at 16:44
1

I've done similar things in a slightly different way. Forgive me if this is not helpful at all and I can delete it.

I'm not doing any signing here but you might be able to figure out how from this.

var collection = new X509Certificate2Collection();
collection.Import(System.Web.Hosting.HostingEnvironment.MapPath(pathToPrivateKey), privateKeyPassword, X509KeyStorageFlags.MachineKeySet);

var requestToPing = (HttpWebRequest)WebRequest.Create(dropOffURL);
requestToPing.Method = "POST";
requestToPing.PreAuthenticate = true;
requestToPing.ClientCertificates.Add(collection[0]);
Joe Phillips
  • 49,743
  • 32
  • 103
  • 159