Skip to content

Commit 81391a0

Browse files
committed
docs for signature (de)coder functions
1 parent 4c63e5b commit 81391a0

File tree

2 files changed

+124
-13
lines changed

2 files changed

+124
-13
lines changed

src/ecdsa/keys.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,13 @@
4848
comments. The actual object stored is base64 encoded.
4949
5050
DER
51-
Distinguished Encoding Rules, the way to encode ASN.1 objects
51+
Distinguished Encoding Rules, the way to encode :term:`ASN.1` objects
5252
deterministically and uniquely into byte strings.
53+
54+
ASN.1
55+
Abstract Syntax Notation 1 is a standard description language for
56+
specifying serialisation and deserialisation of data structures in a
57+
portable and cross-platform way.
5358
"""
5459

5560
import binascii

src/ecdsa/util.py

Lines changed: 118 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import math
55
import binascii
66
from hashlib import sha256
7-
from . import der
87
from six import PY3, int2byte, b, next
8+
from . import der
99

1010
# RFC5480:
1111
# The "unrestricted" algorithm identifier is:
@@ -212,13 +212,48 @@ def sigencode_strings(r, s, order):
212212

213213

214214
def sigencode_string(r, s, order):
215+
"""
216+
Encode the signature to raw format (:term:`raw encoding`)
217+
218+
It's expected that this function will be used as a `sigencode=` parameter
219+
in :func:`ecdsa.keys.SigningKey.sign` method.
220+
221+
:param int r: first parameter of the signature
222+
:param int s: second parameter of the signature
223+
:param int order: the order of the curve over which the signature was
224+
computed
225+
226+
:return: raw encoding of ECDSA signature
227+
:rtype: bytes
228+
"""
215229
# for any given curve, the size of the signature numbers is
216230
# fixed, so just use simple concatenation
217231
r_str, s_str = sigencode_strings(r, s, order)
218232
return r_str + s_str
219233

220234

221235
def sigencode_der(r, s, order):
236+
"""
237+
Encode the signature into the ECDSA-Sig-Value structure using :term:`DER`.
238+
239+
Encodes the signature to the following :term:`ASN.1` structure::
240+
241+
Ecdsa-Sig-Value ::= SEQUENCE {
242+
r INTEGER,
243+
s INTEGER
244+
}
245+
246+
It's expected that this function will be used as a `sigencode=` parameter
247+
in :func:`ecdsa.keys.SigningKey.sign` method.
248+
249+
:param int r: first parameter of the signature
250+
:param int s: second parameter of the signature
251+
:param int order: the order of the curve over which the signature was
252+
computed
253+
254+
:return: DER encoding of ECDSA signature
255+
:rtype: bytes
256+
"""
222257
return der.encode_sequence(der.encode_integer(r), der.encode_integer(s))
223258

224259

@@ -244,44 +279,115 @@ def sigencode_der_canonize(r, s, order):
244279

245280

246281
class MalformedSignature(Exception):
282+
"""
283+
Raised by decoding functions when the signature is malformed.
284+
285+
Malformed in this context means that the relevant strings or integers
286+
do not match what a signature over provided curve would create. Either
287+
because the byte strings have incorrect lengths or because the encoded
288+
values are too large.
289+
"""
290+
247291
pass
248292

249293

250294
def sigdecode_string(signature, order):
295+
"""
296+
Decoder for :term:`raw encoding` of ECDSA signatures.
297+
298+
raw encoding is a simple concatenation of the two integers that comprise
299+
the signature, with each encoded using the same amount of bytes depending
300+
on curve size/order.
301+
302+
It's expected that this function will be used as the `sigdecode=`
303+
parameter to the :func:`ecdsa.keys.VerifyingKey.verify` method.
304+
305+
:param signature: encoded signature
306+
:type signature: bytes like object
307+
:param order: order of the curve over which the signature was computed
308+
:type order: int
309+
310+
:raises MalformedSignature: when the encoding of the signature is invalid
311+
312+
:return: tuple with decoded 'r' and 's' values of signature
313+
:rtype: tuple of ints
314+
"""
251315
l = orderlen(order)
252316
if not len(signature) == 2 * l:
253317
raise MalformedSignature(
254-
"Invalid length of signature, expected {0} bytes long, "
255-
"provided string is {1} bytes long"
256-
.format(2 * l, len(signature)))
318+
"Invalid length of signature, expected {0} bytes long, "
319+
"provided string is {1} bytes long"
320+
.format(2 * l, len(signature)))
257321
r = string_to_number_fixedlen(signature[:l], order)
258322
s = string_to_number_fixedlen(signature[l:], order)
259323
return r, s
260324

261325

262326
def sigdecode_strings(rs_strings, order):
327+
"""
328+
Decode the signature from two strings.
329+
330+
First string needs to be a big endian encoding of 'r', second needs to
331+
be a big endian encoding of the 's' parameter of an ECDSA signature.
332+
333+
It's expected that this function will be used as the `sigdecode=`
334+
parameter to the :func:`ecdsa.keys.VerifyingKey.verify` method.
335+
336+
:param list rs_strings: list of two bytes-like objects, each encoding one
337+
parameter of signature
338+
:param int order: order of the curve over which the signature was computed
339+
340+
:raises MalformedSignature: when the encoding of the signature is invalid
341+
342+
:return: tuple with decoded 'r' and 's' values of signature
343+
:rtype: tuple of ints
344+
"""
263345
if not len(rs_strings) == 2:
264346
raise MalformedSignature(
265-
"Invalid number of strings provided: {0}, expected 2"
266-
.format(len(rs_strings)))
347+
"Invalid number of strings provided: {0}, expected 2"
348+
.format(len(rs_strings)))
267349
(r_str, s_str) = rs_strings
268350
l = orderlen(order)
269351
if not len(r_str) == l:
270352
raise MalformedSignature(
271-
"Invalid length of first string ('r' parameter), "
272-
"expected {0} bytes long, provided string is {1} bytes long"
273-
.format(l, len(r_str)))
353+
"Invalid length of first string ('r' parameter), "
354+
"expected {0} bytes long, provided string is {1} bytes long"
355+
.format(l, len(r_str)))
274356
if not len(s_str) == l:
275357
raise MalformedSignature(
276-
"Invalid length of second string ('s' parameter), "
277-
"expected {0} bytes long, provided string is {1} bytes long"
278-
.format(l, len(s_str)))
358+
"Invalid length of second string ('s' parameter), "
359+
"expected {0} bytes long, provided string is {1} bytes long"
360+
.format(l, len(s_str)))
279361
r = string_to_number_fixedlen(r_str, order)
280362
s = string_to_number_fixedlen(s_str, order)
281363
return r, s
282364

283365

284366
def sigdecode_der(sig_der, order):
367+
"""
368+
Decoder for DER format of ECDSA signatures.
369+
370+
DER format of signature is one that uses the :term:`ASN.1` :term:`DER`
371+
rules to encode it as a sequence of two integers::
372+
373+
Ecdsa-Sig-Value ::= SEQUENCE {
374+
r INTEGER,
375+
s INTEGER
376+
}
377+
378+
It's expected that this function will be used as as the `sigdecode=`
379+
parameter to the :func:`ecdsa.keys.VerifyingKey.verify` method.
380+
381+
:param sig_der: encoded signature
382+
:type sig_der: bytes like object
383+
:param order: order of the curve over which the signature was computed
384+
:type order: int
385+
386+
:raises UnexpectedDER: when the encoding of signature is invalid
387+
388+
:return: tuple with decoded 'r' and 's' values of signature
389+
:rtype: tuple of ints
390+
"""
285391
# return der.encode_sequence(der.encode_integer(r), der.encode_integer(s))
286392
rs_strings, empty = der.remove_sequence(sig_der)
287393
if empty != b(""):

0 commit comments

Comments
 (0)