A parity checksum is just the xor of all the bits in the word. The most efficient way to do this will have log(nbits) operations, because you can halve the number of bits you are dealing with on each iteration. For example:
def parity(word, nbits):
if nbits & (nbits - 1):
raise ValueError("nbits must be power of two")
while nbits > 1:
nbits >>= 1
word ^= (word >> nbits)
return word & 1
A longitudinal parity check is a bit different, because you stop when you get to a given word-size, at which point, your parity should be all zeros or all ones, rather than a single one or zero. I don't know whether you want odd or even parity, so this is a bit more general:
def longitudinal_parity(data, total_bits, word_bits, expected_parity=1):
"""
Performs longitudinal parity check
"""
for nbits in (total_bits, word_bits):
if nbits & (nbits - 1):
raise ValueError("bit size must be power of two")
mask = (1 << total_bits) - 1
while total_bits > word_bits:
total_bits >>= 1
data ^= (data >> total_bits)
mask >>= total_bits
data &= mask
return data == (mask if expected_parity else 0)
So for your example, the first parameter would be a 2048 bit integer, the total_bits would be 2048, the word_bits would be 64, and the desired parity would be 0 or 1.
I don't know anything about Diffie-Hellman's parity check, but if your parity is provided separately (seems likely), then you are comparing against a separate parity word rather than all ones or all zeroes. This is a minor tweak:
def longitudinal_parity(data, total_bits, word_bits, expected_parity):
"""
Performs longitudinal parity check
"""
for nbits in (total_bits, word_bits):
if nbits & (nbits - 1):
raise ValueError("bit size must be power of two")
mask = (1 << total_bits) - 1
while total_bits > word_bits:
total_bits >>= 1
data ^= (data >> total_bits)
mask >>= total_bits
data &= mask
return data == expected_parity
There are plenty of possible optimizations here, such as precalculating masks, starting the mask off at a smaller number, etc. Hopefully the code is readable.