Programming in C#, Java, and god knows what not

Web Server Certificate From a File

If one desires to run HTTPs server from C#, they might get the following warning:

Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date. To generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust'. For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.

And yes, once could follow instructions and have everything running. But where’s the fun in that?

Alternative approach would be to load certificate from the file and .NET makes that really easy.

private static X509Certificate2? GetCertificate() {
  var certFilename = Path.Combine(AppContext.BaseDirectory, "my.pfx");
  if (File.Exists(certFilename)) {
    try {
      return new X509Certificate2(certFilename);
    } catch (CryptographicException ex) {
      // log error or whatever
    }
  }
  return null;
}

So, when bringing server up we can just call it using something like this:

var cert = GetCertificate();
options.Listen(IPAddress.Any, 443, listenOptions => {
  listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
  if (cert != null) {
    listenOptions.UseHttps(cert);
  } else {
    listenOptions.UseHttps();
  }
});

Network Share Login via C#

Accessing remote share programmatically from Windows is easy. Just use \\machine\share notation and you’re golden. Except if you need to access it with a specific user. While PrincipalContext can often help, for samba shares hosted by Linux, that doesn’t necessarily work.

bool Login(string path, string user, string password) {
  var nr = new NativeMethods.NETRESOURCE {
    dwType = NativeMethods.RESOURCETYPE_DISK,
    lpRemoteName = path
  };
  var result = NativeMethods.WNetUseConnection(IntPtr.Zero, nr, password, name, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
  return (result == NativeMethods.NO_ERROR);
}

And, of course, we also need our definitions:

private static class NativeMethods {
    internal const Int32 NO_ERROR = 0;
    internal const Int32 RESOURCETYPE_DISK = 0x00000001;

    [StructLayout(LayoutKind.Sequential)]
    internal class NETRESOURCE {
        public Int32 dwScope = 0;
        public Int32 dwType = 0;
        public Int32 dwDisplayType = 0;
        public Int32 dwUsage = 0;
        public IntPtr lpLocalName;
        public String lpRemoteName;
        public IntPtr lpComment;
        public IntPtr lpProvider;
    }

    [DllImport("mpr.dll", CharSet = CharSet.Ansi)]
    internal static extern Int32 WNetUseConnection(
        IntPtr hwndOwner,
        NETRESOURCE lpNetResource,
        String lpPassword,
        String lpUserId,
        Int32 dwFlags,
        IntPtr lpAccessName,
        IntPtr lpBufferSize,
        IntPtr lpResult
    );

}

And that should be enough for access.

Web Server Certificate From a File

If you’re dealing with HTTPS on .NET 5, you might have seen the following message: Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date. Recommendation to solve this is also clear To generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust' And you’re pointed toward Microsoft docs for more information.

What’s not clear is that you can also load certificate from file and skip the whole system configuration - really useful if you don’t have the full system access. For that just configure your builder appropriately:

Builder = Host.CreateDefaultBuilder()
    .ConfigureWebHostDefaults(webBuilder => {
        webBuilder.ConfigureKestrel(options => {
        var cert = GetCertificate();
        options.Listen(IPAddress.Any, 443, listenOptions => {
            listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
            listenOptions.UseHttps(cert);
        });
    });
})
.Build();

In example code above, loading the certificate is done from GetCertificate function; something like this:

private static X509Certificate2 GetCertificate() {
    return new X509Certificate2("mycertificate.pfx", "");
}

Own Pwned

For a while now ';–have i been pwned? has been providing two services. One more known is informing people of data breaches. One slightly less known is their API. My personal favorite are their password search interface. So, I was really sad to see when Troy started charging for it.

While I understand Troy’s reasons, I used this API in freeware application. And yes, I could “swallow” $3.50 this service cost but I wasn’t willing to. My freeware hobby is already costing me enough. :)

Fortunately, Troy is allowing download of password hashes so one could easily make API on their own server. So, over a weekend I did. In my OwnPwned GitHub repository there’s everything you might need to create your own verification service. But there are some differences.

First of all, this is not a substitution for ';–have i been pwned? API as due to dependency on the data from it, it will ALWAYS be one step behind. Also, I haven’t implemented full API as I only needed the password verification portion. Even for password verification portion, I trimmed all extra data (e.g. password breach count) and focused only on passwords themselves.

To make use of the project, you first need to download the latest password dump (ordered by hash). Once you unpack that file, you would use PwnedRepack to convert this to a binary file. I found this step necessary for both speed (as you can use binary search) and for size (as it brought 25 GB file to slightly more manageable but still huge 12 GB).

With file in hand, there are two ways to search data. The first one would be PwnedServe application that will simply expose interface on localhost. Second way forward it serving PwnedPhp on Apache server. Either way, you can do k-anonymity search over a range using the first 5 hexadecimal characters of password’s SHA-1 hash.

Something like this /range/12345/.

And yes, code is not optimized and probably will never be due to the lack of free time on my side. But it does solve my issue. Your mileage may vary.


PS: Please note, Tray Hunt has opensourced some elements of HIBP with more to come. If you need fully-featured interface that’s probably what you should keep eye on.

Small C# InfluxDB client

Well, after doing InfluxDB client bash and Go, time came to do the same in C#.

I will not go too much into details as you can see the source code yourself. Suffice it to say it supports both v1 and v2 line protocol. And usage is simple as it gets:

var measurement = new InfluxMeasurement("Tick")
  .AddTag("t1", "Tag1")
  .AddTag("t2", "Tag2")
  .AddField("f1", 42)
  .AddField("f2", true);
client.Queue(measurement);

Source code is of course on GitHub and project is available and NuGet package.

The Minimal InfluxDB Client in Go

While you can get a proper InfluxDB client library for Go, sometime there’s no substitution for rolling one yourself - especially since InfluxDB’s Line Protocol is really easy.

It’s just a matter of constructing a correct URL and setting up just two headers. Something like this:

func sendInfluxData(line string, baseUrl string, org string, bucket string, token string) {
    var url string
    if len(org) > 0 {
        url = fmt.Sprintf("%s/api/v2/write?org=%s&bucket=%s",
			  baseUrl, org, bucket)
    } else {
        url = fmt.Sprintf("%s/api/v2/write?bucket=%s",
			  baseUrl, bucket)
    }

    request, _ := http.NewRequest("POST", url, strings.NewReader(line))
    request.Header.Set("Content-Type", "text/plain")
    if len(token) > 0 {
        request.Header.Set("Authorization", "Token " + token)
    }

    response, _ := http.DefaultClient.Do(request)
}

And yes, code doesn’t do error checking nor it has any comments. Deal with it. ;)

On Air

Illustration

Working from home requires a bit of synchronization between occupants. Especially if one member of family spends a lot of time on calls. Quite early into the work-at-home adventure, my wife found a solution. She bought a lighted “On Air” sign.

Idea was good. Whenever I am in conference call, I just light up the sign and everybody knows to keep quiet as our words are not private anymore. In reality most of the time I would either leave sign on longer than needed or forger to turn it off when I’m done speaking.

And pretty much all issues could be traced to the position of the sign. While it was visible to everybody else in the room, it wasn’t directly visible to me. And to make it more annoying, turning it off and on required me to get off the chair. Excellent for physical activity but annoying to do if I need to turn it on/off multiple times in a call.

So I decided to automatize this a bit.

I first repurposed one of the Wyze Plug devices I had around and went about looking for API. Unfortunately, Wyze doesn’t offer public API at this time but other people already reverse-engineered it. But alas, all those ports were outdated. Until I found a gem in comments. With those changes it was easy enough to make my own mini application.

While this would be enough for turning on/off the light, I was after something a bit more fine-grained. In quite a few conference calls I might not speak a lot. For them I just usually hit Mute Mic button on my Lenovo P70 and unmute only when I need to actually speak. So it seemed like a good compromise to only light up the sign when I am unmuted. If I’m muted, other family members can have their conversations without impacting my call.

And the following script was the last piece of the puzzle:

#!/bin/bash

LAST_MIC_STATUS=
while (true); do
  CURR_MIC_STATUS=`/usr/bin/amixer get Capture | grep -q '\[off\]' && echo 0 || echo 1`

  if [[ "$LAST_MIC_STATUS" != "$CURR_MIC_STATUS" ]]; then
    LAST_MIC_STATUS=$CURR_MIC_STATUS
    if [[ "$CURR_MIC_STATUS" -ne 0 ]]; then NEW_STATE=true; else NEW_STATE=false; fi

    WYZE_EMAIL="^^unknown@example.com^^" \
    WYZE_PASSWORD="^^changeme^^" \
    WyzePlugControl ^^2CAA8E6616D2^^ $NEW_STATE
  fi

  sleep 1
done

It will essentially just check for the status of my mute button and adjust Wyze Plug accordingly. At least until Wyze changes API again.

Always Pushing Tags

Tagging is nice but I always forget to push the darn things. And yes, I am one of those guys that push all local tags - so what? We’re all kinky in our ways.

There are many ways you can ensure you push tags with your regular push but my favorite is just editing .gitconfig. In the [remote "origin"] section I just add the following two lines:

push = +refs/heads/*:refs/heads/*
push = +refs/tags/*:refs/tags/*

Now each push will come with a bit of extra.

Couldn't Find a Valid ICU Package

As I ran my .NET 5 application on Linux, I was greeted with the following error:

Process terminated. Couldn't find a valid ICU package installed on the system. Set the configuration flag System.Globalization.Invariant to true if you want to run with no globalization support.
   at System.Environment.FailFast(System.String)
   at System.Globalization.GlobalizationMode.GetGlobalizationInvariantMode()
   at System.Globalization.GlobalizationMode..cctor()
   at System.Globalization.CultureData.CreateCultureWithInvariantData()
   at System.Globalization.CultureData.get_Invariant()
   at System.Globalization.CultureInfo..cctor()
   at System.Globalization.CultureInfo.get_CurrentCulture()
   at System.Globalization.NumberFormatInfo.get_CurrentInfo()
...
Aborted (core dumped)

Underlying cause was my ancient Red Hat installation missing localization support and the easy way to deal with it is was to simply set DOTNET_SYSTEM_GLOBALIZATION_INVARIANT environment variable. On command line that would look something like this:

DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 ./myprogram

However, if we really don’t need globalization support, setting it directly in .csproj might be better:

  <PropertyGroup>
    <InvariantGlobalization>true</InvariantGlobalization>
  </PropertyGroup>

Welford's Algorithm

Most of the time, general statistics calculations are easy. Take all data points you have, find the average, the standard deviation, and you have 90% of stuff you need to present a result in a reasonable and familiar manner. However, what if you have streaming data?

Well, then you have a Welford’s method. This magical algorithm enables you to calculate both average and standard deviation as data arrives without wasting a lot of memory accumulating it all.

So, of course, I wrote a C# code for it. To use it, just add something like this:

var stats = new WelfordVariance();
while(true) {
    stats.Add(something.getValue());
    output.SetMean(stats.Mean);
    output.SetStandardDeviation(stats.StandardDeviation);
}

Algorithm is not perfect and will sometime slightly differ from classically calculated standard deviation but it’s generally within a spitting distance and uses minimum of memory. It’s hard to find better bang-for-buck when it comes to large datasets.