http-message-signatures 0.4.4__py3-none-any.whl → 0.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  from . import algorithms # noqa:F401
2
2
  from .algorithms import HTTPSignatureAlgorithm # noqa:F401
3
3
  from .exceptions import HTTPMessageSignaturesException, InvalidSignature # noqa:F401
4
- from .resolvers import HTTPSignatureComponentResolver, HTTPSignatureKeyResolver # noqa:F401
4
+ from .resolvers import HTTPSignatureComponentResolver # noqa:F401
5
+ from .resolvers import HTTPSignatureKeyResolver # noqa: F401
5
6
  from .signatures import HTTPMessageSigner, HTTPMessageVerifier # noqa:F401
6
7
  from .structures import VerifyResult # noqa:F401
@@ -1,7 +1,13 @@
1
1
  from cryptography.hazmat.primitives import hashes, hmac
2
2
  from cryptography.hazmat.primitives.asymmetric import ec, ed25519, padding, rsa
3
- from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature, encode_dss_signature
4
- from cryptography.hazmat.primitives.serialization import load_pem_private_key, load_pem_public_key
3
+ from cryptography.hazmat.primitives.asymmetric.utils import (
4
+ decode_dss_signature,
5
+ encode_dss_signature,
6
+ )
7
+ from cryptography.hazmat.primitives.serialization import (
8
+ load_pem_private_key,
9
+ load_pem_public_key,
10
+ )
5
11
 
6
12
  from .exceptions import HTTPMessageSignaturesException
7
13
 
@@ -41,15 +47,10 @@ class RSA_PSS_SHA512(HTTPSignatureAlgorithm, PEMKeyLoader):
41
47
  self.hash_algorithm: hashes.HashAlgorithm = hashes.SHA512()
42
48
 
43
49
  def sign(self, message: bytes):
44
- return self.private_key.sign(data=message,
45
- padding=self.padding,
46
- algorithm=self.hash_algorithm)
50
+ return self.private_key.sign(data=message, padding=self.padding, algorithm=self.hash_algorithm)
47
51
 
48
52
  def verify(self, signature: bytes, message: bytes):
49
- self.public_key.verify(signature=signature,
50
- data=message,
51
- padding=self.padding,
52
- algorithm=self.hash_algorithm)
53
+ self.public_key.verify(signature=signature, data=message, padding=self.padding, algorithm=self.hash_algorithm)
53
54
 
54
55
 
55
56
  class RSA_V1_5_SHA256(RSA_PSS_SHA512):
@@ -90,27 +91,24 @@ class ECDSA_P256_SHA256(HTTPSignatureAlgorithm, PEMKeyLoader):
90
91
  raise HTTPMessageSignaturesException("Unexpected public key type")
91
92
  if self.private_key and not isinstance(self.private_key, ec.EllipticCurvePrivateKey):
92
93
  raise HTTPMessageSignaturesException("Unexpected private key type")
93
- if self.public_key and type(self.public_key.curve) != ec.SECP256R1:
94
+ if self.public_key and not isinstance(self.public_key.curve, ec.SECP256R1):
94
95
  raise HTTPMessageSignaturesException("Unexpected elliptic curve type in public key")
95
- if self.private_key and type(self.private_key.curve) != ec.SECP256R1:
96
+ if self.private_key and not isinstance(self.private_key.curve, ec.SECP256R1):
96
97
  raise HTTPMessageSignaturesException("Unexpected elliptic curve type in private key")
97
98
  self.signature_algorithm = ec.ECDSA(hashes.SHA256())
98
99
 
99
100
  def sign(self, message: bytes):
100
- der_sig = self.private_key.sign(message,
101
- signature_algorithm=self.signature_algorithm)
101
+ der_sig = self.private_key.sign(message, signature_algorithm=self.signature_algorithm)
102
102
  r, s = decode_dss_signature(der_sig)
103
- return r.to_bytes(32, byteorder='big') + s.to_bytes(32, byteorder='big')
103
+ return r.to_bytes(32, byteorder="big") + s.to_bytes(32, byteorder="big")
104
104
 
105
105
  def verify(self, signature: bytes, message: bytes):
106
106
  if len(signature) != 64:
107
107
  raise HTTPMessageSignaturesException("Unexpected signature length")
108
- r = int.from_bytes(signature[:32], byteorder='big')
109
- s = int.from_bytes(signature[32:], byteorder='big')
108
+ r = int.from_bytes(signature[:32], byteorder="big")
109
+ s = int.from_bytes(signature[32:], byteorder="big")
110
110
  der_sig = encode_dss_signature(r, s)
111
- self.public_key.verify(signature=der_sig,
112
- data=message,
113
- signature_algorithm=self.signature_algorithm)
111
+ self.public_key.verify(signature=der_sig, data=message, signature_algorithm=self.signature_algorithm)
114
112
 
115
113
 
116
114
  class ED25519(HTTPSignatureAlgorithm, PEMKeyLoader):
@@ -2,5 +2,5 @@ class HTTPMessageSignaturesException(Exception):
2
2
  "Base class for exceptions raised by http_message_signatures"
3
3
 
4
4
 
5
- class InvalidSignature(Exception):
5
+ class InvalidSignature(HTTPMessageSignaturesException):
6
6
  "Class for exceptions raised in the course of verifying an HTTP message signature"
@@ -17,7 +17,7 @@ class HTTPSignatureComponentResolver:
17
17
  "@query",
18
18
  "@query-params",
19
19
  "@status",
20
- "@request-response"
20
+ "@request-response",
21
21
  }
22
22
 
23
23
  # TODO: describe interface
@@ -33,7 +33,7 @@ class HTTPSignatureComponentResolver:
33
33
  component_id = str(component_node.value)
34
34
  if component_id.startswith("@"): # derived component
35
35
  if component_id not in self.derived_component_names:
36
- raise HTTPMessageSignaturesException(f'Unknown covered derived component name {component_id}')
36
+ raise HTTPMessageSignaturesException(f"Unknown covered derived component name {component_id}")
37
37
  resolver = getattr(self, "get_" + component_id[1:].replace("-", "_"))
38
38
  return resolver(**component_node.params)
39
39
  if component_id not in self.headers:
@@ -68,7 +68,7 @@ class HTTPSignatureComponentResolver:
68
68
  if name not in query:
69
69
  raise HTTPMessageSignaturesException(f'Query parameter "{name}" not found in the message URL')
70
70
  if len(query[name]) != 1:
71
- raise HTTPMessageSignaturesException('Query parameters with multiple values are not supported.')
71
+ raise HTTPMessageSignaturesException("Query parameters with multiple values are not supported.")
72
72
  return query[name][0]
73
73
 
74
74
  def get_status(self):
@@ -1,7 +1,7 @@
1
1
  import collections
2
2
  import datetime
3
3
  import logging
4
- from typing import Any, Dict, List, Sequence, Tuple, Type
4
+ from typing import Any, Dict, List, Optional, Sequence, Tuple, Type
5
5
 
6
6
  import http_sfv
7
7
 
@@ -14,27 +14,24 @@ logger = logging.getLogger(__name__)
14
14
 
15
15
 
16
16
  class HTTPSignatureHandler:
17
- signature_metadata_parameters = {
18
- "alg",
19
- "created",
20
- "expires",
21
- "keyid",
22
- "nonce"
23
- }
24
-
25
- def __init__(self, *,
26
- signature_algorithm: Type[HTTPSignatureAlgorithm],
27
- key_resolver: HTTPSignatureKeyResolver,
28
- component_resolver_class: type = HTTPSignatureComponentResolver):
17
+ signature_metadata_parameters = {"alg", "created", "expires", "keyid", "nonce", "tag"}
18
+
19
+ def __init__(
20
+ self,
21
+ *,
22
+ signature_algorithm: Type[HTTPSignatureAlgorithm],
23
+ key_resolver: HTTPSignatureKeyResolver,
24
+ component_resolver_class: type = HTTPSignatureComponentResolver,
25
+ ):
29
26
  if signature_algorithm not in signature_algorithms.values():
30
27
  raise HTTPMessageSignaturesException(f"Unknown signature algorithm {signature_algorithm}")
31
28
  self.signature_algorithm = signature_algorithm
32
29
  self.key_resolver = key_resolver
33
30
  self.component_resolver_class = component_resolver_class
34
31
 
35
- def _build_signature_base(self, message, *,
36
- covered_component_ids: List[Any],
37
- signature_params: Dict[str, str]) -> Tuple:
32
+ def _build_signature_base(
33
+ self, message, *, covered_component_ids: List[Any], signature_params: Dict[str, str]
34
+ ) -> Tuple:
38
35
  assert "@signature-params" not in covered_component_ids
39
36
  sig_elements = collections.OrderedDict()
40
37
  component_resolver = self.component_resolver_class(message)
@@ -48,8 +45,9 @@ class HTTPSignatureHandler:
48
45
  if "\n" in component_key:
49
46
  raise HTTPMessageSignaturesException(f'Component ID "{component_key}" contains newline character')
50
47
  if component_key in sig_elements:
51
- raise HTTPMessageSignaturesException(f'Component ID "{component_key}" appeared multiple times in '
52
- 'signature input')
48
+ raise HTTPMessageSignaturesException(
49
+ f'Component ID "{component_key}" appeared multiple times in signature input'
50
+ )
53
51
  sig_elements[component_key] = component_value
54
52
  sig_params_node = http_sfv.InnerList(covered_component_ids)
55
53
  sig_params_node.params.update(signature_params)
@@ -72,14 +70,19 @@ class HTTPMessageSigner(HTTPSignatureHandler):
72
70
  covered_component_nodes.append(component_name_node)
73
71
  return covered_component_nodes
74
72
 
75
- def sign(self, message, *,
76
- key_id: str,
77
- created: datetime.datetime = None,
78
- expires: datetime.datetime = None,
79
- nonce: str = None,
80
- label: str = None,
81
- include_alg: bool = True,
82
- covered_component_ids: Sequence[str] = ("@method", "@authority", "@target-uri")):
73
+ def sign(
74
+ self,
75
+ message,
76
+ *,
77
+ key_id: str,
78
+ created: Optional[datetime.datetime] = None,
79
+ expires: Optional[datetime.datetime] = None,
80
+ nonce: Optional[str] = None,
81
+ label: Optional[str] = None,
82
+ tag: Optional[str] = None,
83
+ include_alg: bool = True,
84
+ covered_component_ids: Sequence[str] = ("@method", "@authority", "@target-uri"),
85
+ ):
83
86
  # TODO: Accept-Signature autonegotiation
84
87
  key = self.key_resolver.resolve_private_key(key_id)
85
88
  if created is None:
@@ -91,13 +94,13 @@ class HTTPMessageSigner(HTTPSignatureHandler):
91
94
  signature_params["expires"] = int(expires.timestamp())
92
95
  if nonce:
93
96
  signature_params["nonce"] = nonce
97
+ if tag:
98
+ signature_params["tag"] = tag
94
99
  if include_alg:
95
100
  signature_params["alg"] = self.signature_algorithm.algorithm_id
96
101
  covered_component_nodes = self._parse_covered_component_ids(covered_component_ids)
97
102
  sig_base, sig_params_node, _ = self._build_signature_base(
98
- message,
99
- covered_component_ids=covered_component_nodes,
100
- signature_params=signature_params
103
+ message, covered_component_ids=covered_component_nodes, signature_params=signature_params
101
104
  )
102
105
  signer = self.signature_algorithm(private_key=key)
103
106
  signature = signer.sign(sig_base.encode())
@@ -111,6 +114,7 @@ class HTTPMessageSigner(HTTPSignatureHandler):
111
114
 
112
115
 
113
116
  class HTTPMessageVerifier(HTTPSignatureHandler):
117
+ max_clock_skew: datetime.timedelta = datetime.timedelta(seconds=5)
114
118
  require_created: bool = True
115
119
 
116
120
  def _parse_dict_header(self, header_name, headers):
@@ -133,17 +137,19 @@ class HTTPMessageVerifier(HTTPSignatureHandler):
133
137
 
134
138
  def validate_created_and_expires(self, sig_input, max_age=None):
135
139
  now = datetime.datetime.now()
140
+ min_time = now - self.max_clock_skew
141
+ max_time = now + self.max_clock_skew
136
142
  if "created" in sig_input.params:
137
- if self._parse_integer_timestamp(sig_input.params["created"], field_name="created") > now:
143
+ if self._parse_integer_timestamp(sig_input.params["created"], field_name="created") > max_time:
138
144
  raise InvalidSignature('Signature "created" parameter is set to a time in the future')
139
145
  elif self.require_created:
140
146
  raise InvalidSignature('Signature is missing a required "created" parameter')
141
147
  if "expires" in sig_input.params:
142
- if self._parse_integer_timestamp(sig_input.params["expires"], field_name="expires") < now:
148
+ if self._parse_integer_timestamp(sig_input.params["expires"], field_name="expires") < min_time:
143
149
  raise InvalidSignature('Signature "expires" parameter is set to a time in the past')
144
150
  if max_age is not None:
145
- if self._parse_integer_timestamp(sig_input.params["created"], field_name="created") + max_age < now:
146
- raise InvalidSignature(f'Signature age exceeds maximum allowable age {max_age}')
151
+ if self._parse_integer_timestamp(sig_input.params["created"], field_name="created") + max_age < min_time:
152
+ raise InvalidSignature(f"Signature age exceeds maximum allowable age {max_age}")
147
153
 
148
154
  def verify(self, message, *, max_age: datetime.timedelta = datetime.timedelta(days=1)) -> List[VerifyResult]:
149
155
  sig_inputs = self._parse_dict_header("Signature-Input", message.headers)
@@ -165,9 +171,7 @@ class HTTPMessageVerifier(HTTPSignatureHandler):
165
171
  raise InvalidSignature(f'Unexpected signature metadata parameter "{param}"')
166
172
  try:
167
173
  sig_base, sig_params_node, sig_elements = self._build_signature_base(
168
- message,
169
- covered_component_ids=list(sig_input),
170
- signature_params=sig_input.params
174
+ message, covered_component_ids=list(sig_input), signature_params=sig_input.params
171
175
  )
172
176
  except Exception as e:
173
177
  raise InvalidSignature(e) from e
@@ -177,10 +181,12 @@ class HTTPMessageVerifier(HTTPSignatureHandler):
177
181
  verifier.verify(signature=raw_signature, message=sig_base.encode())
178
182
  except Exception as e:
179
183
  raise InvalidSignature(e) from e
180
- verify_result = VerifyResult(label=label,
181
- algorithm=self.signature_algorithm,
182
- covered_components=sig_elements,
183
- parameters=dict(sig_params_node.params),
184
- body=None)
184
+ verify_result = VerifyResult(
185
+ label=label,
186
+ algorithm=self.signature_algorithm,
187
+ covered_components=sig_elements,
188
+ parameters=dict(sig_params_node.params),
189
+ body=None,
190
+ )
185
191
  verify_results.append(verify_result)
186
192
  return verify_results
@@ -34,11 +34,7 @@ class CaseInsensitiveDict(MutableMapping):
34
34
 
35
35
  def lower_items(self):
36
36
  """Like iteritems(), but with all lowercase keys."""
37
- return (
38
- (lowerkey, keyval[1])
39
- for (lowerkey, keyval)
40
- in self._store.items()
41
- )
37
+ return ((lowerkey, keyval[1]) for (lowerkey, keyval) in self._store.items())
42
38
 
43
39
  def __eq__(self, other):
44
40
  if isinstance(other, Mapping):
@@ -1,39 +1,45 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: http-message-signatures
3
- Version: 0.4.4
3
+ Version: 0.6.1
4
4
  Summary: An implementation of the IETF HTTP Message Signatures draft standard
5
- Home-page: https://github.com/pyauth/http-message-signatures
5
+ Project-URL: Homepage, https://github.com/pyauth/http-message-signatures
6
6
  Author: Andrey Kislyuk
7
7
  Author-email: kislyuk@gmail.com
8
+ Maintainer: Andrey Kislyuk
9
+ Maintainer-email: kislyuk@gmail.com
8
10
  License: Apache Software License
9
- Platform: MacOS X
10
- Platform: Posix
11
+ License-File: LICENSE
12
+ License-File: NOTICE
11
13
  Classifier: Intended Audience :: Developers
12
14
  Classifier: License :: OSI Approved :: Apache Software License
13
15
  Classifier: Operating System :: MacOS :: MacOS X
14
16
  Classifier: Operating System :: POSIX
15
17
  Classifier: Programming Language :: Python
16
- Classifier: Programming Language :: Python :: 3.7
17
18
  Classifier: Programming Language :: Python :: 3.8
18
19
  Classifier: Programming Language :: Python :: 3.9
19
20
  Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
20
24
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
- License-File: LICENSE
22
- Requires-Dist: http-sfv (>=0.9.3)
23
- Requires-Dist: cryptography (>=36.0.2)
25
+ Requires-Python: >=3.8
26
+ Requires-Dist: cryptography>=36.0.2
27
+ Requires-Dist: http-sfv>=0.9.3
24
28
  Provides-Extra: tests
25
- Requires-Dist: flake8 ; extra == 'tests'
26
- Requires-Dist: coverage ; extra == 'tests'
27
- Requires-Dist: build ; extra == 'tests'
28
- Requires-Dist: wheel ; extra == 'tests'
29
- Requires-Dist: mypy ; extra == 'tests'
30
- Requires-Dist: requests ; extra == 'tests'
31
-
32
- http-message-signatures: An implementation of the IETF HTTP Message Signatures draft standard
33
- =============================================================================================
29
+ Requires-Dist: build; extra == 'tests'
30
+ Requires-Dist: coverage; extra == 'tests'
31
+ Requires-Dist: flake8; extra == 'tests'
32
+ Requires-Dist: mypy; extra == 'tests'
33
+ Requires-Dist: requests; extra == 'tests'
34
+ Requires-Dist: ruff; extra == 'tests'
35
+ Requires-Dist: wheel; extra == 'tests'
36
+ Description-Content-Type: text/x-rst
37
+
38
+ http-message-signatures: An implementation of RFC 9421, the IETF HTTP Message Signatures standard
39
+ =================================================================================================
34
40
 
35
41
  *http-message-signatures* is an implementation of the IETF
36
- `HTTP Message Signatures <https://datatracker.ietf.org/doc/draft-ietf-httpbis-message-signatures>`_ draft standard in
42
+ `RFC 9421 HTTP Message Signatures <https://datatracker.ietf.org/doc/rfc9421/>`_ standard in
37
43
  Python.
38
44
 
39
45
  Installation
@@ -84,9 +90,9 @@ builds upon this package to provide integrated signing and validation of the req
84
90
  In http-message-signatures, you can ensure that the information signed is what you expect to be signed by only trusting the
85
91
  data returned by the ``verify()`` method::
86
92
 
87
- verify_result = verifier.verify(request)
93
+ verify_results = verifier.verify(request)
88
94
 
89
- This returns VerifyResult, a namedtuple with the following attributes:
95
+ This returns a list of ``VerifyResult`` s, which are ``namedtuple`` s with the following attributes:
90
96
 
91
97
  * label (str): The label for the signature
92
98
  * algorithm: (same as signature_algorithm above)
@@ -95,9 +101,17 @@ builds upon this package to provide integrated signing and validation of the req
95
101
  * body: Always ``None`` (the `requests-http-signature <https://github.com/pyauth/requests-http-signature>`_ package
96
102
  implements returning the body upon successful digest validation).
97
103
 
104
+ Given an HTTP request can potentially have multiple signatures the ``verify()`` method returns a list of ``VerifyResult`` s.
105
+ However, the implementation currently supports just one signature, so the returned list currently contains just one element.
106
+ If more signatures are found in the request then ``InvalidSignature`` is raised.
107
+
108
+ Additionally, the ``verify()`` method raises ``HTTPMessageSignaturesException`` or an exception derived from this class in
109
+ case an error occurs (unable to load PEM key, unsupported algorithm specified in signature input, signature doesn't match
110
+ digest etc.)
111
+
98
112
  Authors
99
113
  -------
100
- * Andrey Kislyuk
114
+ * `Andrey Kislyuk <https://kislyuk.com>`
101
115
 
102
116
  Links
103
117
  -----
@@ -105,7 +119,7 @@ Links
105
119
  * `Documentation <https://FIXME>`_
106
120
  * `Package distribution (PyPI) <https://pypi.python.org/pypi/http-message-signatures>`_
107
121
  * `Change log <https://github.com/pyauth/http-message-signatures/blob/master/Changes.rst>`_
108
- * `IETF HTTP Message Signatures standard tracker <https://datatracker.ietf.org/doc/draft-ietf-httpbis-message-signatures/>`_
122
+ * `IETF HTTP Message Signatures standard tracker <https://datatracker.ietf.org/doc/rfc9421/>`_
109
123
  * `OWASP Top Ten <https://owasp.org/www-project-top-ten/>`_
110
124
 
111
125
  Bugs
@@ -114,4 +128,7 @@ Please report bugs, issues, feature requests, etc. on `GitHub <https://github.co
114
128
 
115
129
  License
116
130
  -------
117
- Licensed under the terms of the `Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`_.
131
+ Copyright 2017-2024, Andrey Kislyuk and http-message-signatures contributors. Licensed under the terms of the
132
+ `Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`_. Distribution of attribution information,
133
+ LICENSE and NOTICE files with source copies of this package and derivative works is **REQUIRED** as specified by the
134
+ Apache License.
@@ -0,0 +1,13 @@
1
+ http_message_signatures/__init__.py,sha256=uGQgs5h8d16QPBbquDHzgD0SC1vF-Y8vXFWQtDHw3PE,439
2
+ http_message_signatures/_algorithms.py,sha256=XW1yajZqG8XmL_SaoWSp_ya-yfENCBt7A3F02Yf3ZXg,6468
3
+ http_message_signatures/algorithms.py,sha256=CXHOcleb8dkdTSUxTdNfl-d0XkVxSXGmf9ugKe_xGaY,190
4
+ http_message_signatures/exceptions.py,sha256=kEF1-8-ACSQL97vfIo_bwv-Hh8pdtjXjRDbsrFKlgA4,260
5
+ http_message_signatures/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ http_message_signatures/resolvers.py,sha256=h-kdnS1Ie3Xv5z22GrE_HkAHHONJ66W3kkEbReGLGLE,3260
7
+ http_message_signatures/signatures.py,sha256=BXFGNYcq4zPDkmfZ7WSKT-MhxMZB3acpiapJEzX-zTg,9286
8
+ http_message_signatures/structures.py,sha256=xCz9W4Rmjj541GgGdjZeKNObxLFqN8mdZFrsOg9g9Yc,1575
9
+ http_message_signatures-0.6.1.dist-info/METADATA,sha256=L7g_TK27F6mzY9A3KokxKIERXS15sPLFL3BK6H4GLY8,6293
10
+ http_message_signatures-0.6.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
11
+ http_message_signatures-0.6.1.dist-info/licenses/LICENSE,sha256=h-3wDrOtt7Mou9MC2Hz07aB0PwvDbGAYnVLAXlFqBAI,9144
12
+ http_message_signatures-0.6.1.dist-info/licenses/NOTICE,sha256=uffnI3KUzenxf-zvcOBEIbaShnRk1fMnvgSzdy1C2M0,634
13
+ http_message_signatures-0.6.1.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -165,27 +165,3 @@ incurred by, or claims asserted against, such Contributor by reason of your
165
165
  accepting any such warranty or additional liability.
166
166
 
167
167
  END OF TERMS AND CONDITIONS
168
-
169
- APPENDIX: How to apply the Apache License to your work
170
-
171
- To apply the Apache License to your work, attach the following boilerplate
172
- notice, with the fields enclosed by brackets "[]" replaced with your own
173
- identifying information. (Don't include the brackets!) The text should be
174
- enclosed in the appropriate comment syntax for the file format. We also
175
- recommend that a file or class name and description of purpose be included on
176
- the same "printed page" as the copyright notice for easier identification within
177
- third-party archives.
178
-
179
- Copyright [yyyy] [name of copyright owner]
180
-
181
- Licensed under the Apache License, Version 2.0 (the "License");
182
- you may not use this file except in compliance with the License.
183
- You may obtain a copy of the License at
184
-
185
- http://www.apache.org/licenses/LICENSE-2.0
186
-
187
- Unless required by applicable law or agreed to in writing, software
188
- distributed under the License is distributed on an "AS IS" BASIS,
189
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190
- See the License for the specific language governing permissions and
191
- limitations under the License.
@@ -0,0 +1,10 @@
1
+ http-message-signatures is a free open source implementation of the
2
+ IETF HTTP Message Signatures standard, RFC 9421. This project is
3
+ staffed by volunteers. If you are using http-message-signatures in a
4
+ for-profit project, please contribute to its development and
5
+ maintenance using the "Sponsor" button on the GitHub project page,
6
+ https://github.com/pyauth/http-message-signatures. If you are looking
7
+ for support with commercial applications based on
8
+ http-message-signatures, please donate and contact its developers
9
+ using the issue tracker on the http-message-signatures project page or
10
+ the contact information listed in README.rst.
@@ -1,5 +0,0 @@
1
- # coding: utf-8
2
- # file generated by setuptools_scm
3
- # don't change, don't track in version control
4
- __version__ = version = '0.4.4'
5
- __version_tuple__ = version_tuple = (0, 4, 4)
@@ -1,14 +0,0 @@
1
- http_message_signatures/__init__.py,sha256=5rr1v-1D3KLtFNtdEc-XmqxBeAhSBb0LOEzF8cTHpqY,403
2
- http_message_signatures/_algorithms.py,sha256=xSjvOhHq0vKxj7pC_Li9E9cppjXahDkiwTf2c2BGZ_I,6695
3
- http_message_signatures/algorithms.py,sha256=CXHOcleb8dkdTSUxTdNfl-d0XkVxSXGmf9ugKe_xGaY,190
4
- http_message_signatures/exceptions.py,sha256=lbIJ5Z2feWFKhH2C4knI4bi0mhYB-jmi__ZV-iNIgHI,239
5
- http_message_signatures/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- http_message_signatures/resolvers.py,sha256=9FpzLWwm7kRtdN8Eo92YJnT936Y61cmHBf2bmY0w_ns,3259
7
- http_message_signatures/signatures.py,sha256=jfAGmeuAmQOlLSt-aTLN41_D9V9lo2xCSomPvLaCwno,9211
8
- http_message_signatures/structures.py,sha256=BD1JYI7SX_H80KNY7zfWFfCpNQarkbOGz3_JL0H9p2w,1621
9
- http_message_signatures/version.py,sha256=W0kYbjRAk8XX-ioVH2wF3kiQ-6mGnmLLhxzsLZbREb8,176
10
- http_message_signatures-0.4.4.dist-info/LICENSE,sha256=c7p036pSC0mkAbXSFFmoUjoUbzt1GKgz7qXvqFEwv2g,10273
11
- http_message_signatures-0.4.4.dist-info/METADATA,sha256=QGzFUEthWqx2KI25e__C1Mm-8mXIf-0Qx_cUE0tny6Y,5192
12
- http_message_signatures-0.4.4.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
13
- http_message_signatures-0.4.4.dist-info/top_level.txt,sha256=9-VThl-09OI1yQ1ejs76InY3ENi24isY60cUUZrviiw,24
14
- http_message_signatures-0.4.4.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- http_message_signatures