Skip to content
Closed
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
149 changes: 128 additions & 21 deletions pep-0543.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Type: Standards Track
Content-Type: text/x-rst
Created: 17-Oct-2016
Python-Version: 3.7
Post-History: 11-Jan-2017, 19-Jan-2017, 02-Feb-2017, 09-Feb-2017
Post-History: 11-Jan-2017, 19-Jan-2017, 02-Feb-2017, 09-Feb-2017, 29-Dec-2017


Abstract
Expand Down Expand Up @@ -1256,6 +1256,32 @@ The definitions of the errors are below::
attack and so can ignore this exception.
"""

File format
~~~~~~~~~~~

Certificates and private keys can be encoded in multiple ways. The most
important file formats are DER and PEM. DER (*Distinguished Encoding
Rules*) describes ASN.1 data structure as bytes. The PEM format is
base64-encoded DER with a header, footer, and optional metadata. For
example a PEM-encoded encrypted private key in PKCS#8 format has additional
PKCS#5 metadata. A file in DER format can only contain one certificate or
key, while a PEM encoded file can contain multiple certs and a key together
with additional text.

A PKCS#12 file is an archive format private keys, certificates, trust
anchors and other data with optional encryption and signature. The PKCS#12
format is out of scope.

::

class FileFormat(Enum):
DER = auto()
PEM = auto()

Libraries may define their own file formats, too. For example OpenSSL has
trusted certificates, which are regular PEM-encoded certificates with an AUX
section appended.


Certificates
~~~~~~~~~~~~
Expand Down Expand Up @@ -1283,19 +1309,28 @@ an individual concrete implementation are also hashable.

class Certificate(metaclass=ABCMeta):
@abstractclassmethod
def from_buffer(cls, buffer: bytes):
def from_buffer(
cls,
buffer: bytes,
*,
password: Optional[Union[Callable[[], Union[bytes, bytearray]], bytes, bytearray]] = None,
format: FileFormat = FileFormat.PEM
) -> Certificate:
"""
Creates a Certificate object from a byte buffer. This byte buffer
may be either PEM-encoded or DER-encoded. If the buffer is PEM
encoded it *must* begin with the standard PEM preamble (a series of
dashes followed by the ASCII bytes "BEGIN CERTIFICATE" and another
series of dashes). In the absence of that preamble, the
implementation may assume that the certificate is DER-encoded
instead.
may be either PEM-encoded or DER-encoded. The password argument
may be used in the future for additional file formats like
PKCS#12 files.
"""

@abstractclassmethod
def from_file(cls, path: Union[pathlib.Path, AnyStr]):
def from_file(
cls,
path: Union[pathlib.Path, AnyStr],
*,
password: Optional[Union[Callable[[], Union[bytes, bytearray]], bytes, bytearray]] = None,
format: FileFormat = FileFormat.PEM
) -> Certificate:
"""
Creates a Certificate object from a file on disk. This method may
be a convenience method that wraps ``open`` and ``from_buffer``,
Expand All @@ -1304,6 +1339,75 @@ an individual concrete implementation are also hashable.
code.
"""

@abstractclassmethod
def chain_from_buffer(
cls,
buffer: bytes,
*,
password: Optional[Union[Callable[[], Union[bytes, bytearray]], bytes, bytearray]] = None,
format: FileFormat = FileFormat.PEM
) -> Tuple[Certificate]:
"""
Creates a Certificate object from a byte buffer. This byte buffer
must be PEM-encoded. The password and format arguments are
currently not used.
"""

@abstractclassmethod
def chain_from_file(
cls,
path: Union[pathlib.Path, AnyStr],
*,
password: Optional[Union[Callable[[], Union[bytes, bytearray]], bytes, bytearray]] = None,
format: FileFormat = FileFormat.PEM
) -> Tuple[Certificate]:
"""
Creates a Certificate chain from a file on disk. This method may
be a convenience method that wraps ``open`` and
``chain_from_buffer``, but some TLS implementations may be able
to provide more-secure or faster methods of loading certificates
that do not involve Python code.

A certificate chain must start with the end-entity cert (server
or client cert) and may be followed by one or more intermediate
CA certs. The second cert must be the issuer of the first cert,
the third cert the issuer of the second cert, and so on. The
chain must not contain a trust anchor (root cert).
"""

@abstractclassmethod
def bundle_from_buffer(
cls,
buffer: bytes,
*,
password: Optional[Union[Callable[[], Union[bytes, bytearray]], bytes, bytearray]] = None,
format: FileFormat = FileFormat.PEM
) -> List[Certificate]:
"""
Creates a bundle of Certificate objects from a byte buffer. This
byte buffer must be PEM-encoded. The password and format
arguments are currently not used.
"""

@abstractclassmethod
def bundle_from_file(
cls,
path: Union[pathlib.Path, AnyStr],
*,
password: Optional[Union[Callable[[], Union[bytes, bytearray]], bytes, bytearray]] = None,
format: FileFormat = FileFormat.PEM
) -> List[Certificate]:
"""
Creates a Certificate bundle from a file on disk. This method may
be a convenience method that wraps ``open`` and
``bundle_from_buffer``, but some TLS implementations may be able
to provide more-secure or faster methods of loading certificates
that do not involve Python code.
"""

def dump(self, format: FileFormat = FileFormat.PEM) -> bytes:
"""Dump certificate as PEM or DER-encoded bytes.
"""

Private Keys
~~~~~~~~~~~~
Expand All @@ -1318,17 +1422,16 @@ This class has all the caveats of the ``Certificate`` class.

class PrivateKey(metaclass=ABCMeta):
@abstractclassmethod
def from_buffer(cls,
buffer: bytes,
password: Optional[Union[Callable[[], Union[bytes, bytearray]], bytes, bytearray]] = None):
def from_buffer(
cls,
buffer: bytes,
*,
password: Optional[Union[Callable[[], Union[bytes, bytearray]], bytes, bytearray]] = None,
format: FileFormat = FileFormat.PEM
) -> PrivateKey:
"""
Creates a PrivateKey object from a byte buffer. This byte buffer
may be either PEM-encoded or DER-encoded. If the buffer is PEM
encoded it *must* begin with the standard PEM preamble (a series of
dashes followed by the ASCII bytes "BEGIN", the key type, and
another series of dashes). In the absence of that preamble, the
implementation may assume that the certificate is DER-encoded
instead.
may be either PEM-encoded or DER-encoded.

The key may additionally be encrypted. If it is, the ``password``
argument can be used to decrypt the key. The ``password`` argument
Expand All @@ -1342,9 +1445,13 @@ This class has all the caveats of the ``Certificate`` class.
"""

@abstractclassmethod
def from_file(cls,
path: Union[pathlib.Path, bytes, str],
password: Optional[Union[Callable[[], Union[bytes, bytearray]], bytes, bytearray]] = None):
def from_file(
cls,
path: Union[pathlib.Path, bytes, str],
*,
password: Optional[Union[Callable[[], Union[bytes, bytearray]], bytes, bytearray]] = None,
format: FileFormat = FileFormat.PEM
) -> PrivateKey:
"""
Creates a PrivateKey object from a file on disk. This method may
be a convenience method that wraps ``open`` and ``from_buffer``,
Expand Down