What are the internals of Pythons str.join()? (Hiding passwords from output) -


i stumbled upon interesting(?) way hide passwords (and other personal data) general output screen logfiles.

in book how make mistakes in python mike pirnat suggests implement class sensitive strings , overload __str__- , __repr__-methods.

i experimented , got this:

class secret(str):      def __init__(self, s):         self.string = s      def __repr__(self):         return "'" + "r"*len(self.string) + "'"      def __str__(self):         return "s" * len(self.string)      def __add__(self, other):         return str.__add__(self.__str__(), other)      def __radd__(self, other):         return str.__add__(other, self.__str__())      def __getslice__(self, i, j):         return ("x"*len(self.string))[i:j] 

(i'm aware using len provides information content hide. it's testing.)

it works fine in cases:

pwd = secret("nothidden")  print("the passwort " + pwd)                  # passwort sssssssss print(pwd + " passwort.")                 # sssssssss password.  print("the passwort {}.".format(pwd))         # password sssssssss. print(["the", "passwort", "is", pwd])            # ['the', 'password', 'is', 'rrrrrrrrr'] print(pwd[:])                                    # xxxxxxxxx 

however not work:

print(" ".join(["the", "password", "is", pwd]))  # password nothidden 

so, how str.join() work internally? method have overload obscure string?

the issue inheriting str, implements __new__ means though avoided calling parent constructor in class, underlying c object still initialized it.

now join checking if has str subclass and, being implemented in c, access directly underlying c structure, or uses other str-related function bypasses __str__ , __repr__ (think it: if value string or string subclass, why code call __str__ or __repr__ obtain value? accesses underlying character array in way!)

to fix this: not inherit str! unfortunately means not able use object string in situations, that's pretty inevitable.


an alternative may work implement __new__ , feed different value str's __new__ method:

class secret(str):     def __new__(cls, initializer):         return super(secret, cls).__new__(cls, 'x'*len(initializer))     def __init__(self, initializer):         self.text = initializer     def __repr__(self):         return "'{}'".format("r"*len(self))     def __str__(self):         return "s"*len(self)     def __add__(self, other):         return str(self) + other     def __radd__(self, other):         return other + str(self) 

which results in:

in [19]: pwd = secret('nothidden')  in [20]: print("the passwort " + pwd)                  # passwort sssssssss     ...: print(pwd + " passwort.")                 # sssssssss password.     ...:      ...: print("the passwort {}.".format(pwd))         # password sssssssss.     ...: print(["the", "passwort", "is", pwd])            # ['the', 'password', 'is', 'rrrrrrrrr']     ...: print(pwd[:]) passwort sssssssss sssssssss passwort. passwort sssssssss. ['the', 'passwort', 'is', 'rrrrrrrrr'] xxxxxxxxx  in [21]: print(" ".join(["the", "password", "is", pwd])) password xxxxxxxxx 

however fail see how useful. mean: purpose of class avoid programming errors end display sensitive information? having exception being triggered better can identify bugs! it's best raise notimplementederror inside __str__ , __repr__ instead of silently provided useless value... sure don't leak secret finding bugs becomes hard.


Comments

Popular posts from this blog

php - How to add and update images or image url in Volusion using Volusion API -

javascript - IE9 error '$'is not defined -