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
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/dh.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ def private_bytes(
encoding: _serialization.Encoding,
format: _serialization.PrivateFormat,
encryption_algorithm: _serialization.KeySerializationEncryption,
*,
comment: bytes = b"",
) -> bytes:
"""
Returns the key serialized as bytes.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/dsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ def private_bytes(
encoding: _serialization.Encoding,
format: _serialization.PrivateFormat,
encryption_algorithm: _serialization.KeySerializationEncryption,
*,
comment: bytes = b"",
) -> bytes:
"""
Returns the key serialized as bytes.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/ec.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ def private_bytes(
encoding: _serialization.Encoding,
format: _serialization.PrivateFormat,
encryption_algorithm: _serialization.KeySerializationEncryption,
*,
comment: bytes = b"",
) -> bytes:
"""
Returns the key serialized as bytes.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/ed25519.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ def private_bytes(
encoding: _serialization.Encoding,
format: _serialization.PrivateFormat,
encryption_algorithm: _serialization.KeySerializationEncryption,
*,
comment: bytes = b"",
) -> bytes:
"""
The serialized bytes of the private key.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/ed448.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ def private_bytes(
encoding: _serialization.Encoding,
format: _serialization.PrivateFormat,
encryption_algorithm: _serialization.KeySerializationEncryption,
*,
comment: bytes = b"",
) -> bytes:
"""
The serialized bytes of the private key.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/mldsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ def private_bytes(
encoding: _serialization.Encoding,
format: _serialization.PrivateFormat,
encryption_algorithm: _serialization.KeySerializationEncryption,
*,
comment: bytes = b"",
) -> bytes:
"""
The serialized bytes of the private key.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/mlkem.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ def private_bytes(
encoding: _serialization.Encoding,
format: _serialization.PrivateFormat,
encryption_algorithm: _serialization.KeySerializationEncryption,
*,
comment: bytes = b"",
) -> bytes:
"""
The serialized bytes of the private key.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/rsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ def private_bytes(
encoding: _serialization.Encoding,
format: _serialization.PrivateFormat,
encryption_algorithm: _serialization.KeySerializationEncryption,
*,
comment: bytes = b"",
) -> bytes:
"""
Returns the key serialized as bytes.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/x25519.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ def private_bytes(
encoding: _serialization.Encoding,
format: _serialization.PrivateFormat,
encryption_algorithm: _serialization.KeySerializationEncryption,
*,
comment: bytes = b"",
) -> bytes:
"""
The serialized bytes of the private key.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/x448.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ def private_bytes(
encoding: _serialization.Encoding,
format: _serialization.PrivateFormat,
encryption_algorithm: _serialization.KeySerializationEncryption,
*,
comment: bytes = b"",
) -> bytes:
"""
The serialized bytes of the private key.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/primitives/serialization/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
SSHPrivateKeyTypes,
SSHPublicKeyTypes,
load_ssh_private_key,
load_ssh_private_key_with_comment,
load_ssh_public_identity,
load_ssh_public_key,
ssh_key_fingerprint,
Expand Down Expand Up @@ -61,6 +62,7 @@
"load_pem_private_key",
"load_pem_public_key",
"load_ssh_private_key",
"load_ssh_private_key_with_comment",
"load_ssh_public_identity",
"load_ssh_public_key",
"ssh_key_fingerprint",
Expand Down
43 changes: 34 additions & 9 deletions src/cryptography/hazmat/primitives/serialization/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,14 +669,17 @@ def _lookup_kformat(key_type: utils.Buffer):
]


def load_ssh_private_key(
def load_ssh_private_key_with_comment(
data: utils.Buffer,
password: bytes | None,
backend: typing.Any = None,
*,
unsafe_skip_rsa_key_validation: bool = False,
) -> SSHPrivateKeyTypes:
"""Load private key from OpenSSH custom encoding."""
) -> tuple[SSHPrivateKeyTypes, bytes]:
"""
Load private key from OpenSSH custom encoding and
return (key, comment).
"""
utils._check_byteslike("data", data)
if password is not None:
utils._check_bytes("password", password)
Expand Down Expand Up @@ -772,8 +775,9 @@ def load_ssh_private_key(
pubfields,
unsafe_skip_rsa_key_validation=unsafe_skip_rsa_key_validation,
)
# We don't use the comment
_, edata = _get_sshstr(edata)

# Capture the comment instead of discarding it with _
comment, edata = _get_sshstr(edata)

# yes, SSH does padding check *after* all other parsing is done.
# need to follow as it writes zero-byte padding too.
Expand All @@ -788,20 +792,39 @@ def load_ssh_private_key(
stacklevel=2,
)

return private_key, comment.tobytes()


def load_ssh_private_key(
data: utils.Buffer,
password: bytes | None,
backend: typing.Any = None,
*,
unsafe_skip_rsa_key_validation: bool = False,
) -> SSHPrivateKeyTypes:
"""Load private key from OpenSSH custom encoding."""
private_key, _ = load_ssh_private_key_with_comment(
data,
password,
backend,
unsafe_skip_rsa_key_validation=unsafe_skip_rsa_key_validation,
)
return private_key


def _serialize_ssh_private_key(
private_key: SSHPrivateKeyTypes,
password: bytes,
encryption_algorithm: KeySerializationEncryption,
comment: bytes = b"",
) -> bytes:
"""Serialize private key with OpenSSH custom encoding."""
utils._check_bytes("password", password)
utils._check_bytes("comment", comment) # <-- Add validation here
if isinstance(private_key, dsa._DSAPrivateKey):
warnings.warn(
"SSH DSA key support is deprecated and will be "
"removed in a future release",
"SSH DSA key support is deprecated and will be removed in a "
"future release",
utils.DeprecatedIn40,
stacklevel=4,
)
Expand Down Expand Up @@ -831,7 +854,9 @@ def _serialize_ssh_private_key(
ciph = None
nkeys = 1
checkval = os.urandom(4)
comment = b""
# To this (split into two shorter lines):
# comment is passed in as a parameter now, so we don't
# overwrite it with b"" unless default is used

# encode public and private parts together
f_public_key = _FragList()
Expand All @@ -841,7 +866,7 @@ def _serialize_ssh_private_key(
f_secrets = _FragList([checkval, checkval])
f_secrets.put_sshstr(key_type)
kformat.encode_private(private_key, f_secrets)
f_secrets.put_sshstr(comment)
f_secrets.put_sshstr(comment) # <-- Uses the passed comment parameter here
f_secrets.put_raw(_PADDING[: blklen - (f_secrets.size() % blklen)])

# top-level structure
Expand Down
6 changes: 5 additions & 1 deletion src/rust/src/backend/dh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,12 +263,15 @@ impl DHPrivateKey {
})
}

#[pyo3(signature = (encoding, format, encryption_algorithm, *, comment = None))]
#[allow(unused_variables)]
fn private_bytes<'p>(
slf: &pyo3::Bound<'p, Self>,
py: pyo3::Python<'p>,
encoding: crate::serialization::Encoding,
format: crate::serialization::PrivateFormat,
encryption_algorithm: &pyo3::Bound<'p, pyo3::PyAny>,
comment: Option<&pyo3::Bound<'p, pyo3::types::PyBytes>>,
) -> CryptographyResult<pyo3::Bound<'p, pyo3::types::PyBytes>> {
if format != crate::serialization::PrivateFormat::PKCS8 {
return Err(CryptographyError::from(
Expand All @@ -285,8 +288,9 @@ impl DHPrivateKey {
encoding,
format,
encryption_algorithm,
true,
false,
false,
None,
)
}

Expand Down
9 changes: 9 additions & 0 deletions src/rust/src/backend/dsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// for complete details.

use pyo3::types::PyAnyMethods;
use pyo3::types::PyBytesMethods;

use crate::backend::utils;
use crate::buf::CffiBuf;
Expand Down Expand Up @@ -150,13 +151,20 @@ impl DsaPrivateKey {
})
}

#[pyo3(signature = (encoding, format, encryption_algorithm, *, comment = None))]
fn private_bytes<'p>(
slf: &pyo3::Bound<'p, Self>,
py: pyo3::Python<'p>,
encoding: crate::serialization::Encoding,
format: crate::serialization::PrivateFormat,
encryption_algorithm: &pyo3::Bound<'p, pyo3::PyAny>,
comment: Option<&pyo3::Bound<'p, pyo3::types::PyBytes>>,
) -> CryptographyResult<pyo3::Bound<'p, pyo3::types::PyBytes>> {
let comment_bytes = match comment {
Some(b) => b.as_bytes(),
None => b"",
};

utils::pkey_private_bytes(
py,
slf,
Expand All @@ -166,6 +174,7 @@ impl DsaPrivateKey {
encryption_algorithm,
true,
false,
Some(comment_bytes),
)
}

Expand Down
9 changes: 9 additions & 0 deletions src/rust/src/backend/ec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

use pyo3::types::PyAnyMethods;
use pyo3::types::PyBytesMethods;

use crate::backend::utils;
use crate::buf::CffiBuf;
Expand Down Expand Up @@ -340,13 +341,20 @@ impl ECPrivateKey {
})
}

#[pyo3(signature = (encoding, format, encryption_algorithm, *, comment = None))]
fn private_bytes<'p>(
slf: &pyo3::Bound<'p, Self>,
py: pyo3::Python<'p>,
encoding: crate::serialization::Encoding,
format: crate::serialization::PrivateFormat,
encryption_algorithm: &pyo3::Bound<'p, pyo3::PyAny>,
comment: Option<&pyo3::Bound<'p, pyo3::types::PyBytes>>,
) -> CryptographyResult<pyo3::Bound<'p, pyo3::types::PyBytes>> {
let comment_bytes = match comment {
Some(b) => b.as_bytes(),
None => b"",
};

utils::pkey_private_bytes(
py,
slf,
Expand All @@ -356,6 +364,7 @@ impl ECPrivateKey {
encryption_algorithm,
true,
false,
Some(comment_bytes),
)
}

Expand Down
9 changes: 9 additions & 0 deletions src/rust/src/backend/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::backend::utils;
use crate::buf::CffiBuf;
use crate::error::{CryptographyError, CryptographyResult};
use crate::exceptions;
use pyo3::types::PyBytesMethods;

#[pyo3::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.openssl.ed25519")]
pub(crate) struct Ed25519PrivateKey {
Expand Down Expand Up @@ -100,13 +101,20 @@ impl Ed25519PrivateKey {
Ok(pyo3::types::PyBytes::new(py, &raw_bytes))
}

#[pyo3(signature = (encoding, format, encryption_algorithm, *, comment = None))]
fn private_bytes<'p>(
slf: &pyo3::Bound<'p, Self>,
py: pyo3::Python<'p>,
encoding: crate::serialization::Encoding,
format: crate::serialization::PrivateFormat,
encryption_algorithm: &pyo3::Bound<'p, pyo3::PyAny>,
comment: Option<&pyo3::Bound<'p, pyo3::types::PyBytes>>,
) -> CryptographyResult<pyo3::Bound<'p, pyo3::types::PyBytes>> {
let comment_bytes = match comment {
Some(b) => b.as_bytes(),
None => b"",
};

utils::pkey_private_bytes(
py,
slf,
Expand All @@ -116,6 +124,7 @@ impl Ed25519PrivateKey {
encryption_algorithm,
true,
true,
Some(comment_bytes),
)
}

Expand Down
17 changes: 15 additions & 2 deletions src/rust/src/backend/ed448.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::backend::utils;
use crate::buf::CffiBuf;
use crate::error::{CryptographyError, CryptographyResult};
use crate::exceptions;
use pyo3::types::PyAnyMethods;

#[pyo3::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.openssl.ed448")]
pub(crate) struct Ed448PrivateKey {
Expand Down Expand Up @@ -98,22 +99,34 @@ impl Ed448PrivateKey {
Ok(pyo3::types::PyBytes::new(py, &raw_bytes))
}

#[pyo3(signature = (encoding, format, encryption_algorithm, *, comment = None))]
#[allow(unused_variables)]
fn private_bytes<'p>(
slf: &pyo3::Bound<'p, Self>,
py: pyo3::Python<'p>,
encoding: crate::serialization::Encoding,
format: crate::serialization::PrivateFormat,
encryption_algorithm: &pyo3::Bound<'p, pyo3::PyAny>,
comment: Option<&pyo3::Bound<'p, pyo3::types::PyBytes>>,
) -> CryptographyResult<pyo3::Bound<'p, pyo3::types::PyBytes>> {
// Intercept raw requests and route them to private_bytes_raw:
if encoding == crate::serialization::Encoding::Raw
&& format == crate::serialization::PrivateFormat::Raw
&& encryption_algorithm.is_instance(&crate::types::NO_ENCRYPTION.get(py)?)?
{
return slf.borrow().private_bytes_raw(py);
}

utils::pkey_private_bytes(
py,
slf,
&slf.borrow().pkey,
encoding,
format,
encryption_algorithm,
true,
true,
false,
false,
None,
)
}

Expand Down
Loading
Loading