At work I am trying to implement automated build for SharePoint (full trust) projects on visual studio online. (Expect to have several articles about this as and when I meet and solve errors)
When doing SharePoint development we have to sign assemblies with a certificate. When the project is initialized there are two options:
- Certificate is protected by a password: (pfx extension) that was with first versions of SharePoint tooling, or if you have created the structure of (visual studio) solution yourself with several assemblies.
- Certificate is not protected: (snk extension) default option of the tooling for a few years
In my case the certificate was protected by a password which causes the following problem: that you have to type this password when you want to build the source on a new machine for the first time. This is really not convenient when doing automated build (no human to type a password when building). This gives us this error message.
Cannot import the following key file: cert.pfx. The key file may be password protected. To correct this, try to import the certificate again or manually install the certificate to the Strong Name CSP with the following key container name: VS_KEY_XXXXXXXXXXXXXXX
It is even worse when you try to configure it with the build hosted machines. These machines are machines pre configured by Microsoft to avoid having to setup your own build machine. (you cannot access it).
The msbuild framework does not provide a simple way to configure the password and the command line tool sn.exe (used to import the certificates in the store of the machine) also prompts for the password. In fact it makes sense: a password should be memorized and never written down (security 101).
So I had to delete the password for the certificate, only the visual studio interface does not allow us to do this. The only solution is to generate a new certificate in this case? Certainly not! This will change the public key of the assembly and potentially cause problems for all the items saved in database after the update! (I’m particularly thinking about the event receivers).
The solution? Convert the certificate using a little bit of code (running it in a console app) found on pastebin https://pastebin.com/dpMxqsK4
X509Certificate2 cert = new X509Certificate2(@“KEY.pfx”, “pfxPassword”, X509KeyStorageFlags.Exportable |) X509KeyStorageFlags.PersistKeySet);
RSACryptoServiceProvider provider = (RSACryptoServiceProvider) cert.PrivateKey;
Byte [] array = provider.ExportCspBlob(!provider.)PublicOnly);
using (FileStream fs = new FileStream (“FileName.snk”, FileMode.Create, FileAccess.Write))
{
FS.Write(array, 0, array.)Length);
}
Hoping it makes you save time in implementing your automated builds with visual studio online.
PS: Ideally your company should buy a public intermediate authority certificate and setup a PKI. From this PKI you should generate your password-protected certificates. These certificates should be imported once (via GPO if possible) on the developers and the build machines. This would:
- keep the private key protected even in case of theft of the sources
- not require you to give the password to developers or to put it in a script anymore
- allow your customers to ensure that the assembly they receive is published by you and not by an attacker
- implement the automated build (on your machines only not the one provided by VS online)
(see authenticode https://msdn.microsoft.com/fr-fr/library/ms172240.aspx )