I cant verify seed generation if someone can see what is wrong
Question:
So i got this function that generates seeds makeseed() and now im trying to make a "verify" seed keep in mind that any seed generated IS Correct so i want it so that the user can input seeds and it’ll check if its valid or not.
here is my code
import random
def getchecksum(seed):
checksum = 0
while True:
checksum = (checksum + (seed & 0xFF)) & 0xFF
checksum = (2 * checksum + (checksum >> 7)) & 0xFF
seed >>= 5
if seed == 0:
break
return checksum
def makeseed():
seed = random.randint(1, 4294967295)
checksum = getchecksum(seed)
abc = "ABCDEFGHJKLMNPQRSTWXYZ01234V6789"
seedsprev = ((seed ^ 0xFEF7FFD) << 8) | checksum
finalseed = ""
for loopindex in range(0, 8):
finalseed = abc[seedsprev & 0x1F] + finalseed
seedsprev >>= 5
return finalseed
def is_valid_seed(seed):
"""
Checks if a seed is valid.
Args:
seed: The seed to check.
Returns:
True if the seed is valid, False otherwise.
"""
seed_length = len(seed)
if seed_length != 8:
return False
abc = "ABCDEFGHJKLMNPQRSTWXYZ01234V6789"
try:
seed_int = 0
for i in range(7, -1, -1):
seed_int <<= 5
seed_int |= abc.index(seed[i])
checksum = getchecksum(seed_int)
seed_int = ((seed_int ^ 0xFEF7FFD) << 8) | checksum
final_seed = ""
for _ in range(8):
final_seed = abc[seed_int & 0x1F] + final_seed
seed_int >>= 5
return final_seed == seed
except ValueError:
return False
ok = makeseed()
print(is_valid_seed(ok)) #to check if the function is correct
print(ok)
I tried to reverse what the makeseed did and i was expecting it to work but it didnt
Answers:
Your string encode/decode was bad because you reassembled the digits in reverse order. The best way to test for something like that is to split out the encode and decode to separate functions so you can run a unit test like decode(encode(x)) == x. I probably would have used an existing library like base32, base64 or just hexadecimal.
Your reversal of the checksum operations also didn’t actually reverse the operations. It just did some of the same math in the same order, not the reverse order.
The thing you need to check in is_valid_seed is whether the checksum actually checks out.
MY_ALPHABET = "ABCDEFGHJKLMNPQRSTWXYZ01234V6789"
def encode(seed: int) -> str:
encoded = ""
for _ in range(0, 8):
value = seed & 0x1F
seed >>= 5
encoded = MY_ALPHABET[value] + encoded
return encoded
def decode(encoded: bytes) -> int:
seed = 0
for digit in encoded:
value = MY_ALPHABET.index(digit)
seed <<= 5
seed += value
return seed
assert(99999 == decode(encode(99999)))
def getchecksum(seed: int):
checksum = 0
while True:
checksum = (checksum + (seed & 0xFF)) & 0xFF
checksum = (2 * checksum + (checksum >> 7)) & 0xFF
seed >>= 5
if seed == 0:
break
return checksum
def make_seed(seed: int):
checksum = getchecksum(seed)
seedsprev = ((seed ^ 0xFEF7FFD) << 8) | checksum
return encode(seedsprev)
def is_valid_seed(encoded: str):
seed = decode(encoded)
checksum = seed & 0xff
original_seed = (seed >> 8) ^ 0xFEF7FFD
return checksum == getchecksum(original_seed)
assert is_valid_seed(make_seed(7777))
assert not is_valid_seed('ABCDEFGH')
So i got this function that generates seeds makeseed() and now im trying to make a "verify" seed keep in mind that any seed generated IS Correct so i want it so that the user can input seeds and it’ll check if its valid or not.
here is my code
import random
def getchecksum(seed):
checksum = 0
while True:
checksum = (checksum + (seed & 0xFF)) & 0xFF
checksum = (2 * checksum + (checksum >> 7)) & 0xFF
seed >>= 5
if seed == 0:
break
return checksum
def makeseed():
seed = random.randint(1, 4294967295)
checksum = getchecksum(seed)
abc = "ABCDEFGHJKLMNPQRSTWXYZ01234V6789"
seedsprev = ((seed ^ 0xFEF7FFD) << 8) | checksum
finalseed = ""
for loopindex in range(0, 8):
finalseed = abc[seedsprev & 0x1F] + finalseed
seedsprev >>= 5
return finalseed
def is_valid_seed(seed):
"""
Checks if a seed is valid.
Args:
seed: The seed to check.
Returns:
True if the seed is valid, False otherwise.
"""
seed_length = len(seed)
if seed_length != 8:
return False
abc = "ABCDEFGHJKLMNPQRSTWXYZ01234V6789"
try:
seed_int = 0
for i in range(7, -1, -1):
seed_int <<= 5
seed_int |= abc.index(seed[i])
checksum = getchecksum(seed_int)
seed_int = ((seed_int ^ 0xFEF7FFD) << 8) | checksum
final_seed = ""
for _ in range(8):
final_seed = abc[seed_int & 0x1F] + final_seed
seed_int >>= 5
return final_seed == seed
except ValueError:
return False
ok = makeseed()
print(is_valid_seed(ok)) #to check if the function is correct
print(ok)
I tried to reverse what the makeseed did and i was expecting it to work but it didnt
Your string encode/decode was bad because you reassembled the digits in reverse order. The best way to test for something like that is to split out the encode and decode to separate functions so you can run a unit test like decode(encode(x)) == x. I probably would have used an existing library like base32, base64 or just hexadecimal.
Your reversal of the checksum operations also didn’t actually reverse the operations. It just did some of the same math in the same order, not the reverse order.
The thing you need to check in is_valid_seed is whether the checksum actually checks out.
MY_ALPHABET = "ABCDEFGHJKLMNPQRSTWXYZ01234V6789"
def encode(seed: int) -> str:
encoded = ""
for _ in range(0, 8):
value = seed & 0x1F
seed >>= 5
encoded = MY_ALPHABET[value] + encoded
return encoded
def decode(encoded: bytes) -> int:
seed = 0
for digit in encoded:
value = MY_ALPHABET.index(digit)
seed <<= 5
seed += value
return seed
assert(99999 == decode(encode(99999)))
def getchecksum(seed: int):
checksum = 0
while True:
checksum = (checksum + (seed & 0xFF)) & 0xFF
checksum = (2 * checksum + (checksum >> 7)) & 0xFF
seed >>= 5
if seed == 0:
break
return checksum
def make_seed(seed: int):
checksum = getchecksum(seed)
seedsprev = ((seed ^ 0xFEF7FFD) << 8) | checksum
return encode(seedsprev)
def is_valid_seed(encoded: str):
seed = decode(encoded)
checksum = seed & 0xff
original_seed = (seed >> 8) ^ 0xFEF7FFD
return checksum == getchecksum(original_seed)
assert is_valid_seed(make_seed(7777))
assert not is_valid_seed('ABCDEFGH')