I was able to discover the crux of the problem from last week. Previously, we were baffled by the fact that the size of the private key that is generated by the server application appears to much smaller than the private key that was generated by XCA, even though they both are using the same elliptic curve algorithm and key length. It turns out there is actually two ways of encoding an ECC key, i.e in a compressed format or an uncompressed format. I came to know about it through this discussion.
How do you determine whether a given key is compressed or uncompressed? For a 256 bit length public ECC key, the compressed format would result in a size of (32+1) bytes, whereas the uncompressed format gives (64+1) bytes in size. The reason for the uncompressed being at that size is because the key is a curve point represented by two coordinates, i.e two 256 bit values, while the compressed only needs one coordinate value. More on that here. There is also an additional byte at the start of the encoding which denotes whether the key is compressed or not compressed, which is why there is a +1 earlier. The uncompressed form is denoted by 0x04 whereas the compressed form is denoted by 0x02 or 0x03. You can clearly check whether a certificate is using a compressed or uncompressed key using the OpenSSL CLI as they encode the public key as a hexadecimal octet string.
Of course, that was just what I suspected to be the problem. To test it out, I first exported a private key from XCA, and then get the compressed form out of it instead using OpenSSL, since XCA uses the uncompressed format by default. I then import the key back into XCA, and got one of the certificates to use that compressed key and exported out a PKCS#12 containing the full certificate chain with it. I also exported another that uses the uncompressed as well. I tried to import both PKCS#12 using Microsoft Edge in Windows. It turns out that the one with the compressed key had the same exact problem as I had with Windows while on the other hand, the one with the uncompressed key had no issues. It’s the same thing for macOS as well. So that had to be the issue all along!
Botan actually provides a compressed encoding of the ECC key by default. I just have to change it such that it gives an uncompressed format instead. With the latest version of the library, that could easily be done by calling a method of the ECDSA class, however the version of the library we are using does not have that, and there is no convenient way to do it, from what I’ve seen so far. The version of the library that is packaged for Ubuntu 18.04 is of a slightly older version. Dr Shawn didn’t wanted to upgrade the library manually himself, as he would have to maintain it for future releases as well. The other option would be to use OpenSSL libraries to uncompress the ECC key just before the PKCS#12 gets created and exported.
We know what the problem is now, but how it should be implemented is the question now as well. I hope I’m able to get over this soon, as I am already behind schedule…