我偶然发现了一种有趣的(?)方式来隐藏密码(和其他个人数据)从屏幕到日志文件的一般输出.
在他的书" 如何在Python中犯错"中, Mike Pirnat建议为敏感字符串实现一个类,并使其__str__- 和 - __repr__方法重载.
我试验过这个并得到了这个:
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]
Run Code Online (Sandbox Code Playgroud)
(我知道使用len提供有关要隐藏的内容的信息.它仅用于测试.)
它在这种情况下工作正常:
pwd = secret("nothidden")
print("The passwort is " + pwd) # The passwort is SSSSSSSSS
print(pwd + " is the passwort.") # SSSSSSSSS is the password.
print("The passwort is {}.".format(pwd)) # The password is SSSSSSSSS.
print(["The", "passwort", "is", pwd]) # ['The', 'password', 'is', 'RRRRRRRRR']
print(pwd[:]) # XXXXXXXXX
Run Code Online (Sandbox Code Playgroud)
但是这不起作用:
print(" ".join(["The", "password", "is", pwd])) # The password is nothidden
Run Code Online (Sandbox Code Playgroud)
那么,str.join()如何在内部工作?我需要重载哪种方法来掩盖字符串?
问题在于你是继承的str,这可能是实现的__new__,这意味着即使你避免在你的类中调用父构造函数,底层的C对象仍然用它初始化.
现在join可能是检查,如果它有一个str子类,并在C中实现,但是直接访问底层的C结构,或使用一个其它str-相关函数绕过__str__和__repr__(想一想:如果该值是一个字符串或字符串的子类,为什么代码会调用__str__或__repr__获取它的值?它只是以某种方式访问底层字符数组!)
为了解决这个问题:那不是继承str!不幸的是,这意味着在某些情况下你将无法像字符串一样使用该对象,但这几乎是不可避免的.
可工作的替代方案是实现__new__和饲料一个不同的值str的__new__方法:
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)
Run Code Online (Sandbox Code Playgroud)
结果如下:
In [19]: pwd = secret('nothidden')
In [20]: print("The passwort is " + pwd) # The passwort is SSSSSSSSS
...: print(pwd + " is the passwort.") # SSSSSSSSS is the password.
...:
...: print("The passwort is {}.".format(pwd)) # The password is SSSSSSSSS.
...: print(["The", "passwort", "is", pwd]) # ['The', 'password', 'is', 'RRRRRRRRR']
...: print(pwd[:])
The passwort is SSSSSSSSS
SSSSSSSSS is the passwort.
The passwort is SSSSSSSSS.
['The', 'passwort', 'is', 'RRRRRRRRR']
XXXXXXXXX
In [21]: print(" ".join(["The", "password", "is", pwd]))
The password is XXXXXXXXX
Run Code Online (Sandbox Code Playgroud)
但是,我没有真正看到它是如何有用的.我的意思是:这个类的目的是避免编程错误,最终显示敏感信息?但是,触发异常会更好,以便您可以识别错误!为此,它可能最好在raise NotImplementedError内部__str__,__repr__而不是默默地提供一个无用的价值...确保你不泄漏秘密,但发现错误变得非常困难.
| 归档时间: |
|
| 查看次数: |
208 次 |
| 最近记录: |