-
Notifications
You must be signed in to change notification settings - Fork 2
/
cli.py
executable file
·207 lines (163 loc) · 55.8 KB
/
cli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/env python3
import sympy
import functools
import operator
import random
import argparse
import itertools
import sys
import types
import math
system_random = random.SystemRandom()
# https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
prime_field = (2 ** 384) - (2 ** 128) - (2 ** 96) + (2 ** 32) - 1
# a hex number has 8 bytes
HEX_SIZE = 8
# a word encodes 11 bytes, since 2 ** 11 = 2048 (size of bip0039 wordlist)
WORD_SIZE = 11
# the prime field is 384 bits and we store (x, y) points of 384 bit numbers
# and so a shared secret is made up of 70 words, since 70 * 11 > 2 * 384 which means it can encode one point
SHARED_SECRET_WORD_LENGTH = 70
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'({hex(self.x)[2:]},\n {hex(self.y)[2:]})'
# cached here for faster execution
WORDLIST = ['abandon', 'ability', 'able', 'about', 'above', 'absent', 'absorb', 'abstract', 'absurd', 'abuse', 'access', 'accident', 'account', 'accuse', 'achieve', 'acid', 'acoustic', 'acquire', 'across', 'act', 'action', 'actor', 'actress', 'actual', 'adapt', 'add', 'addict', 'address', 'adjust', 'admit', 'adult', 'advance', 'advice', 'aerobic', 'affair', 'afford', 'afraid', 'again', 'age', 'agent', 'agree', 'ahead', 'aim', 'air', 'airport', 'aisle', 'alarm', 'album', 'alcohol', 'alert', 'alien', 'all', 'alley', 'allow', 'almost', 'alone', 'alpha', 'already', 'also', 'alter', 'always', 'amateur', 'amazing', 'among', 'amount', 'amused', 'analyst', 'anchor', 'ancient', 'anger', 'angle', 'angry', 'animal', 'ankle', 'announce', 'annual', 'another', 'answer', 'antenna', 'antique', 'anxiety', 'any', 'apart', 'apology', 'appear', 'apple', 'approve', 'april', 'arch', 'arctic', 'area', 'arena', 'argue', 'arm', 'armed', 'armor', 'army', 'around', 'arrange', 'arrest', 'arrive', 'arrow', 'art', 'artefact', 'artist', 'artwork', 'ask', 'aspect', 'assault', 'asset', 'assist', 'assume', 'asthma', 'athlete', 'atom', 'attack', 'attend', 'attitude', 'attract', 'auction', 'audit', 'august', 'aunt', 'author', 'auto', 'autumn', 'average', 'avocado', 'avoid', 'awake', 'aware', 'away', 'awesome', 'awful', 'awkward', 'axis', 'baby', 'bachelor', 'bacon', 'badge', 'bag', 'balance', 'balcony', 'ball', 'bamboo', 'banana', 'banner', 'bar', 'barely', 'bargain', 'barrel', 'base', 'basic', 'basket', 'battle', 'beach', 'bean', 'beauty', 'because', 'become', 'beef', 'before', 'begin', 'behave', 'behind', 'believe', 'below', 'belt', 'bench', 'benefit', 'best', 'betray', 'better', 'between', 'beyond', 'bicycle', 'bid', 'bike', 'bind', 'biology', 'bird', 'birth', 'bitter', 'black', 'blade', 'blame', 'blanket', 'blast', 'bleak', 'bless', 'blind', 'blood', 'blossom', 'blouse', 'blue', 'blur', 'blush', 'board', 'boat', 'body', 'boil', 'bomb', 'bone', 'bonus', 'book', 'boost', 'border', 'boring', 'borrow', 'boss', 'bottom', 'bounce', 'box', 'boy', 'bracket', 'brain', 'brand', 'brass', 'brave', 'bread', 'breeze', 'brick', 'bridge', 'brief', 'bright', 'bring', 'brisk', 'broccoli', 'broken', 'bronze', 'broom', 'brother', 'brown', 'brush', 'bubble', 'buddy', 'budget', 'buffalo', 'build', 'bulb', 'bulk', 'bullet', 'bundle', 'bunker', 'burden', 'burger', 'burst', 'bus', 'business', 'busy', 'butter', 'buyer', 'buzz', 'cabbage', 'cabin', 'cable', 'cactus', 'cage', 'cake', 'call', 'calm', 'camera', 'camp', 'can', 'canal', 'cancel', 'candy', 'cannon', 'canoe', 'canvas', 'canyon', 'capable', 'capital', 'captain', 'car', 'carbon', 'card', 'cargo', 'carpet', 'carry', 'cart', 'case', 'cash', 'casino', 'castle', 'casual', 'cat', 'catalog', 'catch', 'category', 'cattle', 'caught', 'cause', 'caution', 'cave', 'ceiling', 'celery', 'cement', 'census', 'century', 'cereal', 'certain', 'chair', 'chalk', 'champion', 'change', 'chaos', 'chapter', 'charge', 'chase', 'chat', 'cheap', 'check', 'cheese', 'chef', 'cherry', 'chest', 'chicken', 'chief', 'child', 'chimney', 'choice', 'choose', 'chronic', 'chuckle', 'chunk', 'churn', 'cigar', 'cinnamon', 'circle', 'citizen', 'city', 'civil', 'claim', 'clap', 'clarify', 'claw', 'clay', 'clean', 'clerk', 'clever', 'click', 'client', 'cliff', 'climb', 'clinic', 'clip', 'clock', 'clog', 'close', 'cloth', 'cloud', 'clown', 'club', 'clump', 'cluster', 'clutch', 'coach', 'coast', 'coconut', 'code', 'coffee', 'coil', 'coin', 'collect', 'color', 'column', 'combine', 'come', 'comfort', 'comic', 'common', 'company', 'concert', 'conduct', 'confirm', 'congress', 'connect', 'consider', 'control', 'convince', 'cook', 'cool', 'copper', 'copy', 'coral', 'core', 'corn', 'correct', 'cost', 'cotton', 'couch', 'country', 'couple', 'course', 'cousin', 'cover', 'coyote', 'crack', 'cradle', 'craft', 'cram', 'crane', 'crash', 'crater', 'crawl', 'crazy', 'cream', 'credit', 'creek', 'crew', 'cricket', 'crime', 'crisp', 'critic', 'crop', 'cross', 'crouch', 'crowd', 'crucial', 'cruel', 'cruise', 'crumble', 'crunch', 'crush', 'cry', 'crystal', 'cube', 'culture', 'cup', 'cupboard', 'curious', 'current', 'curtain', 'curve', 'cushion', 'custom', 'cute', 'cycle', 'dad', 'damage', 'damp', 'dance', 'danger', 'daring', 'dash', 'daughter', 'dawn', 'day', 'deal', 'debate', 'debris', 'decade', 'december', 'decide', 'decline', 'decorate', 'decrease', 'deer', 'defense', 'define', 'defy', 'degree', 'delay', 'deliver', 'demand', 'demise', 'denial', 'dentist', 'deny', 'depart', 'depend', 'deposit', 'depth', 'deputy', 'derive', 'describe', 'desert', 'design', 'desk', 'despair', 'destroy', 'detail', 'detect', 'develop', 'device', 'devote', 'diagram', 'dial', 'diamond', 'diary', 'dice', 'diesel', 'diet', 'differ', 'digital', 'dignity', 'dilemma', 'dinner', 'dinosaur', 'direct', 'dirt', 'disagree', 'discover', 'disease', 'dish', 'dismiss', 'disorder', 'display', 'distance', 'divert', 'divide', 'divorce', 'dizzy', 'doctor', 'document', 'dog', 'doll', 'dolphin', 'domain', 'donate', 'donkey', 'donor', 'door', 'dose', 'double', 'dove', 'draft', 'dragon', 'drama', 'drastic', 'draw', 'dream', 'dress', 'drift', 'drill', 'drink', 'drip', 'drive', 'drop', 'drum', 'dry', 'duck', 'dumb', 'dune', 'during', 'dust', 'dutch', 'duty', 'dwarf', 'dynamic', 'eager', 'eagle', 'early', 'earn', 'earth', 'easily', 'east', 'easy', 'echo', 'ecology', 'economy', 'edge', 'edit', 'educate', 'effort', 'egg', 'eight', 'either', 'elbow', 'elder', 'electric', 'elegant', 'element', 'elephant', 'elevator', 'elite', 'else', 'embark', 'embody', 'embrace', 'emerge', 'emotion', 'employ', 'empower', 'empty', 'enable', 'enact', 'end', 'endless', 'endorse', 'enemy', 'energy', 'enforce', 'engage', 'engine', 'enhance', 'enjoy', 'enlist', 'enough', 'enrich', 'enroll', 'ensure', 'enter', 'entire', 'entry', 'envelope', 'episode', 'equal', 'equip', 'era', 'erase', 'erode', 'erosion', 'error', 'erupt', 'escape', 'essay', 'essence', 'estate', 'eternal', 'ethics', 'evidence', 'evil', 'evoke', 'evolve', 'exact', 'example', 'excess', 'exchange', 'excite', 'exclude', 'excuse', 'execute', 'exercise', 'exhaust', 'exhibit', 'exile', 'exist', 'exit', 'exotic', 'expand', 'expect', 'expire', 'explain', 'expose', 'express', 'extend', 'extra', 'eye', 'eyebrow', 'fabric', 'face', 'faculty', 'fade', 'faint', 'faith', 'fall', 'false', 'fame', 'family', 'famous', 'fan', 'fancy', 'fantasy', 'farm', 'fashion', 'fat', 'fatal', 'father', 'fatigue', 'fault', 'favorite', 'feature', 'february', 'federal', 'fee', 'feed', 'feel', 'female', 'fence', 'festival', 'fetch', 'fever', 'few', 'fiber', 'fiction', 'field', 'figure', 'file', 'film', 'filter', 'final', 'find', 'fine', 'finger', 'finish', 'fire', 'firm', 'first', 'fiscal', 'fish', 'fit', 'fitness', 'fix', 'flag', 'flame', 'flash', 'flat', 'flavor', 'flee', 'flight', 'flip', 'float', 'flock', 'floor', 'flower', 'fluid', 'flush', 'fly', 'foam', 'focus', 'fog', 'foil', 'fold', 'follow', 'food', 'foot', 'force', 'forest', 'forget', 'fork', 'fortune', 'forum', 'forward', 'fossil', 'foster', 'found', 'fox', 'fragile', 'frame', 'frequent', 'fresh', 'friend', 'fringe', 'frog', 'front', 'frost', 'frown', 'frozen', 'fruit', 'fuel', 'fun', 'funny', 'furnace', 'fury', 'future', 'gadget', 'gain', 'galaxy', 'gallery', 'game', 'gap', 'garage', 'garbage', 'garden', 'garlic', 'garment', 'gas', 'gasp', 'gate', 'gather', 'gauge', 'gaze', 'general', 'genius', 'genre', 'gentle', 'genuine', 'gesture', 'ghost', 'giant', 'gift', 'giggle', 'ginger', 'giraffe', 'girl', 'give', 'glad', 'glance', 'glare', 'glass', 'glide', 'glimpse', 'globe', 'gloom', 'glory', 'glove', 'glow', 'glue', 'goat', 'goddess', 'gold', 'good', 'goose', 'gorilla', 'gospel', 'gossip', 'govern', 'gown', 'grab', 'grace', 'grain', 'grant', 'grape', 'grass', 'gravity', 'great', 'green', 'grid', 'grief', 'grit', 'grocery', 'group', 'grow', 'grunt', 'guard', 'guess', 'guide', 'guilt', 'guitar', 'gun', 'gym', 'habit', 'hair', 'half', 'hammer', 'hamster', 'hand', 'happy', 'harbor', 'hard', 'harsh', 'harvest', 'hat', 'have', 'hawk', 'hazard', 'head', 'health', 'heart', 'heavy', 'hedgehog', 'height', 'hello', 'helmet', 'help', 'hen', 'hero', 'hidden', 'high', 'hill', 'hint', 'hip', 'hire', 'history', 'hobby', 'hockey', 'hold', 'hole', 'holiday', 'hollow', 'home', 'honey', 'hood', 'hope', 'horn', 'horror', 'horse', 'hospital', 'host', 'hotel', 'hour', 'hover', 'hub', 'huge', 'human', 'humble', 'humor', 'hundred', 'hungry', 'hunt', 'hurdle', 'hurry', 'hurt', 'husband', 'hybrid', 'ice', 'icon', 'idea', 'identify', 'idle', 'ignore', 'ill', 'illegal', 'illness', 'image', 'imitate', 'immense', 'immune', 'impact', 'impose', 'improve', 'impulse', 'inch', 'include', 'income', 'increase', 'index', 'indicate', 'indoor', 'industry', 'infant', 'inflict', 'inform', 'inhale', 'inherit', 'initial', 'inject', 'injury', 'inmate', 'inner', 'innocent', 'input', 'inquiry', 'insane', 'insect', 'inside', 'inspire', 'install', 'intact', 'interest', 'into', 'invest', 'invite', 'involve', 'iron', 'island', 'isolate', 'issue', 'item', 'ivory', 'jacket', 'jaguar', 'jar', 'jazz', 'jealous', 'jeans', 'jelly', 'jewel', 'job', 'join', 'joke', 'journey', 'joy', 'judge', 'juice', 'jump', 'jungle', 'junior', 'junk', 'just', 'kangaroo', 'keen', 'keep', 'ketchup', 'key', 'kick', 'kid', 'kidney', 'kind', 'kingdom', 'kiss', 'kit', 'kitchen', 'kite', 'kitten', 'kiwi', 'knee', 'knife', 'knock', 'know', 'lab', 'label', 'labor', 'ladder', 'lady', 'lake', 'lamp', 'language', 'laptop', 'large', 'later', 'latin', 'laugh', 'laundry', 'lava', 'law', 'lawn', 'lawsuit', 'layer', 'lazy', 'leader', 'leaf', 'learn', 'leave', 'lecture', 'left', 'leg', 'legal', 'legend', 'leisure', 'lemon', 'lend', 'length', 'lens', 'leopard', 'lesson', 'letter', 'level', 'liar', 'liberty', 'library', 'license', 'life', 'lift', 'light', 'like', 'limb', 'limit', 'link', 'lion', 'liquid', 'list', 'little', 'live', 'lizard', 'load', 'loan', 'lobster', 'local', 'lock', 'logic', 'lonely', 'long', 'loop', 'lottery', 'loud', 'lounge', 'love', 'loyal', 'lucky', 'luggage', 'lumber', 'lunar', 'lunch', 'luxury', 'lyrics', 'machine', 'mad', 'magic', 'magnet', 'maid', 'mail', 'main', 'major', 'make', 'mammal', 'man', 'manage', 'mandate', 'mango', 'mansion', 'manual', 'maple', 'marble', 'march', 'margin', 'marine', 'market', 'marriage', 'mask', 'mass', 'master', 'match', 'material', 'math', 'matrix', 'matter', 'maximum', 'maze', 'meadow', 'mean', 'measure', 'meat', 'mechanic', 'medal', 'media', 'melody', 'melt', 'member', 'memory', 'mention', 'menu', 'mercy', 'merge', 'merit', 'merry', 'mesh', 'message', 'metal', 'method', 'middle', 'midnight', 'milk', 'million', 'mimic', 'mind', 'minimum', 'minor', 'minute', 'miracle', 'mirror', 'misery', 'miss', 'mistake', 'mix', 'mixed', 'mixture', 'mobile', 'model', 'modify', 'mom', 'moment', 'monitor', 'monkey', 'monster', 'month', 'moon', 'moral', 'more', 'morning', 'mosquito', 'mother', 'motion', 'motor', 'mountain', 'mouse', 'move', 'movie', 'much', 'muffin', 'mule', 'multiply', 'muscle', 'museum', 'mushroom', 'music', 'must', 'mutual', 'myself', 'mystery', 'myth', 'naive', 'name', 'napkin', 'narrow', 'nasty', 'nation', 'nature', 'near', 'neck', 'need', 'negative', 'neglect', 'neither', 'nephew', 'nerve', 'nest', 'net', 'network', 'neutral', 'never', 'news', 'next', 'nice', 'night', 'noble', 'noise', 'nominee', 'noodle', 'normal', 'north', 'nose', 'notable', 'note', 'nothing', 'notice', 'novel', 'now', 'nuclear', 'number', 'nurse', 'nut', 'oak', 'obey', 'object', 'oblige', 'obscure', 'observe', 'obtain', 'obvious', 'occur', 'ocean', 'october', 'odor', 'off', 'offer', 'office', 'often', 'oil', 'okay', 'old', 'olive', 'olympic', 'omit', 'once', 'one', 'onion', 'online', 'only', 'open', 'opera', 'opinion', 'oppose', 'option', 'orange', 'orbit', 'orchard', 'order', 'ordinary', 'organ', 'orient', 'original', 'orphan', 'ostrich', 'other', 'outdoor', 'outer', 'output', 'outside', 'oval', 'oven', 'over', 'own', 'owner', 'oxygen', 'oyster', 'ozone', 'pact', 'paddle', 'page', 'pair', 'palace', 'palm', 'panda', 'panel', 'panic', 'panther', 'paper', 'parade', 'parent', 'park', 'parrot', 'party', 'pass', 'patch', 'path', 'patient', 'patrol', 'pattern', 'pause', 'pave', 'payment', 'peace', 'peanut', 'pear', 'peasant', 'pelican', 'pen', 'penalty', 'pencil', 'people', 'pepper', 'perfect', 'permit', 'person', 'pet', 'phone', 'photo', 'phrase', 'physical', 'piano', 'picnic', 'picture', 'piece', 'pig', 'pigeon', 'pill', 'pilot', 'pink', 'pioneer', 'pipe', 'pistol', 'pitch', 'pizza', 'place', 'planet', 'plastic', 'plate', 'play', 'please', 'pledge', 'pluck', 'plug', 'plunge', 'poem', 'poet', 'point', 'polar', 'pole', 'police', 'pond', 'pony', 'pool', 'popular', 'portion', 'position', 'possible', 'post', 'potato', 'pottery', 'poverty', 'powder', 'power', 'practice', 'praise', 'predict', 'prefer', 'prepare', 'present', 'pretty', 'prevent', 'price', 'pride', 'primary', 'print', 'priority', 'prison', 'private', 'prize', 'problem', 'process', 'produce', 'profit', 'program', 'project', 'promote', 'proof', 'property', 'prosper', 'protect', 'proud', 'provide', 'public', 'pudding', 'pull', 'pulp', 'pulse', 'pumpkin', 'punch', 'pupil', 'puppy', 'purchase', 'purity', 'purpose', 'purse', 'push', 'put', 'puzzle', 'pyramid', 'quality', 'quantum', 'quarter', 'question', 'quick', 'quit', 'quiz', 'quote', 'rabbit', 'raccoon', 'race', 'rack', 'radar', 'radio', 'rail', 'rain', 'raise', 'rally', 'ramp', 'ranch', 'random', 'range', 'rapid', 'rare', 'rate', 'rather', 'raven', 'raw', 'razor', 'ready', 'real', 'reason', 'rebel', 'rebuild', 'recall', 'receive', 'recipe', 'record', 'recycle', 'reduce', 'reflect', 'reform', 'refuse', 'region', 'regret', 'regular', 'reject', 'relax', 'release', 'relief', 'rely', 'remain', 'remember', 'remind', 'remove', 'render', 'renew', 'rent', 'reopen', 'repair', 'repeat', 'replace', 'report', 'require', 'rescue', 'resemble', 'resist', 'resource', 'response', 'result', 'retire', 'retreat', 'return', 'reunion', 'reveal', 'review', 'reward', 'rhythm', 'rib', 'ribbon', 'rice', 'rich', 'ride', 'ridge', 'rifle', 'right', 'rigid', 'ring', 'riot', 'ripple', 'risk', 'ritual', 'rival', 'river', 'road', 'roast', 'robot', 'robust', 'rocket', 'romance', 'roof', 'rookie', 'room', 'rose', 'rotate', 'rough', 'round', 'route', 'royal', 'rubber', 'rude', 'rug', 'rule', 'run', 'runway', 'rural', 'sad', 'saddle', 'sadness', 'safe', 'sail', 'salad', 'salmon', 'salon', 'salt', 'salute', 'same', 'sample', 'sand', 'satisfy', 'satoshi', 'sauce', 'sausage', 'save', 'say', 'scale', 'scan', 'scare', 'scatter', 'scene', 'scheme', 'school', 'science', 'scissors', 'scorpion', 'scout', 'scrap', 'screen', 'script', 'scrub', 'sea', 'search', 'season', 'seat', 'second', 'secret', 'section', 'security', 'seed', 'seek', 'segment', 'select', 'sell', 'seminar', 'senior', 'sense', 'sentence', 'series', 'service', 'session', 'settle', 'setup', 'seven', 'shadow', 'shaft', 'shallow', 'share', 'shed', 'shell', 'sheriff', 'shield', 'shift', 'shine', 'ship', 'shiver', 'shock', 'shoe', 'shoot', 'shop', 'short', 'shoulder', 'shove', 'shrimp', 'shrug', 'shuffle', 'shy', 'sibling', 'sick', 'side', 'siege', 'sight', 'sign', 'silent', 'silk', 'silly', 'silver', 'similar', 'simple', 'since', 'sing', 'siren', 'sister', 'situate', 'six', 'size', 'skate', 'sketch', 'ski', 'skill', 'skin', 'skirt', 'skull', 'slab', 'slam', 'sleep', 'slender', 'slice', 'slide', 'slight', 'slim', 'slogan', 'slot', 'slow', 'slush', 'small', 'smart', 'smile', 'smoke', 'smooth', 'snack', 'snake', 'snap', 'sniff', 'snow', 'soap', 'soccer', 'social', 'sock', 'soda', 'soft', 'solar', 'soldier', 'solid', 'solution', 'solve', 'someone', 'song', 'soon', 'sorry', 'sort', 'soul', 'sound', 'soup', 'source', 'south', 'space', 'spare', 'spatial', 'spawn', 'speak', 'special', 'speed', 'spell', 'spend', 'sphere', 'spice', 'spider', 'spike', 'spin', 'spirit', 'split', 'spoil', 'sponsor', 'spoon', 'sport', 'spot', 'spray', 'spread', 'spring', 'spy', 'square', 'squeeze', 'squirrel', 'stable', 'stadium', 'staff', 'stage', 'stairs', 'stamp', 'stand', 'start', 'state', 'stay', 'steak', 'steel', 'stem', 'step', 'stereo', 'stick', 'still', 'sting', 'stock', 'stomach', 'stone', 'stool', 'story', 'stove', 'strategy', 'street', 'strike', 'strong', 'struggle', 'student', 'stuff', 'stumble', 'style', 'subject', 'submit', 'subway', 'success', 'such', 'sudden', 'suffer', 'sugar', 'suggest', 'suit', 'summer', 'sun', 'sunny', 'sunset', 'super', 'supply', 'supreme', 'sure', 'surface', 'surge', 'surprise', 'surround', 'survey', 'suspect', 'sustain', 'swallow', 'swamp', 'swap', 'swarm', 'swear', 'sweet', 'swift', 'swim', 'swing', 'switch', 'sword', 'symbol', 'symptom', 'syrup', 'system', 'table', 'tackle', 'tag', 'tail', 'talent', 'talk', 'tank', 'tape', 'target', 'task', 'taste', 'tattoo', 'taxi', 'teach', 'team', 'tell', 'ten', 'tenant', 'tennis', 'tent', 'term', 'test', 'text', 'thank', 'that', 'theme', 'then', 'theory', 'there', 'they', 'thing', 'this', 'thought', 'three', 'thrive', 'throw', 'thumb', 'thunder', 'ticket', 'tide', 'tiger', 'tilt', 'timber', 'time', 'tiny', 'tip', 'tired', 'tissue', 'title', 'toast', 'tobacco', 'today', 'toddler', 'toe', 'together', 'toilet', 'token', 'tomato', 'tomorrow', 'tone', 'tongue', 'tonight', 'tool', 'tooth', 'top', 'topic', 'topple', 'torch', 'tornado', 'tortoise', 'toss', 'total', 'tourist', 'toward', 'tower', 'town', 'toy', 'track', 'trade', 'traffic', 'tragic', 'train', 'transfer', 'trap', 'trash', 'travel', 'tray', 'treat', 'tree', 'trend', 'trial', 'tribe', 'trick', 'trigger', 'trim', 'trip', 'trophy', 'trouble', 'truck', 'true', 'truly', 'trumpet', 'trust', 'truth', 'try', 'tube', 'tuition', 'tumble', 'tuna', 'tunnel', 'turkey', 'turn', 'turtle', 'twelve', 'twenty', 'twice', 'twin', 'twist', 'two', 'type', 'typical', 'ugly', 'umbrella', 'unable', 'unaware', 'uncle', 'uncover', 'under', 'undo', 'unfair', 'unfold', 'unhappy', 'uniform', 'unique', 'unit', 'universe', 'unknown', 'unlock', 'until', 'unusual', 'unveil', 'update', 'upgrade', 'uphold', 'upon', 'upper', 'upset', 'urban', 'urge', 'usage', 'use', 'used', 'useful', 'useless', 'usual', 'utility', 'vacant', 'vacuum', 'vague', 'valid', 'valley', 'valve', 'van', 'vanish', 'vapor', 'various', 'vast', 'vault', 'vehicle', 'velvet', 'vendor', 'venture', 'venue', 'verb', 'verify', 'version', 'very', 'vessel', 'veteran', 'viable', 'vibrant', 'vicious', 'victory', 'video', 'view', 'village', 'vintage', 'violin', 'virtual', 'virus', 'visa', 'visit', 'visual', 'vital', 'vivid', 'vocal', 'voice', 'void', 'volcano', 'volume', 'vote', 'voyage', 'wage', 'wagon', 'wait', 'walk', 'wall', 'walnut', 'want', 'warfare', 'warm', 'warrior', 'wash', 'wasp', 'waste', 'water', 'wave', 'way', 'wealth', 'weapon', 'wear', 'weasel', 'weather', 'web', 'wedding', 'weekend', 'weird', 'welcome', 'west', 'wet', 'whale', 'what', 'wheat', 'wheel', 'when', 'where', 'whip', 'whisper', 'wide', 'width', 'wife', 'wild', 'will', 'win', 'window', 'wine', 'wing', 'wink', 'winner', 'winter', 'wire', 'wisdom', 'wise', 'wish', 'witness', 'wolf', 'woman', 'wonder', 'wood', 'wool', 'word', 'work', 'world', 'worry', 'worth', 'wrap', 'wreck', 'wrestle', 'wrist', 'write', 'wrong', 'yard', 'year', 'yellow', 'you', 'young', 'youth', 'zebra', 'zero', 'zone', 'zoo']
INDEXED_WORDS = {'abandon': 0, 'ability': 1, 'able': 2, 'about': 3, 'above': 4, 'absent': 5, 'absorb': 6, 'abstract': 7, 'absurd': 8, 'abuse': 9, 'access': 10, 'accident': 11, 'account': 12, 'accuse': 13, 'achieve': 14, 'acid': 15, 'acoustic': 16, 'acquire': 17, 'across': 18, 'act': 19, 'action': 20, 'actor': 21, 'actress': 22, 'actual': 23, 'adapt': 24, 'add': 25, 'addict': 26, 'address': 27, 'adjust': 28, 'admit': 29, 'adult': 30, 'advance': 31, 'advice': 32, 'aerobic': 33, 'affair': 34, 'afford': 35, 'afraid': 36, 'again': 37, 'age': 38, 'agent': 39, 'agree': 40, 'ahead': 41, 'aim': 42, 'air': 43, 'airport': 44, 'aisle': 45, 'alarm': 46, 'album': 47, 'alcohol': 48, 'alert': 49, 'alien': 50, 'all': 51, 'alley': 52, 'allow': 53, 'almost': 54, 'alone': 55, 'alpha': 56, 'already': 57, 'also': 58, 'alter': 59, 'always': 60, 'amateur': 61, 'amazing': 62, 'among': 63, 'amount': 64, 'amused': 65, 'analyst': 66, 'anchor': 67, 'ancient': 68, 'anger': 69, 'angle': 70, 'angry': 71, 'animal': 72, 'ankle': 73, 'announce': 74, 'annual': 75, 'another': 76, 'answer': 77, 'antenna': 78, 'antique': 79, 'anxiety': 80, 'any': 81, 'apart': 82, 'apology': 83, 'appear': 84, 'apple': 85, 'approve': 86, 'april': 87, 'arch': 88, 'arctic': 89, 'area': 90, 'arena': 91, 'argue': 92, 'arm': 93, 'armed': 94, 'armor': 95, 'army': 96, 'around': 97, 'arrange': 98, 'arrest': 99, 'arrive': 100, 'arrow': 101, 'art': 102, 'artefact': 103, 'artist': 104, 'artwork': 105, 'ask': 106, 'aspect': 107, 'assault': 108, 'asset': 109, 'assist': 110, 'assume': 111, 'asthma': 112, 'athlete': 113, 'atom': 114, 'attack': 115, 'attend': 116, 'attitude': 117, 'attract': 118, 'auction': 119, 'audit': 120, 'august': 121, 'aunt': 122, 'author': 123, 'auto': 124, 'autumn': 125, 'average': 126, 'avocado': 127, 'avoid': 128, 'awake': 129, 'aware': 130, 'away': 131, 'awesome': 132, 'awful': 133, 'awkward': 134, 'axis': 135, 'baby': 136, 'bachelor': 137, 'bacon': 138, 'badge': 139, 'bag': 140, 'balance': 141, 'balcony': 142, 'ball': 143, 'bamboo': 144, 'banana': 145, 'banner': 146, 'bar': 147, 'barely': 148, 'bargain': 149, 'barrel': 150, 'base': 151, 'basic': 152, 'basket': 153, 'battle': 154, 'beach': 155, 'bean': 156, 'beauty': 157, 'because': 158, 'become': 159, 'beef': 160, 'before': 161, 'begin': 162, 'behave': 163, 'behind': 164, 'believe': 165, 'below': 166, 'belt': 167, 'bench': 168, 'benefit': 169, 'best': 170, 'betray': 171, 'better': 172, 'between': 173, 'beyond': 174, 'bicycle': 175, 'bid': 176, 'bike': 177, 'bind': 178, 'biology': 179, 'bird': 180, 'birth': 181, 'bitter': 182, 'black': 183, 'blade': 184, 'blame': 185, 'blanket': 186, 'blast': 187, 'bleak': 188, 'bless': 189, 'blind': 190, 'blood': 191, 'blossom': 192, 'blouse': 193, 'blue': 194, 'blur': 195, 'blush': 196, 'board': 197, 'boat': 198, 'body': 199, 'boil': 200, 'bomb': 201, 'bone': 202, 'bonus': 203, 'book': 204, 'boost': 205, 'border': 206, 'boring': 207, 'borrow': 208, 'boss': 209, 'bottom': 210, 'bounce': 211, 'box': 212, 'boy': 213, 'bracket': 214, 'brain': 215, 'brand': 216, 'brass': 217, 'brave': 218, 'bread': 219, 'breeze': 220, 'brick': 221, 'bridge': 222, 'brief': 223, 'bright': 224, 'bring': 225, 'brisk': 226, 'broccoli': 227, 'broken': 228, 'bronze': 229, 'broom': 230, 'brother': 231, 'brown': 232, 'brush': 233, 'bubble': 234, 'buddy': 235, 'budget': 236, 'buffalo': 237, 'build': 238, 'bulb': 239, 'bulk': 240, 'bullet': 241, 'bundle': 242, 'bunker': 243, 'burden': 244, 'burger': 245, 'burst': 246, 'bus': 247, 'business': 248, 'busy': 249, 'butter': 250, 'buyer': 251, 'buzz': 252, 'cabbage': 253, 'cabin': 254, 'cable': 255, 'cactus': 256, 'cage': 257, 'cake': 258, 'call': 259, 'calm': 260, 'camera': 261, 'camp': 262, 'can': 263, 'canal': 264, 'cancel': 265, 'candy': 266, 'cannon': 267, 'canoe': 268, 'canvas': 269, 'canyon': 270, 'capable': 271, 'capital': 272, 'captain': 273, 'car': 274, 'carbon': 275, 'card': 276, 'cargo': 277, 'carpet': 278, 'carry': 279, 'cart': 280, 'case': 281, 'cash': 282, 'casino': 283, 'castle': 284, 'casual': 285, 'cat': 286, 'catalog': 287, 'catch': 288, 'category': 289, 'cattle': 290, 'caught': 291, 'cause': 292, 'caution': 293, 'cave': 294, 'ceiling': 295, 'celery': 296, 'cement': 297, 'census': 298, 'century': 299, 'cereal': 300, 'certain': 301, 'chair': 302, 'chalk': 303, 'champion': 304, 'change': 305, 'chaos': 306, 'chapter': 307, 'charge': 308, 'chase': 309, 'chat': 310, 'cheap': 311, 'check': 312, 'cheese': 313, 'chef': 314, 'cherry': 315, 'chest': 316, 'chicken': 317, 'chief': 318, 'child': 319, 'chimney': 320, 'choice': 321, 'choose': 322, 'chronic': 323, 'chuckle': 324, 'chunk': 325, 'churn': 326, 'cigar': 327, 'cinnamon': 328, 'circle': 329, 'citizen': 330, 'city': 331, 'civil': 332, 'claim': 333, 'clap': 334, 'clarify': 335, 'claw': 336, 'clay': 337, 'clean': 338, 'clerk': 339, 'clever': 340, 'click': 341, 'client': 342, 'cliff': 343, 'climb': 344, 'clinic': 345, 'clip': 346, 'clock': 347, 'clog': 348, 'close': 349, 'cloth': 350, 'cloud': 351, 'clown': 352, 'club': 353, 'clump': 354, 'cluster': 355, 'clutch': 356, 'coach': 357, 'coast': 358, 'coconut': 359, 'code': 360, 'coffee': 361, 'coil': 362, 'coin': 363, 'collect': 364, 'color': 365, 'column': 366, 'combine': 367, 'come': 368, 'comfort': 369, 'comic': 370, 'common': 371, 'company': 372, 'concert': 373, 'conduct': 374, 'confirm': 375, 'congress': 376, 'connect': 377, 'consider': 378, 'control': 379, 'convince': 380, 'cook': 381, 'cool': 382, 'copper': 383, 'copy': 384, 'coral': 385, 'core': 386, 'corn': 387, 'correct': 388, 'cost': 389, 'cotton': 390, 'couch': 391, 'country': 392, 'couple': 393, 'course': 394, 'cousin': 395, 'cover': 396, 'coyote': 397, 'crack': 398, 'cradle': 399, 'craft': 400, 'cram': 401, 'crane': 402, 'crash': 403, 'crater': 404, 'crawl': 405, 'crazy': 406, 'cream': 407, 'credit': 408, 'creek': 409, 'crew': 410, 'cricket': 411, 'crime': 412, 'crisp': 413, 'critic': 414, 'crop': 415, 'cross': 416, 'crouch': 417, 'crowd': 418, 'crucial': 419, 'cruel': 420, 'cruise': 421, 'crumble': 422, 'crunch': 423, 'crush': 424, 'cry': 425, 'crystal': 426, 'cube': 427, 'culture': 428, 'cup': 429, 'cupboard': 430, 'curious': 431, 'current': 432, 'curtain': 433, 'curve': 434, 'cushion': 435, 'custom': 436, 'cute': 437, 'cycle': 438, 'dad': 439, 'damage': 440, 'damp': 441, 'dance': 442, 'danger': 443, 'daring': 444, 'dash': 445, 'daughter': 446, 'dawn': 447, 'day': 448, 'deal': 449, 'debate': 450, 'debris': 451, 'decade': 452, 'december': 453, 'decide': 454, 'decline': 455, 'decorate': 456, 'decrease': 457, 'deer': 458, 'defense': 459, 'define': 460, 'defy': 461, 'degree': 462, 'delay': 463, 'deliver': 464, 'demand': 465, 'demise': 466, 'denial': 467, 'dentist': 468, 'deny': 469, 'depart': 470, 'depend': 471, 'deposit': 472, 'depth': 473, 'deputy': 474, 'derive': 475, 'describe': 476, 'desert': 477, 'design': 478, 'desk': 479, 'despair': 480, 'destroy': 481, 'detail': 482, 'detect': 483, 'develop': 484, 'device': 485, 'devote': 486, 'diagram': 487, 'dial': 488, 'diamond': 489, 'diary': 490, 'dice': 491, 'diesel': 492, 'diet': 493, 'differ': 494, 'digital': 495, 'dignity': 496, 'dilemma': 497, 'dinner': 498, 'dinosaur': 499, 'direct': 500, 'dirt': 501, 'disagree': 502, 'discover': 503, 'disease': 504, 'dish': 505, 'dismiss': 506, 'disorder': 507, 'display': 508, 'distance': 509, 'divert': 510, 'divide': 511, 'divorce': 512, 'dizzy': 513, 'doctor': 514, 'document': 515, 'dog': 516, 'doll': 517, 'dolphin': 518, 'domain': 519, 'donate': 520, 'donkey': 521, 'donor': 522, 'door': 523, 'dose': 524, 'double': 525, 'dove': 526, 'draft': 527, 'dragon': 528, 'drama': 529, 'drastic': 530, 'draw': 531, 'dream': 532, 'dress': 533, 'drift': 534, 'drill': 535, 'drink': 536, 'drip': 537, 'drive': 538, 'drop': 539, 'drum': 540, 'dry': 541, 'duck': 542, 'dumb': 543, 'dune': 544, 'during': 545, 'dust': 546, 'dutch': 547, 'duty': 548, 'dwarf': 549, 'dynamic': 550, 'eager': 551, 'eagle': 552, 'early': 553, 'earn': 554, 'earth': 555, 'easily': 556, 'east': 557, 'easy': 558, 'echo': 559, 'ecology': 560, 'economy': 561, 'edge': 562, 'edit': 563, 'educate': 564, 'effort': 565, 'egg': 566, 'eight': 567, 'either': 568, 'elbow': 569, 'elder': 570, 'electric': 571, 'elegant': 572, 'element': 573, 'elephant': 574, 'elevator': 575, 'elite': 576, 'else': 577, 'embark': 578, 'embody': 579, 'embrace': 580, 'emerge': 581, 'emotion': 582, 'employ': 583, 'empower': 584, 'empty': 585, 'enable': 586, 'enact': 587, 'end': 588, 'endless': 589, 'endorse': 590, 'enemy': 591, 'energy': 592, 'enforce': 593, 'engage': 594, 'engine': 595, 'enhance': 596, 'enjoy': 597, 'enlist': 598, 'enough': 599, 'enrich': 600, 'enroll': 601, 'ensure': 602, 'enter': 603, 'entire': 604, 'entry': 605, 'envelope': 606, 'episode': 607, 'equal': 608, 'equip': 609, 'era': 610, 'erase': 611, 'erode': 612, 'erosion': 613, 'error': 614, 'erupt': 615, 'escape': 616, 'essay': 617, 'essence': 618, 'estate': 619, 'eternal': 620, 'ethics': 621, 'evidence': 622, 'evil': 623, 'evoke': 624, 'evolve': 625, 'exact': 626, 'example': 627, 'excess': 628, 'exchange': 629, 'excite': 630, 'exclude': 631, 'excuse': 632, 'execute': 633, 'exercise': 634, 'exhaust': 635, 'exhibit': 636, 'exile': 637, 'exist': 638, 'exit': 639, 'exotic': 640, 'expand': 641, 'expect': 642, 'expire': 643, 'explain': 644, 'expose': 645, 'express': 646, 'extend': 647, 'extra': 648, 'eye': 649, 'eyebrow': 650, 'fabric': 651, 'face': 652, 'faculty': 653, 'fade': 654, 'faint': 655, 'faith': 656, 'fall': 657, 'false': 658, 'fame': 659, 'family': 660, 'famous': 661, 'fan': 662, 'fancy': 663, 'fantasy': 664, 'farm': 665, 'fashion': 666, 'fat': 667, 'fatal': 668, 'father': 669, 'fatigue': 670, 'fault': 671, 'favorite': 672, 'feature': 673, 'february': 674, 'federal': 675, 'fee': 676, 'feed': 677, 'feel': 678, 'female': 679, 'fence': 680, 'festival': 681, 'fetch': 682, 'fever': 683, 'few': 684, 'fiber': 685, 'fiction': 686, 'field': 687, 'figure': 688, 'file': 689, 'film': 690, 'filter': 691, 'final': 692, 'find': 693, 'fine': 694, 'finger': 695, 'finish': 696, 'fire': 697, 'firm': 698, 'first': 699, 'fiscal': 700, 'fish': 701, 'fit': 702, 'fitness': 703, 'fix': 704, 'flag': 705, 'flame': 706, 'flash': 707, 'flat': 708, 'flavor': 709, 'flee': 710, 'flight': 711, 'flip': 712, 'float': 713, 'flock': 714, 'floor': 715, 'flower': 716, 'fluid': 717, 'flush': 718, 'fly': 719, 'foam': 720, 'focus': 721, 'fog': 722, 'foil': 723, 'fold': 724, 'follow': 725, 'food': 726, 'foot': 727, 'force': 728, 'forest': 729, 'forget': 730, 'fork': 731, 'fortune': 732, 'forum': 733, 'forward': 734, 'fossil': 735, 'foster': 736, 'found': 737, 'fox': 738, 'fragile': 739, 'frame': 740, 'frequent': 741, 'fresh': 742, 'friend': 743, 'fringe': 744, 'frog': 745, 'front': 746, 'frost': 747, 'frown': 748, 'frozen': 749, 'fruit': 750, 'fuel': 751, 'fun': 752, 'funny': 753, 'furnace': 754, 'fury': 755, 'future': 756, 'gadget': 757, 'gain': 758, 'galaxy': 759, 'gallery': 760, 'game': 761, 'gap': 762, 'garage': 763, 'garbage': 764, 'garden': 765, 'garlic': 766, 'garment': 767, 'gas': 768, 'gasp': 769, 'gate': 770, 'gather': 771, 'gauge': 772, 'gaze': 773, 'general': 774, 'genius': 775, 'genre': 776, 'gentle': 777, 'genuine': 778, 'gesture': 779, 'ghost': 780, 'giant': 781, 'gift': 782, 'giggle': 783, 'ginger': 784, 'giraffe': 785, 'girl': 786, 'give': 787, 'glad': 788, 'glance': 789, 'glare': 790, 'glass': 791, 'glide': 792, 'glimpse': 793, 'globe': 794, 'gloom': 795, 'glory': 796, 'glove': 797, 'glow': 798, 'glue': 799, 'goat': 800, 'goddess': 801, 'gold': 802, 'good': 803, 'goose': 804, 'gorilla': 805, 'gospel': 806, 'gossip': 807, 'govern': 808, 'gown': 809, 'grab': 810, 'grace': 811, 'grain': 812, 'grant': 813, 'grape': 814, 'grass': 815, 'gravity': 816, 'great': 817, 'green': 818, 'grid': 819, 'grief': 820, 'grit': 821, 'grocery': 822, 'group': 823, 'grow': 824, 'grunt': 825, 'guard': 826, 'guess': 827, 'guide': 828, 'guilt': 829, 'guitar': 830, 'gun': 831, 'gym': 832, 'habit': 833, 'hair': 834, 'half': 835, 'hammer': 836, 'hamster': 837, 'hand': 838, 'happy': 839, 'harbor': 840, 'hard': 841, 'harsh': 842, 'harvest': 843, 'hat': 844, 'have': 845, 'hawk': 846, 'hazard': 847, 'head': 848, 'health': 849, 'heart': 850, 'heavy': 851, 'hedgehog': 852, 'height': 853, 'hello': 854, 'helmet': 855, 'help': 856, 'hen': 857, 'hero': 858, 'hidden': 859, 'high': 860, 'hill': 861, 'hint': 862, 'hip': 863, 'hire': 864, 'history': 865, 'hobby': 866, 'hockey': 867, 'hold': 868, 'hole': 869, 'holiday': 870, 'hollow': 871, 'home': 872, 'honey': 873, 'hood': 874, 'hope': 875, 'horn': 876, 'horror': 877, 'horse': 878, 'hospital': 879, 'host': 880, 'hotel': 881, 'hour': 882, 'hover': 883, 'hub': 884, 'huge': 885, 'human': 886, 'humble': 887, 'humor': 888, 'hundred': 889, 'hungry': 890, 'hunt': 891, 'hurdle': 892, 'hurry': 893, 'hurt': 894, 'husband': 895, 'hybrid': 896, 'ice': 897, 'icon': 898, 'idea': 899, 'identify': 900, 'idle': 901, 'ignore': 902, 'ill': 903, 'illegal': 904, 'illness': 905, 'image': 906, 'imitate': 907, 'immense': 908, 'immune': 909, 'impact': 910, 'impose': 911, 'improve': 912, 'impulse': 913, 'inch': 914, 'include': 915, 'income': 916, 'increase': 917, 'index': 918, 'indicate': 919, 'indoor': 920, 'industry': 921, 'infant': 922, 'inflict': 923, 'inform': 924, 'inhale': 925, 'inherit': 926, 'initial': 927, 'inject': 928, 'injury': 929, 'inmate': 930, 'inner': 931, 'innocent': 932, 'input': 933, 'inquiry': 934, 'insane': 935, 'insect': 936, 'inside': 937, 'inspire': 938, 'install': 939, 'intact': 940, 'interest': 941, 'into': 942, 'invest': 943, 'invite': 944, 'involve': 945, 'iron': 946, 'island': 947, 'isolate': 948, 'issue': 949, 'item': 950, 'ivory': 951, 'jacket': 952, 'jaguar': 953, 'jar': 954, 'jazz': 955, 'jealous': 956, 'jeans': 957, 'jelly': 958, 'jewel': 959, 'job': 960, 'join': 961, 'joke': 962, 'journey': 963, 'joy': 964, 'judge': 965, 'juice': 966, 'jump': 967, 'jungle': 968, 'junior': 969, 'junk': 970, 'just': 971, 'kangaroo': 972, 'keen': 973, 'keep': 974, 'ketchup': 975, 'key': 976, 'kick': 977, 'kid': 978, 'kidney': 979, 'kind': 980, 'kingdom': 981, 'kiss': 982, 'kit': 983, 'kitchen': 984, 'kite': 985, 'kitten': 986, 'kiwi': 987, 'knee': 988, 'knife': 989, 'knock': 990, 'know': 991, 'lab': 992, 'label': 993, 'labor': 994, 'ladder': 995, 'lady': 996, 'lake': 997, 'lamp': 998, 'language': 999, 'laptop': 1000, 'large': 1001, 'later': 1002, 'latin': 1003, 'laugh': 1004, 'laundry': 1005, 'lava': 1006, 'law': 1007, 'lawn': 1008, 'lawsuit': 1009, 'layer': 1010, 'lazy': 1011, 'leader': 1012, 'leaf': 1013, 'learn': 1014, 'leave': 1015, 'lecture': 1016, 'left': 1017, 'leg': 1018, 'legal': 1019, 'legend': 1020, 'leisure': 1021, 'lemon': 1022, 'lend': 1023, 'length': 1024, 'lens': 1025, 'leopard': 1026, 'lesson': 1027, 'letter': 1028, 'level': 1029, 'liar': 1030, 'liberty': 1031, 'library': 1032, 'license': 1033, 'life': 1034, 'lift': 1035, 'light': 1036, 'like': 1037, 'limb': 1038, 'limit': 1039, 'link': 1040, 'lion': 1041, 'liquid': 1042, 'list': 1043, 'little': 1044, 'live': 1045, 'lizard': 1046, 'load': 1047, 'loan': 1048, 'lobster': 1049, 'local': 1050, 'lock': 1051, 'logic': 1052, 'lonely': 1053, 'long': 1054, 'loop': 1055, 'lottery': 1056, 'loud': 1057, 'lounge': 1058, 'love': 1059, 'loyal': 1060, 'lucky': 1061, 'luggage': 1062, 'lumber': 1063, 'lunar': 1064, 'lunch': 1065, 'luxury': 1066, 'lyrics': 1067, 'machine': 1068, 'mad': 1069, 'magic': 1070, 'magnet': 1071, 'maid': 1072, 'mail': 1073, 'main': 1074, 'major': 1075, 'make': 1076, 'mammal': 1077, 'man': 1078, 'manage': 1079, 'mandate': 1080, 'mango': 1081, 'mansion': 1082, 'manual': 1083, 'maple': 1084, 'marble': 1085, 'march': 1086, 'margin': 1087, 'marine': 1088, 'market': 1089, 'marriage': 1090, 'mask': 1091, 'mass': 1092, 'master': 1093, 'match': 1094, 'material': 1095, 'math': 1096, 'matrix': 1097, 'matter': 1098, 'maximum': 1099, 'maze': 1100, 'meadow': 1101, 'mean': 1102, 'measure': 1103, 'meat': 1104, 'mechanic': 1105, 'medal': 1106, 'media': 1107, 'melody': 1108, 'melt': 1109, 'member': 1110, 'memory': 1111, 'mention': 1112, 'menu': 1113, 'mercy': 1114, 'merge': 1115, 'merit': 1116, 'merry': 1117, 'mesh': 1118, 'message': 1119, 'metal': 1120, 'method': 1121, 'middle': 1122, 'midnight': 1123, 'milk': 1124, 'million': 1125, 'mimic': 1126, 'mind': 1127, 'minimum': 1128, 'minor': 1129, 'minute': 1130, 'miracle': 1131, 'mirror': 1132, 'misery': 1133, 'miss': 1134, 'mistake': 1135, 'mix': 1136, 'mixed': 1137, 'mixture': 1138, 'mobile': 1139, 'model': 1140, 'modify': 1141, 'mom': 1142, 'moment': 1143, 'monitor': 1144, 'monkey': 1145, 'monster': 1146, 'month': 1147, 'moon': 1148, 'moral': 1149, 'more': 1150, 'morning': 1151, 'mosquito': 1152, 'mother': 1153, 'motion': 1154, 'motor': 1155, 'mountain': 1156, 'mouse': 1157, 'move': 1158, 'movie': 1159, 'much': 1160, 'muffin': 1161, 'mule': 1162, 'multiply': 1163, 'muscle': 1164, 'museum': 1165, 'mushroom': 1166, 'music': 1167, 'must': 1168, 'mutual': 1169, 'myself': 1170, 'mystery': 1171, 'myth': 1172, 'naive': 1173, 'name': 1174, 'napkin': 1175, 'narrow': 1176, 'nasty': 1177, 'nation': 1178, 'nature': 1179, 'near': 1180, 'neck': 1181, 'need': 1182, 'negative': 1183, 'neglect': 1184, 'neither': 1185, 'nephew': 1186, 'nerve': 1187, 'nest': 1188, 'net': 1189, 'network': 1190, 'neutral': 1191, 'never': 1192, 'news': 1193, 'next': 1194, 'nice': 1195, 'night': 1196, 'noble': 1197, 'noise': 1198, 'nominee': 1199, 'noodle': 1200, 'normal': 1201, 'north': 1202, 'nose': 1203, 'notable': 1204, 'note': 1205, 'nothing': 1206, 'notice': 1207, 'novel': 1208, 'now': 1209, 'nuclear': 1210, 'number': 1211, 'nurse': 1212, 'nut': 1213, 'oak': 1214, 'obey': 1215, 'object': 1216, 'oblige': 1217, 'obscure': 1218, 'observe': 1219, 'obtain': 1220, 'obvious': 1221, 'occur': 1222, 'ocean': 1223, 'october': 1224, 'odor': 1225, 'off': 1226, 'offer': 1227, 'office': 1228, 'often': 1229, 'oil': 1230, 'okay': 1231, 'old': 1232, 'olive': 1233, 'olympic': 1234, 'omit': 1235, 'once': 1236, 'one': 1237, 'onion': 1238, 'online': 1239, 'only': 1240, 'open': 1241, 'opera': 1242, 'opinion': 1243, 'oppose': 1244, 'option': 1245, 'orange': 1246, 'orbit': 1247, 'orchard': 1248, 'order': 1249, 'ordinary': 1250, 'organ': 1251, 'orient': 1252, 'original': 1253, 'orphan': 1254, 'ostrich': 1255, 'other': 1256, 'outdoor': 1257, 'outer': 1258, 'output': 1259, 'outside': 1260, 'oval': 1261, 'oven': 1262, 'over': 1263, 'own': 1264, 'owner': 1265, 'oxygen': 1266, 'oyster': 1267, 'ozone': 1268, 'pact': 1269, 'paddle': 1270, 'page': 1271, 'pair': 1272, 'palace': 1273, 'palm': 1274, 'panda': 1275, 'panel': 1276, 'panic': 1277, 'panther': 1278, 'paper': 1279, 'parade': 1280, 'parent': 1281, 'park': 1282, 'parrot': 1283, 'party': 1284, 'pass': 1285, 'patch': 1286, 'path': 1287, 'patient': 1288, 'patrol': 1289, 'pattern': 1290, 'pause': 1291, 'pave': 1292, 'payment': 1293, 'peace': 1294, 'peanut': 1295, 'pear': 1296, 'peasant': 1297, 'pelican': 1298, 'pen': 1299, 'penalty': 1300, 'pencil': 1301, 'people': 1302, 'pepper': 1303, 'perfect': 1304, 'permit': 1305, 'person': 1306, 'pet': 1307, 'phone': 1308, 'photo': 1309, 'phrase': 1310, 'physical': 1311, 'piano': 1312, 'picnic': 1313, 'picture': 1314, 'piece': 1315, 'pig': 1316, 'pigeon': 1317, 'pill': 1318, 'pilot': 1319, 'pink': 1320, 'pioneer': 1321, 'pipe': 1322, 'pistol': 1323, 'pitch': 1324, 'pizza': 1325, 'place': 1326, 'planet': 1327, 'plastic': 1328, 'plate': 1329, 'play': 1330, 'please': 1331, 'pledge': 1332, 'pluck': 1333, 'plug': 1334, 'plunge': 1335, 'poem': 1336, 'poet': 1337, 'point': 1338, 'polar': 1339, 'pole': 1340, 'police': 1341, 'pond': 1342, 'pony': 1343, 'pool': 1344, 'popular': 1345, 'portion': 1346, 'position': 1347, 'possible': 1348, 'post': 1349, 'potato': 1350, 'pottery': 1351, 'poverty': 1352, 'powder': 1353, 'power': 1354, 'practice': 1355, 'praise': 1356, 'predict': 1357, 'prefer': 1358, 'prepare': 1359, 'present': 1360, 'pretty': 1361, 'prevent': 1362, 'price': 1363, 'pride': 1364, 'primary': 1365, 'print': 1366, 'priority': 1367, 'prison': 1368, 'private': 1369, 'prize': 1370, 'problem': 1371, 'process': 1372, 'produce': 1373, 'profit': 1374, 'program': 1375, 'project': 1376, 'promote': 1377, 'proof': 1378, 'property': 1379, 'prosper': 1380, 'protect': 1381, 'proud': 1382, 'provide': 1383, 'public': 1384, 'pudding': 1385, 'pull': 1386, 'pulp': 1387, 'pulse': 1388, 'pumpkin': 1389, 'punch': 1390, 'pupil': 1391, 'puppy': 1392, 'purchase': 1393, 'purity': 1394, 'purpose': 1395, 'purse': 1396, 'push': 1397, 'put': 1398, 'puzzle': 1399, 'pyramid': 1400, 'quality': 1401, 'quantum': 1402, 'quarter': 1403, 'question': 1404, 'quick': 1405, 'quit': 1406, 'quiz': 1407, 'quote': 1408, 'rabbit': 1409, 'raccoon': 1410, 'race': 1411, 'rack': 1412, 'radar': 1413, 'radio': 1414, 'rail': 1415, 'rain': 1416, 'raise': 1417, 'rally': 1418, 'ramp': 1419, 'ranch': 1420, 'random': 1421, 'range': 1422, 'rapid': 1423, 'rare': 1424, 'rate': 1425, 'rather': 1426, 'raven': 1427, 'raw': 1428, 'razor': 1429, 'ready': 1430, 'real': 1431, 'reason': 1432, 'rebel': 1433, 'rebuild': 1434, 'recall': 1435, 'receive': 1436, 'recipe': 1437, 'record': 1438, 'recycle': 1439, 'reduce': 1440, 'reflect': 1441, 'reform': 1442, 'refuse': 1443, 'region': 1444, 'regret': 1445, 'regular': 1446, 'reject': 1447, 'relax': 1448, 'release': 1449, 'relief': 1450, 'rely': 1451, 'remain': 1452, 'remember': 1453, 'remind': 1454, 'remove': 1455, 'render': 1456, 'renew': 1457, 'rent': 1458, 'reopen': 1459, 'repair': 1460, 'repeat': 1461, 'replace': 1462, 'report': 1463, 'require': 1464, 'rescue': 1465, 'resemble': 1466, 'resist': 1467, 'resource': 1468, 'response': 1469, 'result': 1470, 'retire': 1471, 'retreat': 1472, 'return': 1473, 'reunion': 1474, 'reveal': 1475, 'review': 1476, 'reward': 1477, 'rhythm': 1478, 'rib': 1479, 'ribbon': 1480, 'rice': 1481, 'rich': 1482, 'ride': 1483, 'ridge': 1484, 'rifle': 1485, 'right': 1486, 'rigid': 1487, 'ring': 1488, 'riot': 1489, 'ripple': 1490, 'risk': 1491, 'ritual': 1492, 'rival': 1493, 'river': 1494, 'road': 1495, 'roast': 1496, 'robot': 1497, 'robust': 1498, 'rocket': 1499, 'romance': 1500, 'roof': 1501, 'rookie': 1502, 'room': 1503, 'rose': 1504, 'rotate': 1505, 'rough': 1506, 'round': 1507, 'route': 1508, 'royal': 1509, 'rubber': 1510, 'rude': 1511, 'rug': 1512, 'rule': 1513, 'run': 1514, 'runway': 1515, 'rural': 1516, 'sad': 1517, 'saddle': 1518, 'sadness': 1519, 'safe': 1520, 'sail': 1521, 'salad': 1522, 'salmon': 1523, 'salon': 1524, 'salt': 1525, 'salute': 1526, 'same': 1527, 'sample': 1528, 'sand': 1529, 'satisfy': 1530, 'satoshi': 1531, 'sauce': 1532, 'sausage': 1533, 'save': 1534, 'say': 1535, 'scale': 1536, 'scan': 1537, 'scare': 1538, 'scatter': 1539, 'scene': 1540, 'scheme': 1541, 'school': 1542, 'science': 1543, 'scissors': 1544, 'scorpion': 1545, 'scout': 1546, 'scrap': 1547, 'screen': 1548, 'script': 1549, 'scrub': 1550, 'sea': 1551, 'search': 1552, 'season': 1553, 'seat': 1554, 'second': 1555, 'secret': 1556, 'section': 1557, 'security': 1558, 'seed': 1559, 'seek': 1560, 'segment': 1561, 'select': 1562, 'sell': 1563, 'seminar': 1564, 'senior': 1565, 'sense': 1566, 'sentence': 1567, 'series': 1568, 'service': 1569, 'session': 1570, 'settle': 1571, 'setup': 1572, 'seven': 1573, 'shadow': 1574, 'shaft': 1575, 'shallow': 1576, 'share': 1577, 'shed': 1578, 'shell': 1579, 'sheriff': 1580, 'shield': 1581, 'shift': 1582, 'shine': 1583, 'ship': 1584, 'shiver': 1585, 'shock': 1586, 'shoe': 1587, 'shoot': 1588, 'shop': 1589, 'short': 1590, 'shoulder': 1591, 'shove': 1592, 'shrimp': 1593, 'shrug': 1594, 'shuffle': 1595, 'shy': 1596, 'sibling': 1597, 'sick': 1598, 'side': 1599, 'siege': 1600, 'sight': 1601, 'sign': 1602, 'silent': 1603, 'silk': 1604, 'silly': 1605, 'silver': 1606, 'similar': 1607, 'simple': 1608, 'since': 1609, 'sing': 1610, 'siren': 1611, 'sister': 1612, 'situate': 1613, 'six': 1614, 'size': 1615, 'skate': 1616, 'sketch': 1617, 'ski': 1618, 'skill': 1619, 'skin': 1620, 'skirt': 1621, 'skull': 1622, 'slab': 1623, 'slam': 1624, 'sleep': 1625, 'slender': 1626, 'slice': 1627, 'slide': 1628, 'slight': 1629, 'slim': 1630, 'slogan': 1631, 'slot': 1632, 'slow': 1633, 'slush': 1634, 'small': 1635, 'smart': 1636, 'smile': 1637, 'smoke': 1638, 'smooth': 1639, 'snack': 1640, 'snake': 1641, 'snap': 1642, 'sniff': 1643, 'snow': 1644, 'soap': 1645, 'soccer': 1646, 'social': 1647, 'sock': 1648, 'soda': 1649, 'soft': 1650, 'solar': 1651, 'soldier': 1652, 'solid': 1653, 'solution': 1654, 'solve': 1655, 'someone': 1656, 'song': 1657, 'soon': 1658, 'sorry': 1659, 'sort': 1660, 'soul': 1661, 'sound': 1662, 'soup': 1663, 'source': 1664, 'south': 1665, 'space': 1666, 'spare': 1667, 'spatial': 1668, 'spawn': 1669, 'speak': 1670, 'special': 1671, 'speed': 1672, 'spell': 1673, 'spend': 1674, 'sphere': 1675, 'spice': 1676, 'spider': 1677, 'spike': 1678, 'spin': 1679, 'spirit': 1680, 'split': 1681, 'spoil': 1682, 'sponsor': 1683, 'spoon': 1684, 'sport': 1685, 'spot': 1686, 'spray': 1687, 'spread': 1688, 'spring': 1689, 'spy': 1690, 'square': 1691, 'squeeze': 1692, 'squirrel': 1693, 'stable': 1694, 'stadium': 1695, 'staff': 1696, 'stage': 1697, 'stairs': 1698, 'stamp': 1699, 'stand': 1700, 'start': 1701, 'state': 1702, 'stay': 1703, 'steak': 1704, 'steel': 1705, 'stem': 1706, 'step': 1707, 'stereo': 1708, 'stick': 1709, 'still': 1710, 'sting': 1711, 'stock': 1712, 'stomach': 1713, 'stone': 1714, 'stool': 1715, 'story': 1716, 'stove': 1717, 'strategy': 1718, 'street': 1719, 'strike': 1720, 'strong': 1721, 'struggle': 1722, 'student': 1723, 'stuff': 1724, 'stumble': 1725, 'style': 1726, 'subject': 1727, 'submit': 1728, 'subway': 1729, 'success': 1730, 'such': 1731, 'sudden': 1732, 'suffer': 1733, 'sugar': 1734, 'suggest': 1735, 'suit': 1736, 'summer': 1737, 'sun': 1738, 'sunny': 1739, 'sunset': 1740, 'super': 1741, 'supply': 1742, 'supreme': 1743, 'sure': 1744, 'surface': 1745, 'surge': 1746, 'surprise': 1747, 'surround': 1748, 'survey': 1749, 'suspect': 1750, 'sustain': 1751, 'swallow': 1752, 'swamp': 1753, 'swap': 1754, 'swarm': 1755, 'swear': 1756, 'sweet': 1757, 'swift': 1758, 'swim': 1759, 'swing': 1760, 'switch': 1761, 'sword': 1762, 'symbol': 1763, 'symptom': 1764, 'syrup': 1765, 'system': 1766, 'table': 1767, 'tackle': 1768, 'tag': 1769, 'tail': 1770, 'talent': 1771, 'talk': 1772, 'tank': 1773, 'tape': 1774, 'target': 1775, 'task': 1776, 'taste': 1777, 'tattoo': 1778, 'taxi': 1779, 'teach': 1780, 'team': 1781, 'tell': 1782, 'ten': 1783, 'tenant': 1784, 'tennis': 1785, 'tent': 1786, 'term': 1787, 'test': 1788, 'text': 1789, 'thank': 1790, 'that': 1791, 'theme': 1792, 'then': 1793, 'theory': 1794, 'there': 1795, 'they': 1796, 'thing': 1797, 'this': 1798, 'thought': 1799, 'three': 1800, 'thrive': 1801, 'throw': 1802, 'thumb': 1803, 'thunder': 1804, 'ticket': 1805, 'tide': 1806, 'tiger': 1807, 'tilt': 1808, 'timber': 1809, 'time': 1810, 'tiny': 1811, 'tip': 1812, 'tired': 1813, 'tissue': 1814, 'title': 1815, 'toast': 1816, 'tobacco': 1817, 'today': 1818, 'toddler': 1819, 'toe': 1820, 'together': 1821, 'toilet': 1822, 'token': 1823, 'tomato': 1824, 'tomorrow': 1825, 'tone': 1826, 'tongue': 1827, 'tonight': 1828, 'tool': 1829, 'tooth': 1830, 'top': 1831, 'topic': 1832, 'topple': 1833, 'torch': 1834, 'tornado': 1835, 'tortoise': 1836, 'toss': 1837, 'total': 1838, 'tourist': 1839, 'toward': 1840, 'tower': 1841, 'town': 1842, 'toy': 1843, 'track': 1844, 'trade': 1845, 'traffic': 1846, 'tragic': 1847, 'train': 1848, 'transfer': 1849, 'trap': 1850, 'trash': 1851, 'travel': 1852, 'tray': 1853, 'treat': 1854, 'tree': 1855, 'trend': 1856, 'trial': 1857, 'tribe': 1858, 'trick': 1859, 'trigger': 1860, 'trim': 1861, 'trip': 1862, 'trophy': 1863, 'trouble': 1864, 'truck': 1865, 'true': 1866, 'truly': 1867, 'trumpet': 1868, 'trust': 1869, 'truth': 1870, 'try': 1871, 'tube': 1872, 'tuition': 1873, 'tumble': 1874, 'tuna': 1875, 'tunnel': 1876, 'turkey': 1877, 'turn': 1878, 'turtle': 1879, 'twelve': 1880, 'twenty': 1881, 'twice': 1882, 'twin': 1883, 'twist': 1884, 'two': 1885, 'type': 1886, 'typical': 1887, 'ugly': 1888, 'umbrella': 1889, 'unable': 1890, 'unaware': 1891, 'uncle': 1892, 'uncover': 1893, 'under': 1894, 'undo': 1895, 'unfair': 1896, 'unfold': 1897, 'unhappy': 1898, 'uniform': 1899, 'unique': 1900, 'unit': 1901, 'universe': 1902, 'unknown': 1903, 'unlock': 1904, 'until': 1905, 'unusual': 1906, 'unveil': 1907, 'update': 1908, 'upgrade': 1909, 'uphold': 1910, 'upon': 1911, 'upper': 1912, 'upset': 1913, 'urban': 1914, 'urge': 1915, 'usage': 1916, 'use': 1917, 'used': 1918, 'useful': 1919, 'useless': 1920, 'usual': 1921, 'utility': 1922, 'vacant': 1923, 'vacuum': 1924, 'vague': 1925, 'valid': 1926, 'valley': 1927, 'valve': 1928, 'van': 1929, 'vanish': 1930, 'vapor': 1931, 'various': 1932, 'vast': 1933, 'vault': 1934, 'vehicle': 1935, 'velvet': 1936, 'vendor': 1937, 'venture': 1938, 'venue': 1939, 'verb': 1940, 'verify': 1941, 'version': 1942, 'very': 1943, 'vessel': 1944, 'veteran': 1945, 'viable': 1946, 'vibrant': 1947, 'vicious': 1948, 'victory': 1949, 'video': 1950, 'view': 1951, 'village': 1952, 'vintage': 1953, 'violin': 1954, 'virtual': 1955, 'virus': 1956, 'visa': 1957, 'visit': 1958, 'visual': 1959, 'vital': 1960, 'vivid': 1961, 'vocal': 1962, 'voice': 1963, 'void': 1964, 'volcano': 1965, 'volume': 1966, 'vote': 1967, 'voyage': 1968, 'wage': 1969, 'wagon': 1970, 'wait': 1971, 'walk': 1972, 'wall': 1973, 'walnut': 1974, 'want': 1975, 'warfare': 1976, 'warm': 1977, 'warrior': 1978, 'wash': 1979, 'wasp': 1980, 'waste': 1981, 'water': 1982, 'wave': 1983, 'way': 1984, 'wealth': 1985, 'weapon': 1986, 'wear': 1987, 'weasel': 1988, 'weather': 1989, 'web': 1990, 'wedding': 1991, 'weekend': 1992, 'weird': 1993, 'welcome': 1994, 'west': 1995, 'wet': 1996, 'whale': 1997, 'what': 1998, 'wheat': 1999, 'wheel': 2000, 'when': 2001, 'where': 2002, 'whip': 2003, 'whisper': 2004, 'wide': 2005, 'width': 2006, 'wife': 2007, 'wild': 2008, 'will': 2009, 'win': 2010, 'window': 2011, 'wine': 2012, 'wing': 2013, 'wink': 2014, 'winner': 2015, 'winter': 2016, 'wire': 2017, 'wisdom': 2018, 'wise': 2019, 'wish': 2020, 'witness': 2021, 'wolf': 2022, 'woman': 2023, 'wonder': 2024, 'wood': 2025, 'wool': 2026, 'word': 2027, 'work': 2028, 'world': 2029, 'worry': 2030, 'worth': 2031, 'wrap': 2032, 'wreck': 2033, 'wrestle': 2034, 'wrist': 2035, 'write': 2036, 'wrong': 2037, 'yard': 2038, 'year': 2039, 'yellow': 2040, 'you': 2041, 'young': 2042, 'youth': 2043, 'zebra': 2044, 'zero': 2045, 'zone': 2046, 'zoo': 2047}
def encode_random_polynomial_hex(hex_key: str, shared_secrets: int, total_secrets: int) -> list[str]:
secret_integer = int(hex_key, base=16) % prime_field
points = encode_random_polynomial(secret_integer, shared_secrets, total_secrets)
return [decode_point_hex(point) for point in points]
def encode_random_polynomial_words(word_key: list[str], shared_secrets: int, total_secrets: int) -> list[str]:
secret_indexes = [INDEXED_WORDS[word] for word in word_key]
as_bits = ''.join(bin(index)[2:].rjust(WORD_SIZE, '0') for index in secret_indexes)
secret_integer = int(as_bits, base=2) % prime_field
points = encode_random_polynomial(secret_integer, shared_secrets, total_secrets)
return [decode_point_word(point) for point in points]
def encode_random_polynomial(secret: int, shared_secrets: int, total_secrets: int) -> list[Point]:
points = []
# generate a random equation that is at most of degree shared_secrets - 1
degree = shared_secrets - 1
equation = [1] * degree
equation.append(secret)
for _ in range(total_secrets):
x = system_random.randrange(1, prime_field)
# apply the equation on each point
y = sum(x ** (degree - i) * coefficient for i, coefficient in enumerate(equation))
points.append(Point(x, y % prime_field))
return points
def decode_polynomial_hex(parts: list[str]) -> str:
return decode_polynomial(parts, encode_point_hex, decode_secret_hex)
def decode_polynomial_words(parts: list[str]) -> str:
return decode_polynomial(parts, encode_point_words, decode_secret_words)
def decode_polynomial(parts: list[str], encoding_function: types.FunctionType, decoding_function: types.FunctionType) -> str:
def reduce_function(variable: sympy.Symbol, xs: set[int]):
return functools.reduce(operator.mul, [variable - value for value in xs])
secrets = [encoding_function(part) for part in parts]
secrets_by_x = set(secret.x for secret in secrets)
x_symbol = sympy.Symbol('x')
equation = 0
while secrets:
secret = secrets.pop()
copy = secrets_by_x - {secret.x}
equation += reduce_function(x_symbol, copy) * sympy.invert(reduce_function(secret.x, copy), prime_field) * secret.y
integer_solution = int(equation.subs(x_symbol, 0)) % prime_field
return decoding_function(integer_solution)
def decode_secret_hex(solution: int) -> str:
binary_solution = bin(solution)[2:].rjust(256, '0')
indexes = [int(binary_solution[i:i + HEX_SIZE], base=2) for i in range(0, len(binary_solution), HEX_SIZE)]
return '0x' + ''.join([hex(index)[2:].rjust(2, '0') for index in indexes])
def decode_secret_words(solution: int) -> str:
binary_solution = bin(solution)[2:].rjust(24 * WORD_SIZE, '0')
indexes = [int(binary_solution[i:i + WORD_SIZE], base=2) for i in range(0, len(binary_solution), WORD_SIZE)]
private_key_array = [WORDLIST[i] for i in indexes]
return ' '.join(private_key_array)
def encode_point_hex(string: str) -> Point:
stripped = string.lstrip('0x')
indexes = [int(stripped[i:i + 2], base=16) for i in range(0, len(stripped), 2)]
return encode_point(indexes, HEX_SIZE)
def encode_point_words(string: str) -> Point:
word_array = string.split(' ')
indexes = [INDEXED_WORDS[word] for word in word_array]
return encode_point(indexes, WORD_SIZE)
def encode_point(indexes: list[int], size: int) -> Point:
bytes_solution = ''.join(bin(index)[2:].rjust(size, '0') for index in indexes)
integer_solution = int(bytes_solution, base=2)
mask = 2 ** 384 - 1
x = integer_solution & mask
y = integer_solution >> 384
return Point(x, y)
def decode_point(point: Point, size: int):
big_integer = point.x + (point.y << 384)
padding = math.ceil(384 * 2 / size)
bytes_solution = bin(big_integer)[2:].rjust(padding * size, '0')
indexes = [int(bytes_solution[i:i + size], base=2) for i in range(0, len(bytes_solution), size)]
return indexes
def decode_point_hex(point: Point) -> str:
indexes = decode_point(point, HEX_SIZE)
return '0x' + ''.join([hex(i)[2:].rjust(2, '0') for i in indexes])
def decode_point_word(point: Point) -> str:
indexes = decode_point(point, WORD_SIZE)
word_array = [WORDLIST[i] for i in indexes]
return ' '.join(word_array)
def print_usage():
print('Usage:\n')
print('encoding:')
print(' python3 ' + sys.argv[0] + ' num_shared_keys num_total_keys key\n')
print('decoding:')
print(' python3 ' + sys.argv[0] + ' num_shared_keys key1 key2 [...]\n')
exit(1)
def is_base_10(x):
try:
return int(x, 10)
except ValueError:
return False
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('args', type=str, help='arguments', nargs='*')
namespace = parser.parse_args()
args = namespace.args
if len(args) < 3:
print_usage()
num_shared_secrets = is_base_10(args[0])
if not num_shared_secrets:
print_usage()
num_total_secrets = is_base_10(args[1])
if num_total_secrets:
key = args[2:]
is_words = len(key) == 24
is_hex = len(key) == 1
if not (is_words or is_hex):
print('\nKey must be one hex private key or 24 bip0039 words')
exit(3)
if is_words:
encoded = encode_random_polynomial_words(key, num_shared_secrets, num_total_secrets)
else:
encoded = encode_random_polynomial_hex(key[0], num_shared_secrets, num_total_secrets)
print()
print(*encoded, sep="\n\n")
print()
else:
keys = args[1:]
is_words = all(word in INDEXED_WORDS for word in keys)
if is_words:
if len(keys) % SHARED_SECRET_WORD_LENGTH != 0:
print(f'\nMust be a multiple of {SHARED_SECRET_WORD_LENGTH} words\n')
exit(3)
new_keys = []
for i in range(0, len(keys), SHARED_SECRET_WORD_LENGTH):
new_keys.append(' '.join(keys[i:i+SHARED_SECRET_WORD_LENGTH]))
keys = new_keys
if len(keys) == num_shared_secrets:
if any(a == b for a, b in itertools.combinations(keys, r=2)):
print('\nEach secret must be unique!\n')
exit(2)
if is_words:
print('\n', decode_polynomial_words(keys), '\n')
else:
print('\n', decode_polynomial_hex(keys), '\n')
else:
print_usage()