OAuth2 and LabVIEW — Revisited for 2020, A Bug in the SHA256 VI
In part one of this 2020 update, I began a journey of updating my OAuth2 example to use a new feature in LabVIEW 2020–the new hash function that supports SHA-256, among other algorithms.
Where I left off, I needed to modify the output of the new VI to create a byte array instead of converting it to a lowercase hex string.
I proposed three choices:
- Ignore the 2020 VI and just use the .Net implementation I used in 2019.
- In my SHA256.vi, add code after Byte Array Checksum.vi to convert the hex string back into a binary array.
- Make my own copy of Byte Array Checksum.vi and remove the subVI which converts to a lowercase string.
Which one did you choose? I decided to try all three. I already had #1, since it was the 2019 version. Here’s a quick and dirty implementation of #2, where I convert the hex string back to a byte array.
And here’s an implementation of #3, where I went and found the VI that called Bytes to Lowercase Hex String, made a copy of it, and removed the subVI call. I replaced it with a straight Byte Array to String.
What do you think so far? There are things I dislike about both #2 and #3.
- In #2, it seems wasteful to convert it to ASCII, and then convert it back. These aren’t large strings, but it just seems like a hack.
- In #3, I dislike the idea of modifying a vi.lib VI–especially one that’s not on the palettes.
I’m leaning towards #3, because it feels like the right implementation, even if it violates the “don’t mess with vi.lib VIs” principle.
Before I commit to a solution, let’s run the unit tests on each. The results for #1 pass with flying colors, of course. The results for both #2 and #3, though, fail. And I thought this was going to be easy. Keep reading below…
Here are the unit test results…
Test Case 3 failed. Let’s dig into it…
When I originally wrote this example, I searched the web for “SHA-256 test vectors” and found a few test vectors here:
https://www.di-mgt.com.au/sha_testvectors.html
The first five test vectors can be tested in LabVIEW, so I wrote unit tests for them. The first one, for example, hashes the string “abc”. The fifth one was a bit of a challenge–hash a string of a million characters. I wrote a helper VI to create a string containing one million letters ‘a’ to feed to SHA256.vi.
Anyway, test case 3 hashes a particular 448-bit string. This may seem like an unusual number, but the author of the test knows that this is a size that commonly trips up algorithm implementers. This shows the string (labelled “input message”) with the expected result for SHA-256 circled.
In fact, if I use my 2019 .Net implementation, I get exactly that result…
But if I use the new 2020 Byte Array Checksum.vi, it gets the wrong answer…
Just to be sure, I went and found some other SHA-256 test vectors (from NIST), and showed that they also failed for 448-bit inputs.
I’m not sure whether this affects other sizes of hash functions or other sizes of input. There’s a lot of shared code, so I’m not trusting any of these VIs right now. I confirmed that the same bug afflicts the File Checksum.vi in LabVIEW 2020.
You’ve probably guessed my answer to the question at the top: the implementation I’ve chosen for my OAuth2 example remains the 2019 implementation that uses .Net, since it’s the only one I have confidence in.
Important lesson learned: The unit tests I wrote months ago were invaluable for finding this problem.
In fact, when I first wrote the unit tests, I kind of wondered if it was worth it. I mean, if the algorithm works, it works, right? This attitude was reinforced by the fact that the tests never failed with the original .Net implementation. They only confirmed what I already knew: that the code worked.
Thus, writing tests seemed like busy work at the time–writing tests for the sake of writing tests. I hope you and I both see how naïve I was. I’ll reiterate that I’m grateful that I spent time writing unit tests.
I’ve reported the LabVIEW 2020 behavior to NI tech support late last week, but haven’t heard back. Meanwhile, the developer of the feature reached out after yesterday’s blog post, and he’s looking into it. I’ll report back here when I know more.
Update
Late last night, I heard from the NI software engineer who was looking into this. This morning, I tried the proposed fix and it worked for me. So, the good news is that NI is not only aware of the problem, but knows the cases that are affected and how to fix it. No promises, but I’d expect this to be fixed in NI’s next software update for LabVIEW 2020.
As an aside, I still haven’t heard from NI tech support, but I’ll fill them in when they get back to me. 🙂
Read the other articles in this series:
- Part One — Setting up a LabVIEW Web Service Callback Function
- Part Two — The Authentication Process
- Part Three — Improving the Example
- Part Four — Reusability
- OAuth2 and LabVIEW 2020, Using the New SHA256 VI
- OAuth2 and LabVIEW 2020, A Bug in the SHA256 VI
- OAuth2 and LabVIEW — A Bug in LabVIEW’s SSL Certificate Handling
- OAuth2 and LabVIEW 2020, Changes to the LabVIEW Web Servers
- OAuth2 and LabVIEW — Replacing the Web Server
For others interested in this issue: you can hotfix your own LabVIEW install by opening vi.lib\security\Message Digest\SHA-2\SHA-256\Pad.vi and changing the “0..56” Case Structure case to read “0..55”. This affects SHA-256 and SHA-224, and not any other hash functions. This affects all messages of size (n mod 64 == 56). You can refer to this issue as Bug 1054835 when contacting NI support.