Repository: pydantic/pydantic

Issue:
Hashable SecretStr
### Initial Checks

- [X] I have searched Google & GitHub for similar requests and couldn't find anything
- [X] I have read and followed [the docs](https://pydantic-docs.helpmanual.io) and still think this feature is missing

### Description

I'd like to see instances of the pydantic class `SecretStr` to be hashable like instances of the `str` class are hashable.

I use it mainly in instances of `BaseSettings` and during startup of a server application, I add settings classes which I can successfully construct in a set. This gives me an indication of missing configuration values.
But models containing fields annotated with `SecretStr` currently cannot be added to a set as Python complains about the `SecretStr` type: `TypeError: unhashable type: 'SecretStr'`

Example snippet:

```py
import pydantic

class M(pydantic.BaseModel):
    s: pydantic.SecretStr = pydantic.SecretStr("secret")

    def __hash__(self):
        return hash((type(self),) + tuple(self.__dict__.values()))

def test_can_hash():
    assert hash(M())
```

### Affected Components

- [ ] [Compatibility between releases](https://pydantic-docs.helpmanual.io/changelog/)
- [ ] [Data validation/parsing](https://pydantic-docs.helpmanual.io/usage/models/#basic-model-usage)
- [ ] [Data serialization](https://pydantic-docs.helpmanual.io/usage/exporting_models/) - `.dict()` and `.json()`
- [ ] [JSON Schema](https://pydantic-docs.helpmanual.io/usage/schema/)
- [ ] [Dataclasses](https://pydantic-docs.helpmanual.io/usage/dataclasses/)
- [ ] [Model Config](https://pydantic-docs.helpmanual.io/usage/model_config/)
- [ ] [Field Types](https://pydantic-docs.helpmanual.io/usage/types/) - adding or changing a particular data type
- [ ] [Function validation decorator](https://pydantic-docs.helpmanual.io/usage/validation_decorator/)
- [ ] [Generic Models](https://pydantic-docs.helpmanual.io/usage/models/#generic-models)
- [X] [Other Model behaviour](https://pydantic-docs.helpmanual.io/usage/models/) - `construct()`, pickling, private attributes, ORM mode
- [ ] [Settings Management](https://pydantic-docs.helpmanual.io/usage/settings/)
- [ ] [Plugins](https://pydantic-docs.helpmanual.io/) and integration with other tools - mypy, FastAPI, python-devtools, Hypothesis, VS Code, PyCharm, etc.


Discussion:
please give more details on what you're asking for and how it would be useful.

Closing but happy to reopen if more details are provided.

Resolving patch:
diff --git a/pydantic/types.py b/pydantic/types.py
--- a/pydantic/types.py
+++ b/pydantic/types.py
@@ -834,6 +834,9 @@ def __eq__(self, other: Any) -> bool:
     def __str__(self) -> str:
         return '**********' if self.get_secret_value() else ''
 
+    def __hash__(self) -> int:
+        return hash(self.get_secret_value())
+
     @abc.abstractmethod
     def get_secret_value(self) -> Any:  # pragma: no cover
         ...


Test patch:
diff --git a/tests/test_types.py b/tests/test_types.py
--- a/tests/test_types.py
+++ b/tests/test_types.py
@@ -2650,6 +2650,10 @@ class Foobar(BaseModel):
     assert m.password.get_secret_value() == '1234'
 
 
+def test_secretstr_is_hashable():
+    assert type(hash(SecretStr('secret'))) is int
+
+
 def test_secretstr_error():
     class Foobar(BaseModel):
         password: SecretStr
@@ -2742,6 +2746,10 @@ class Foobar(BaseModel):
     _ = Foobar(password=SecretBytes(b'1234'))
 
 
+def test_secretbytes_is_hashable():
+    assert type(hash(SecretBytes(b'secret'))) is int
+
+
 def test_secretbytes_error():
     class Foobar(BaseModel):
         password: SecretBytes