Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ anyhow = "1"
chrono = "0.4"
once_cell = "1.21"
sequoia-openpgp = { version = "2.4", default-features = false, features = [ "crypto-rust", "allow-experimental-crypto", "allow-variable-time-crypto", "compression-deflate"] }
sequoia-policy-config = "0.8.2"

[features]
system-policy-default = []

[dependencies.pyo3]
version = "0.30.1"
Expand Down
37 changes: 7 additions & 30 deletions NEXT.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,18 @@
# Next version changes
## This file contains changes that will be included in the next version that is released
v0.1.35

The biggest change in this release is the `Cert`/`Tsk` split.
Previously, the `Cert` class was used for both certificates (containing only public parts) and TSKs (secret keys).
The `Tsk` class was obtained through the `secrets` accessor of the `Cert`.

For better security, ergonomics, and alignment with the Stateless OpenPGP specification, this has been reversed:
- `Tsk.from_*` functions are available for reading secret keys
- A `Cert` can be extracted from a `Tsk` via the `extract_certificate` function

Note that all old APIs continue to work and will trigger deprecation warnings with migration suggestions.
There are no plans to remove the old APIs, and we have tests to verify that they continue to work.

In the long term, this will ensure that handing a `Cert` object to a different function will not allow it to elevate privileges and extract secret components.
Code that explicitly deals with sensitive key material in the form of `Tsk` will also be easier to spot.

`Tsk`s are, by design, quite limited in features and do not try to mimic `Cert`s.
This is a step towards a future of non-software keys, where the signer or decryptor may live in an HSM.

More details are available in the [issue comment](https://github.com/wiktor-k/pysequoia/pull/79#issuecomment-5327913731).
v0.1.36

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I asked this before, but why not just keep a running changelog?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use that file to fill in tag description but maybe a running file would be a better idea. We would have to pre-fill it from tags in a separate PR.


New:
- `Tsk` now supports `__bytes__` and `__repr__` [#73]
- `verify` now supports compressed signatures [#77]
- `Cert.generate` has a new option to control expiration: `validity_seconds` [#75]
- `Packet` now supports `__bytes__` to get the full serialized packet [#85]
- Post-quantum cryptography (PQC) support via sequoia-openpgp 2.4:
- `PublicKeyAlgorithm` now includes PQC variants (ML-DSA, SLH-DSA, ML-KEM)
- New `CipherSuite` enum for `Tsk.generate()` with PQC presets (`MLDSA65_Ed25519`, `MLDSA87_Ed448`)
- New `SigningAlgorithm` and `EncryptionAlgorithm` enums for fine-grained algorithm selection (e.g. SLH-DSA signing with classical encryption)
- Load custom cryptographic policies from Sequoia configuration files.
- Apply custom policies when reading certificates and secret keys and performing cryptographic operations (example: working with keys/signatures which use SHA-1 in binding signatures)
- Provide `system-policy-default` feature, which adopts the system Sequoia policy by default at import time. Intended for distribution package builds.
- Show the configuration file used by a policy in its representation.

Fixed:
- `Packet.body` now returns just the body bytes without the tag and length header [#85]
-

Changed:
- `Tsk.generate(validity_seconds)` defaults to `None` [#89]
-

Removed:
-
Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -423,14 +423,14 @@ os.unlink(output_path)
The `Cert` class represents one OpenPGP certificate (commonly called a
"public key").

This package additionally verifies the certificate using Sequoia PGP's
[`StandardPolicy`][SP]. This means that certificates using weak
This package additionally verifies the certificate using its default
[cryptographic policy](docs/policy.md). This means that certificates using weak
cryptography can fail to load, or present a different view than in
other OpenPGP software (e.g. if a User ID uses SHA-1 in its
back-signature, it may be missing from the list of User IDs returned
by this package).

[SP]: https://docs.rs/sequoia-openpgp/latest/sequoia_openpgp/policy/struct.StandardPolicy.html
To choose a different policy, see [Cryptographic policies](docs/policy.md).

Certificates have two forms, one is ASCII armored and one is raw bytes:

Expand All @@ -455,6 +455,10 @@ print(f"Bytes of the TSK: {bytes(tsk)!r}")
Certificates can be parsed from files (`Cert.from_file`) or bytes in
memory (`Cert.from_bytes`).

Pass `policy=policy` when reading a certificate or secret key to use a custom
policy for later operations on that object. The policy is also retained by
certificates extracted from a secret key.

```python
cert1 = Tsk.generate("Test <test@example.com>").extract_certificate()
buffer = bytes(cert1)
Expand Down
62 changes: 62 additions & 0 deletions docs/policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Cryptographic policies

PySequoia uses the build's default cryptographic policy when reading or using
certificates, verifying signatures, or decrypting messages. To use a different
policy, load one from a Sequoia configuration file and pass it to the operation.
For example, a configuration file can permit legacy SHA-1 certificate signatures
without permitting SHA-1 data signatures:

```toml
[hash_algorithms]
sha1.second_preimage_resistance = "always"
```

```python
from pysequoia import Policy, verify

policy = Policy.from_sequoia_config_file("/path/to/policy.toml")
result = verify(signed, get_certs_verify, policy=policy)
```

The policy can also be passed to certificate and secret key readers, such as
`Cert.from_file` and `Tsk.from_file`, and to `decrypt` and `decrypt_file`.
`repr(policy)` shows the configuration path or indicates that the policy uses
the build's default.

## Using a system policy configuration

To use a Sequoia policy managed by the operating system, omit the path:

```python
policy = Policy.from_sequoia_config_file()
result = verify(signed, get_certs_verify, policy=policy)
```

With no path, `from_sequoia_config_file` reads the absolute path in
`SEQUOIA_CRYPTO_POLICY` when that variable is set. Otherwise, it reads
`/etc/crypto-policies/back-ends/sequoia.config`.

This default path is a Sequoia convention, not a guarantee across Linux
distributions. Check that supported distributions provide a config there before
relying on it.

Setting `SEQUOIA_CRYPTO_POLICY` to an empty string explicitly selects
the built-in default policy. A missing or invalid file raises an exception
instead of falling back to the default policy.

Distributions can build with the Cargo feature `system-policy-default` to use
the system policy by default for operations where no policy is passed. The
configuration is loaded at import time. If the file is missing or invalid,
the import fails. Ensure `/etc/crypto-policies/back-ends/sequoia.config` exists
or set `SEQUOIA_CRYPTO_POLICY` to another absolute path. Explicitly passed
policies still override the default.

The feature selects a Sequoia policy; it does not change the cryptographic
backend or load OpenSSL configuration.

For the security properties and other advanced policy controls, see Sequoia's
[policy documentation][policy-docs] and its
[policy configuration format][policy-config].

[policy-docs]: https://docs.rs/sequoia-openpgp/latest/sequoia_openpgp/policy/index.html
[policy-config]: https://docs.rs/sequoia-policy-config/latest/sequoia_policy_config/
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "maturin"

[project]
name = "pysequoia"
version = "0.1.35"
version = "0.1.36"
requires-python = ">=3.7"
readme = "README.md"
classifiers = [
Expand Down
Loading
Loading