heuer / segno

Python QR Code and Micro QR Code encoder
https://pypi.org/project/segno/
BSD 3-Clause "New" or "Revised" License
631 stars 54 forks source link

Malformed padding when number of bits is a multiple of 8 #123

Open simon-staal opened 1 year ago

simon-staal commented 1 year ago

There is a likely bug in the implementation when encoding 4-digit numbers into a 1-H QR code. This causes QR codes generated by segno to fail being captured when using BoofCV - see here

lessthanoptimal commented 1 year ago

Thought I would explain in some more detail since I'm the person claiming it's not a bug in the decoder but a bug in the encoder:

The padding that's added after the message is supposed to be added after the last byte. When the number of bits is divisible by 8 it starts it one byte after it should. The reason most encoders don't have an issue is that they ignore the padding bytes.

I suspect the code calculates the first byte that it should add padding using this formula:

paddingByte = bits/8 + 1

If you have a 12 bit message this will return byte 2, which is correct, but if you have a 16 bit message it will return 3, which is incorrect.

Illustration, '*' is a message bit, '-' is an unused bit

[********][****----][padding][padding]  <--- correct
[********][********][--------][padding] <-- wrong. skips first byte

Here's one possible correct formula

paddingBytes = bits/8 + (bits%8 == 0 ? 0 : 1)

heuer commented 1 year ago

Thanks for the information. I'll look into that end of next week

simon-staal commented 1 year ago

Just a quick update on this, the padding issue likely affects micro QR codes as well based on some of the testing I've done with those - obtaining the same errors with from 1-H codes above on M4-Q QR codes.