def _block_to_indices(block): if len(block) > 4: raise ValueError("block too big") # `menmonicode` uses little-endian numbers. num = from_base(256, reversed(block)) indices = list(reversed(to_base(1626, num))) # Pad the list of indices to the correct size. length = { 1: 1, 2: 2, 3: 3, 4: 3, }[len(block)] indices += [0] * (length - len(indices)) # The third byte in a block slightly leaks into the third word. A # different set of words is used for this case to distinguish it from the # four byte case. if len(block) == 3: indices[-1] += 1626 return indices
def _block_to_indices(block): if len(block) > 4: raise ValueError("block too big") # menmonicode uses little-endian numbers num = from_base(256, reversed(block)) indices = list(reversed(to_base(1626, num))) # pad the list of indices to the correct size length = { 1: 1, 2: 2, 3: 3, 4: 3, }[len(block)] indices += [0] * (length - len(indices)) # The third byte in a block slightly leaks into the third word. A # different set of words is used for this case to distinguish it from the # four byte case if len(block) == 3: indices[-1] += 1626 return indices
def _words_to_block(words): if not isinstance(words, tuple): raise TypeError("expected tuple of words") if len(words) == 0: raise ValueError("no words in block") if len(words) > 3: raise ValueError("too many words in block") try: indices = list(word_to_index(word) for word in words) except KeyError as e: raise ValueError("word not recognized") from e # calculate length of block. # both three byte and four byte blocks map to three words but can be # distinguished as a different word list is used to encode the last word # in the three byte case length = { 1: 1, 2: 2, 3: 3 if indices[-1] >= 1626 else 4, }[len(words)] if length == 3: indices[2] -= 1626 # check that words in the second word list don't appear anywhere else in # the block for index in indices: if index > 1626: raise ValueError( "unexpected three byte word: %s" % index_to_word(index) ) num = from_base(1626, reversed(indices)) block = bytes(reversed(to_base(256, num))) # pad to correct length return block.ljust(length, b'\x00')
def _words_to_block(words): if not isinstance(words, tuple): raise TypeError("expected tuple of words") if len(words) == 0: raise ValueError("no words in block") if len(words) > 3: raise ValueError("too many words in block") try: indices = list(word_to_index(word) for word in words) except KeyError as e: raise ValueError("word not recognized") from e # Calculate length of block. # Both three byte and four byte blocks map to three words but can be # distinguished as a different word list is used to encode the last word # in the three byte case. length = { 1: 1, 2: 2, 3: 3 if indices[-1] >= 1626 else 4, }[len(words)] if length == 3: indices[2] -= 1626 # Check that words in the second word list don't appear anywhere else in # the block. for index in indices: if index > 1626: raise ValueError(( "unexpected three byte word: {word!r}" ).format(word=index_to_word(index))) num = from_base(1626, reversed(indices)) block = bytes(reversed(to_base(256, num))) # Pad to correct length. return block.ljust(length, b'\x00')
def test_encode_base_ten(self): self.assertEqual([1, 2, 3, 4, 5, 6], to_base(10, 123456))
def test_encode_zero(self): self.assertEqual([], to_base(12, 0))