10

I'm making a client app for Windows 10. I have a problem where I'd like to open-source my code, but leave the API key invisible to other people. This is the relevant portion of my source file:

private const string ApiKey = "YOUR_API_KEY";

I'd like to have this transformed to

private const string ApiKey = "THE_ACTUAL_API_KEY";

when it is compiled. How would I go about doing this?


edit: Sorry for any ambiguities; I was asking how to prevent viewers of the source code on GitHub from seeing the string, whilst not having to change it during local builds. This question does not relate to encryption in any way.

Hogan
  • 69,564
  • 10
  • 76
  • 117
James Ko
  • 32,215
  • 30
  • 128
  • 239
  • Did you read up about SecureString in C#? – TomTom Jan 27 '16 at 18:38
  • 1
    @TomTom IMHO this isn't duplicate of the question you have linked to... – Stewart_R Jan 27 '16 at 18:40
  • 3
    Also, a securestring isnt really a solution. You can only append 1 character to a securestring, which will require you to have it as a string elsewhere. – Mathijs Jan 27 '16 at 18:42
  • One of the approach could be to generate a self [signed certificate](https://blogs.technet.microsoft.com/jhoward/2005/02/02/how-to-use-makecert-for-trusted-root-certification-authority-and-ssl-certificate-issuance/) then [Encrypt](http://blog.aggregatedintelligence.com/2010/02/encryptingdecrypting-using.html) the string using RSAcryptography and place it as APIKey in your application. To decrypt the key you need to write a [Decryption](http://www.csharpbydesign.com/2008/04/asymmetric-key-encryption-with.html) method which would use your PKCS#12 (PFX) format private key from ur app at run time. – vendettamit Jan 27 '16 at 19:20
  • @TomTom I took a look at the link you posted. While it didn't work for me, I found another solution that did. If you un-mark this as a dupe, I'll be happy answer my own question with the solution I found. Thanks. – James Ko Jan 27 '16 at 19:24
  • @vendettamit Done, thanks for reminding me! – James Ko Jan 27 '16 at 20:45

3 Answers3

16

Here's how I ended up solving the problem.

I added a class to my project called Credentials.cs:

public static class Credentials
{
    public const string ApiKey = "YOUR_API_KEY";
}

All further references to the API key were made via the field I added. For example:

public void MakeRequest()
{
    var client = new ApiClient(Credentials.ApiKey);
    client.DoSomething();
}

Now for the magical part. After committing that file via Git, I ran git update-index --assume-unchanged Credentials.cs, which (as per this SO answer) tells Git to stop tracking changes to the file. In other words, if you modify the file and run git diff or git status, nothing will show up.

Then I replaced YOUR_API_KEY with the actual API key in the file, and now everything works perfectly.

Community
  • 1
  • 1
James Ko
  • 32,215
  • 30
  • 128
  • 239
  • 4
    I thought the question was to _safely_ storing it. Putting it in plaintext is by no means "safe." All you're doing is just leaving an uncommitted change. – Jeff Mercado Jan 27 '16 at 20:49
  • 2
    @JeffMercado All I need is to make sure viewers of the source code can't see it. I did not mention encryption/obfuscation in my original post. – James Ko Jan 27 '16 at 20:52
2

I usually put these in a Web.config.Template.xml file. Then I put my real keys in web.debug.config (for example) and when the project is built, i transform Web.config.Template.xml with web.debug.config and dump the transformation into web.config. I use a nuget package XmlTransformer and put this line in the "prebuild" events to accomplish this every time I build the project: "$(SolutionDir)packages\XmlTransformer.1.1.0.4\lib\net40\XmlTransformer.exe" /s:"$(ProjectDir)Web.config.Template.xml" /t:"$(ProjectDir)Web.$(ConfigurationName).config" /d:"$(ProjectDir)Web.config" /k:Transform

I never commit web.config or web.debug.config to SC, only the web.template.config

here's some more info on config transformations: https://msdn.microsoft.com/en-us/library/dd465326(v=vs.110).aspx

solidau
  • 4,021
  • 3
  • 24
  • 45
  • I'll add that there is now a Visual Studio extension that takes care of most of this for you now. Check out Fast Koala: https://marketplace.visualstudio.com/items?itemName=JonDaviswijitscom.FastKoala-WebAppconfigXMLtransforms – solidau Oct 10 '17 at 19:48
1

You can't. The only solution is it must not be stored in your public GitHub repo. You can never allow any non-public portion of a secret to be... public.

The solution to this is you must store the secret closer to your hosting. Here's an example of how Azure Websites has built in secret protection that seamlessly integrates with continuous deployment. Other cloud providers have similar constructs, for do it yourself hosting... you must do it yourself. You build a post-build step that will swap in the secrets from a non-public location.

Separate option is to maintain a private fork of your public repo that contains the key. Then you just pull updates from the public repo to your private one as desired. But optimally you want to keep the keys out of source control.

Chris Marisic
  • 32,487
  • 24
  • 164
  • 258