@@ -24,14 +24,18 @@ class Secret:
2424 "Secret('******')"
2525 """
2626
27- def __init__ (self , value : str , * , direct_value : bool = False ) -> None :
27+ def __init__ (
28+ self , value : str , * , direct_value : bool = False , encoding : str = "utf8"
29+ ) -> None :
2830 """
2931 Create an instance of Secret.
3032
3133 Args:
3234 value: The name of an environment variable reference (prefixed with $), or
3335 a secret if direct_value=True.
3436 direct_value: Must be set to True to allow passing secrets directly
37+ encoding: The encoding to be used when comparing strings with
38+ secrets.compare_digest.
3539
3640 Raises:
3741 ValueError: If a secret is provided without explicit permission.
@@ -45,6 +49,7 @@ def __init__(self, value: str, *, direct_value: bool = False) -> None:
4549 "directly."
4650 )
4751 self ._value = value
52+ self ._encoding = encoding
4853 # Validate that we can retrieve a value
4954 value = self .get_value ()
5055 if not isinstance (value , str ) or not value :
@@ -86,6 +91,9 @@ def get_value(self) -> str:
8691 return value
8792 return self ._value
8893
94+ def _get_value_bytes (self ) -> bytes :
95+ return self .get_value ().encode (self ._encoding )
96+
8997 def __str__ (self ) -> str :
9098 return "******" # Never expose the actual value
9199
@@ -102,9 +110,11 @@ def __eq__(self, other: object) -> bool:
102110 if isinstance (other , str ):
103111 # Using constant-time comparison to prevent timing attacks, with
104112 # secrets.compare_digest.
105- return secrets .compare_digest (self .get_value (), other )
113+ return secrets .compare_digest (
114+ self ._get_value_bytes (), other .encode (self ._encoding , errors = "ignore" )
115+ )
106116
107117 if not isinstance (other , Secret ):
108118 return NotImplemented
109119
110- return secrets .compare_digest (self .get_value (), other .get_value ())
120+ return secrets .compare_digest (self ._get_value_bytes (), other ._get_value_bytes ())
0 commit comments