## [Python][Crypto] Simplest possible password manager, part II

Previously. As I remarked at that post, base64 is inefficient. You would use more characters, including space, maybe.

How would you print a number?

#!/usr/bin/env python3

# slice one bit at each iteration:
def as_base2(n):
rt=""
while True:
# is the last bit set?
if n&1:
rt=rt+"1"
else:
rt=rt+"0"
n=n>>1
# no more bits?
if n==0:
# reverse string:
return rt[::-1]

# slice 4 bits at each iteration:
def as_base16(n):
rt=""
while True:
rt=rt+"0123456789abcdef"[n&0xf]
n=n>>4
# no more bits?
if n==0:
# reverse string:
return rt[::-1]

# slice one decimal digit at each iteration:
def as_base10(n):
rt=""
while True:
rt=rt+"0123456789"[int(n%10)]
n=int(n/10)
# no more bits?
if n==0:
# reverse string:
return rt[::-1]

# as an exercise, you can write a function for base64 - just slice 6 bits at each iteration!

# slice a digit of some base, at each iteration:
def as_base_X(n, charset):
base=len(charset)
rt=""
while True:
rt=rt+charset[int(n%base)]
n=int(n/base)
# no more bits?
if n==0:
# reverse string:
return rt[::-1]

print (as_base2(0b111000))
print (as_base16(0x1234567890abcdef))
print (as_base10(1234567890))

charset="".join(list(map(chr, list(range(32, 127)))))
# 95 chars, space included:
# ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}~' print ("["+as_base_X(1234567890, charset)+"]") # will print: [/.y5M]  Now I use the following Python script to encode a MD5 hash as a bignumber and than print it as a base95 number: #!/usr/bin/env python3 import hashlib print ("Enter the master password:") MASTER=input() ACCOUNT="dennis.yurichev" HOST="gmail.com" # To be incremented if you have to change this password # For example, if compromised: SALT="1" m=hashlib.md5() m.update(MASTER.encode("utf-8")) m.update(ACCOUNT.encode("utf-8")) m.update(HOST.encode("utf-8")) m.update(SALT.encode("utf-8")) hashed=m.digest() # https://stackoverflow.com/questions/444591/how-to-convert-a-string-of-bytes-into-an-int hashed_bn=int.from_bytes(hashed, byteorder='big') #print (hashed_bn) # slice a digit of some base, at each iteration: def as_base_X(n, charset): base=len(charset) rt="" while True: rt=rt+charset[int(n%base)] # discard last decimal number n=int(n/base) # no more bits? if n==0: # reverse string: return rt[::-1] charset="".join(list(map(chr, list(range(32, 127))))) # 95 chars, space included: # ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}~'
print (as_base_X(hashed_bn, charset))


For example:

Enter the master password:
asd
\$Pvnp-Kw%yj1}S5)gZW@


This is shorter than base64.

###### (the post first published at 20220511.)

Yes, I know about these lousy Disqus ads. Please use adblocker. I would consider to subscribe to 'pro' version of Disqus if the signal/noise ratio in comments would be good enough.