doorcontrol: Fix Credential odd parity calculation

whoops!
This commit is contained in:
Adam Goldsmith 2024-09-01 21:35:58 -04:00
parent bde7828865
commit ee48d286c2
2 changed files with 23 additions and 5 deletions

View File

@ -25,15 +25,23 @@ class InvalidParity(InvalidHexCode):
class Credential: class Credential:
bits: bitstring.Bits bits: bitstring.Bits
@staticmethod
def even_parity(bits: bitstring.Bits) -> bool:
return bool(bits[7:19].count(1) % 2)
@staticmethod
def odd_parity(bits: bitstring.Bits) -> bool:
return (bits[19:31].count(1) % 2) == 0
@classmethod @classmethod
def from_code(cls, facility=int, card_number=int) -> "Credential": def from_code(cls, facility: int, card_number: int) -> "Credential":
bits = bitstring.pack( bits = bitstring.pack(
"0b000000, 0b0, uint:8=facility, uint:16=card_number, 0b0", "0b000000, 0b0, uint:8=facility, uint:16=card_number, 0b0",
facility=facility, facility=facility,
card_number=card_number, card_number=card_number,
) )
bits[6] = bits[7:19].count(1) % 2 # even parity bits[6] = cls.even_parity(bits)
bits[31] = bits[19:31].count(0) % 2 # odd parity bits[31] = cls.odd_parity(bits)
return cls(bitstring.Bits(bits)) return cls(bitstring.Bits(bits))
@classmethod @classmethod
@ -42,9 +50,9 @@ class Credential:
if bits[:6].any(1): if bits[:6].any(1):
raise Not26Bit(bits) raise Not26Bit(bits)
if bits[6] != bits[7:19].count(1) % 2: if bits[6] != cls.even_parity(bits):
raise InvalidParity(bits, "even") raise InvalidParity(bits, "even")
if bits[31] != (bits[19:31].count(0) % 2): if bits[31] != (cls.odd_parity(bits)):
raise InvalidParity(bits, "odd") raise InvalidParity(bits, "odd")
return cls(bits) return cls(bits)

View File

@ -18,3 +18,13 @@ class CredentialTestCase(TestCase):
cred = Credential.from_code(facility_code, card_number) cred = Credential.from_code(facility_code, card_number)
hex_cred = Credential.from_hex(cred.hex) hex_cred = Credential.from_hex(cred.hex)
self.assertEqual(cred, hex_cred) self.assertEqual(cred, hex_cred)
def test_example_numbers(self):
examples = [
(100, 12345, "02C86073"),
]
for facility_code, card_number, hex_number in examples:
code_cred = Credential.from_code(facility_code, card_number)
hex_cred = Credential.from_hex(hex_number)
self.assertEqual(code_cred, hex_cred)