catacomb-python
4 years agoalgorithms.c: Add bindings for STROBE. mdw/strobe
Mark Wooding [Tue, 26 Nov 2019 22:23:10 +0000 (22:23 +0000)]
algorithms.c: Add bindings for STROBE.

4 years agot/t-algorithms.py (HashBufferTestMixin): Assemble method names dynamically.
Mark Wooding [Tue, 26 Nov 2019 22:23:50 +0000 (22:23 +0000)]
t/t-algorithms.py (HashBufferTestMixin): Assemble method names dynamically.

Not everything I want to test with this machinery calls its methods
`hashXXX'.

4 years agoSplit 'pyke/' into commit 'e5aa77d831ad8b42167f3205ee290f238003e20a'
Mark Wooding [Mon, 25 Nov 2019 18:03:03 +0000 (18:03 +0000)]
Split 'pyke/' into commit 'e5aa77d831ad8b42167f3205ee290f238003e20a'

git-subtree-dir: pyke
git-subtree-mainline: c719150915e19e1be2a5a315e5e565e1a541921f
git-subtree-split: e5aa77d831ad8b42167f3205ee290f238003e20a

* commit 'e5aa77d831ad8b42167f3205ee290f238003e20a': (102 commits)
  pyke/pyke-mLib.c: Raise `OverflowError' on out-of-range inputs.
  Port to Python 3.
  *.[ch]: Some preparatory reformatting for the Python 3 porting.
  mp.c, catacomb/__init__.py, pyke/: Fix mixed-mode arithmetic involving `float'.
  *.c: Separate string function calls according to text/binary usage.
  *.c: Introduce a new input conversion for binary strings.
  *.c: Use the new `Py_hash_t' type.
  *.c: Use `PyVarObject_HEAD_INIT' to initialize type object headers.
  *.c: Use the new `Py_TYPE' and `Py_SIZE' macros; define them if necessary.
  pyke/mapping.c, key.c: Make the mapping code more intrusive and complete.
  pyke/mapping.c: Introduce macro for unconstifying common keyword list.
  pyke/pyke.c (newtype): Explicitly clear `ht_slots'.
  *.c: Split the constant definitions into the various submodules.
  pyke/pyke.[ch]: Make type skeleton structures be read-only.
  pyke/pyke.h: Add a `MEMBER' variant with explicit member name.
  *.c: Use Python `METH_NOARGS' methods where applicable.
  *.c: Use Python's facilities for defining class and static methods.
  *.c: Make all of the type-definition tables read-only.
  pyke/pyke.c: Check conversions hidden inside `KWLIST' and `KWMETH'.
  pyke/pyke.h, key.c: Rename `INDEXERR' to `MAPERR'.
  ...

Note that history prior to a172f897f4fdd800b3f70cdfe2140205f6b2f531
(`pyke/, ...: Extract utilities into a sort-of reusable library') is
pared down from the original Catacomb/Python history, but should be
enough for useful blaming and bisection.

4 years agoalgorithms.c: Add a Keccak `set' method now there's upstream support.
Mark Wooding [Mon, 14 Oct 2019 00:01:05 +0000 (01:01 +0100)]
algorithms.c: Add a Keccak `set' method now there's upstream support.

Bump dependency on Catacomb.

4 years agomp.c: Accept arbitrary iterables as inputs to `MPCRT'.
Mark Wooding [Mon, 25 Nov 2019 13:30:44 +0000 (13:30 +0000)]
mp.c: Accept arbitrary iterables as inputs to `MPCRT'.

Both the constructor and the `solve' method.

4 years agoec.c (ecptxl_1): Accept any iterable of coordinates.
Mark Wooding [Mon, 25 Nov 2019 13:29:39 +0000 (13:29 +0000)]
ec.c (ecptxl_1): Accept any iterable of coordinates.

4 years agocatacomb.c (mexp_common): Accept an arbitrary iterable.
Mark Wooding [Mon, 25 Nov 2019 13:19:45 +0000 (13:19 +0000)]
catacomb.c (mexp_common): Accept an arbitrary iterable.

This means that any iterable producing either (BASE, EXP) pair objects
or alternating BASE/EXP pairs can be used as input to any of the
multiple-exponentiation functions.  Of course, expecting an object with
unpredictable iteration order to produce a useful sequence of BASE/EXP
pairs will probably cause disappointment, but, for example, a dictionary
mapping bases to exponents seems like a reasonable thing to maintain.

4 years agocatacomb.c, ec.c, group.c, mp.c: Count base/exponent pairs with `size_t'.
Mark Wooding [Fri, 18 Oct 2019 20:24:23 +0000 (21:24 +0100)]
catacomb.c, ec.c, group.c, mp.c: Count base/exponent pairs with `size_t'.

Admittedly, if you get even slightly close to the limits of an `int',
the calculation will take an infinite amount of time.

4 years agorand.c: Implement the `passes' property of the `DSARand' generator.
Mark Wooding [Mon, 25 Nov 2019 13:07:34 +0000 (13:07 +0000)]
rand.c: Implement the `passes' property of the `DSARand' generator.

This has always been present in the C library, but wasn't surfaced in
Python, which seems like a poor show.

4 years agorand.c: Make nonce/IV arguments to cipher-based random generators optional.
Mark Wooding [Mon, 25 Nov 2019 13:04:35 +0000 (13:04 +0000)]
rand.c: Make nonce/IV arguments to cipher-based random generators optional.

In all cases, this defaults to zero.

4 years agocatacomb/__init__.py: Rewrite `kcdsaprime' to return the correct length.
Mark Wooding [Mon, 25 Nov 2019 13:12:43 +0000 (13:12 +0000)]
catacomb/__init__.py: Rewrite `kcdsaprime' to return the correct length.

The old version wouldn't return numbers of the correct length reliably.
This new one, written to follow Catacomb's own algorithm, will.

4 years agopgen.c: Add a binding for Catacomb's `primeiter'.
Mark Wooding [Mon, 25 Nov 2019 12:57:55 +0000 (12:57 +0000)]
pgen.c: Add a binding for Catacomb's `primeiter'.

4 years agomp.c: Simplify final cleanup in `MPCRT' operations.
Mark Wooding [Mon, 25 Nov 2019 13:25:34 +0000 (13:25 +0000)]
mp.c: Simplify final cleanup in `MPCRT' operations.

4 years agomp.c: Fix overly ambitious section header.
Mark Wooding [Sun, 20 Oct 2019 15:14:18 +0000 (16:14 +0100)]
mp.c: Fix overly ambitious section header.

4 years agomp.c: Accept `0x', `0o' and `0b' prefixes on strings with explicit base.
Mark Wooding [Mon, 25 Nov 2019 12:49:34 +0000 (12:49 +0000)]
mp.c: Accept `0x', `0o' and `0b' prefixes on strings with explicit base.

Python itself does this, so it seems like a good idea.

4 years agokey.c: Make the `KeyFile' key-lookup methods behave consistently.
Mark Wooding [Mon, 25 Nov 2019 12:00:52 +0000 (12:00 +0000)]
key.c: Make the `KeyFile' key-lookup methods behave consistently.

Annoyingly, `byid' and `bytag' would raise `KERR_NOTFOUND', while
`bytype' would give you `None'.  Resolve this: add a `fail' keyword
argument to each method, which defaults to true: if `fail' is true then
a failed lookup raises `KERR_NOTFOUND'; if false, then you get `None'.

4 years agokey.c: Complain about duplicate subkeys passed to `KeyDataStructured'.
Mark Wooding [Mon, 25 Nov 2019 11:54:12 +0000 (11:54 +0000)]
key.c: Complain about duplicate subkeys passed to `KeyDataStructured'.

This wasn't previously possible (without complicated subterfuge), but
now a keyword argument can duplicate a mapping set in the positional
argument.

4 years agokey.c: Populate `KeyDataStructured' from the keywords.
Mark Wooding [Mon, 25 Nov 2019 11:51:44 +0000 (11:51 +0000)]
key.c: Populate `KeyDataStructured' from the keywords.

Process the keyword arguments as additional mappings to install in the
new object.  In particular, `subkeys' is not special any more.

4 years agokey.c: Factor out populating a `KeyDataStructured' from a mapping.
Mark Wooding [Mon, 25 Nov 2019 11:48:39 +0000 (11:48 +0000)]
key.c: Factor out populating a `KeyDataStructured' from a mapping.

Introduce a new function `populate_struct' which does the gruntwork of
iterating over a given mapping and setting the corresponding labels in a
`key_data' object.

No functional change.

4 years agokey.c: Make `KeyDataStructured' constructor cleanup less bizarre.
Mark Wooding [Mon, 25 Nov 2019 11:44:52 +0000 (11:44 +0000)]
key.c: Make `KeyDataStructured' constructor cleanup less bizarre.

Drop the reference to `kd' if it's non-null, rather than inspecting the
apparently unrelated `me'.

4 years agoalgorithms.c: Use `RETURN_ME' rather than doing the job by hand.
Mark Wooding [Sun, 24 Nov 2019 23:08:14 +0000 (23:08 +0000)]
algorithms.c: Use `RETURN_ME' rather than doing the job by hand.

4 years ago*.c: Delete some pointless refcount twiddling.
Mark Wooding [Sun, 24 Nov 2019 23:07:59 +0000 (23:07 +0000)]
*.c: Delete some pointless refcount twiddling.

4 years agoec.c, catacomb/__init__.py: Return tail from `parse'; provide `fromstring'.
Mark Wooding [Sun, 24 Nov 2019 22:50:56 +0000 (22:50 +0000)]
ec.c, catacomb/__init__.py: Return tail from `parse'; provide `fromstring'.

`ECCurve.parse' was inconsistent with the established nomenclature.
Generally, `parse' reads a prefix of some given string, returning the
denoted value and the unprocessed remainder of the input string;
`fromstring' does the same, except that it returns only the value, and
raises an exception if the remainder of the string is not only
whitespace.

Fix `ECCurve.parse' (which unfortunately is an incompatible change), and
add missing `fromstring' methods to `ECCurve' and `ECInfo'.

4 years agoec.c: Accept and discard parentheses around a point when parsing.
Mark Wooding [Sun, 24 Nov 2019 22:46:33 +0000 (22:46 +0000)]
ec.c: Accept and discard parentheses around a point when parsing.

The `str' function returns parentheses around the coordinates, so it
seems unfair to reject parentheses on input.

4 years agoec.c (ecptxl_1): Preparatory reformatting.
Mark Wooding [Sun, 24 Nov 2019 22:45:14 +0000 (22:45 +0000)]
ec.c (ecptxl_1): Preparatory reformatting.

Gentle vertical compression.

4 years agoec.c: Dispatch to `ecptxl_3' whether or not we have a curve.
Mark Wooding [Sun, 24 Nov 2019 22:42:10 +0000 (22:42 +0000)]
ec.c: Dispatch to `ecptxl_3' whether or not we have a curve.

The `ecptxl_3' function has a better error message in the case where
there is no curve.  Indeed, `want sequence of two or three items' is
downright unfair in the case where you did in fact supply a sequence of
three items, and the real problem is that you're trying to construct a
curveless point.

4 years agoec.c: Reject strings with trailing junk in the curve-point constructor.
Mark Wooding [Sun, 24 Nov 2019 21:54:44 +0000 (21:54 +0000)]
ec.c: Reject strings with trailing junk in the curve-point constructor.

4 years agoec.c: Accept field elements in the fast path from `samep' fields.
Mark Wooding [Sun, 24 Nov 2019 21:45:37 +0000 (21:45 +0000)]
ec.c: Accept field elements in the fast path from `samep' fields.

... as well as from the same field object.

4 years agocatacomb/__init__.py, mp.c: Use implicit-conversion rules for rationals.
Mark Wooding [Sun, 24 Nov 2019 00:50:18 +0000 (00:50 +0000)]
catacomb/__init__.py, mp.c: Use implicit-conversion rules for rationals.

Export the implicit conversions for `MP' and `GF' to Python, and use
them in the `BaseRat' constructor.

4 years agoec.c, field.c, group.c: Allow exponents and scalars from prime fields.
Mark Wooding [Sun, 24 Nov 2019 00:41:52 +0000 (00:41 +0000)]
ec.c, field.c, group.c: Allow exponents and scalars from prime fields.

The idea is that the unit group of a finite field, and the point group
of an elliptic curve, can usefully be viewed as modules over a suitable
integer quotient ring; and, even more so, prime-order subgroups of these
can be considered as one-dimensional vector spaces over prime-order
fields.  It's therefore helpful to allow elements of the appropriate
field as exponents or scalar multipliers as appropriate.  Unfortunately
it's annoying to check whether we have the /right/ scalar field; we
could check, but that does a lot of computation for little benefit.  So
allow any prime-field element in these positions.

I don't (currently) allow a prime-field element as the exponent in `pow'
applied to `MP' or `GF'; I'm open to representation on whether this is a
good idea.  They are permitted in the exponentiation functions attached
to the various modular-reduction classes, because the exponent operand
in those cases is subject to explicit conversion.

4 years agomp.c: Tighten up the `MP' and `GF' implicit conversions.
Mark Wooding [Sun, 24 Nov 2019 00:28:14 +0000 (00:28 +0000)]
mp.c: Tighten up the `MP' and `GF' implicit conversions.

Allow implicit conversions to `MP' from `PrimeFilter' (for old time's
sake), and anything /other than/ field elements and polynomials which
implements the `__index__' implicit conversion to integer.

Don't allow implicit conversions to `GF' at all.

4 years agomp.c: Use implicit-conversion rules in `coerce'.
Mark Wooding [Sun, 24 Nov 2019 00:24:57 +0000 (00:24 +0000)]
mp.c: Use implicit-conversion rules in `coerce'.

Coercion is only used (in `Py_TPFLAGS_CHECKTYPES' classes) in the three-
way comparison function; but that's still relevant in Python 2.

4 years agomp.c: Convert shift amounts via `index' to prevent `float' and `str'.
Mark Wooding [Sun, 24 Nov 2019 00:21:44 +0000 (00:21 +0000)]
mp.c: Convert shift amounts via `index' to prevent `float' and `str'.

It obviously makes no sense to calculate `MP(4) << "4"' or `MP(9) >>
2.8'.

4 years agoec.c, field.c, group.c, mp.c: Fix conversions in `pow' and scalar mul.
Mark Wooding [Sun, 24 Nov 2019 00:18:43 +0000 (00:18 +0000)]
ec.c, field.c, group.c, mp.c: Fix conversions in `pow' and scalar mul.

The base and modulus (if present) should belong to the base ring; the
exponent or scalar should be an integer; and we should use implicit-
conversion rules for all three.  (Of course, the modulus can also be
`None'.)

This tightening temporarily breaks a test multiplying an elliptic curve
point by a prime-field element Q n.  That used to work, but not for any
especially principled reason; and this wasn't commutative (n Q would
multiply n by the x-coordinate of Q coerced into the scalar field).  We
shall fix this soon.

4 years agofield.c: Replace `tofe' by `implicitfe', calling `implicit{mp,gf}'.
Mark Wooding [Sat, 23 Nov 2019 23:48:52 +0000 (23:48 +0000)]
field.c: Replace `tofe' by `implicitfe', calling `implicit{mp,gf}'.

If something converts to an integer, we allow converting it to a
prime-field element too; similarly, things that convert to polynomials
can convert to binary-field elements.  (Obviously, these conversions use
the canonical homomorphisms.)

4 years agopyke/pyke-mLib.c: Raise `OverflowError' on out-of-range inputs.
Mark Wooding [Sat, 23 Nov 2019 15:05:39 +0000 (15:05 +0000)]
pyke/pyke-mLib.c: Raise `OverflowError' on out-of-range inputs.

This seems to match better what Python does under these conditions.

4 years agocatacomb/__init__.py: Prepare rational classes for upcoming changes.
Mark Wooding [Sat, 23 Nov 2019 23:39:21 +0000 (23:39 +0000)]
catacomb/__init__.py: Prepare rational classes for upcoming changes.

In the near future, we won't be able to guarantee that all rings allow
implicit conversions of (integer) 0 and 1 to the additive and
multiplicative ring identities, so:

  * define `ZERO' and `ONE' class attributes on the concrete classes to
    hold the respective ring identities;

  * make the `_split_rat' function into a private method of the
    `BaseRat' class and adjust callers to match;

  * compare against `ZERO' to detect an exact element of the base ring;
    and

  * return `ONE' as the implicit denominator for a base-ring element or
    foreign object to be converted.

No functional change.

4 years agomp.c: Export `implicitmp' and `implicitgf'.
Mark Wooding [Sat, 23 Nov 2019 22:38:04 +0000 (22:38 +0000)]
mp.c: Export `implicitmp' and `implicitgf'.

The next few commits are going to be about shoring up implicit
conversions in generic arithmetic operators, and, in particular, in
forbidding obviously silly conversions, e.g., from floating-point
numbers of strings to integers or polynomials.  This is a first step
towards that.

No new callers yet, and no functional change.

4 years agoalgorithms.c: Hide the `_Poly1305Class' type a bit better.
Mark Wooding [Sun, 13 Oct 2019 23:58:57 +0000 (00:58 +0100)]
algorithms.c: Hide the `_Poly1305Class' type a bit better.

4 years agopyke/pyke-mLib.c: Raise `OverflowError' on out-of-range inputs.
Mark Wooding [Sat, 23 Nov 2019 15:05:39 +0000 (15:05 +0000)]
pyke/pyke-mLib.c: Raise `OverflowError' on out-of-range inputs.

This seems to match better what Python does under these conditions.

4 years agoalgorithms.c (FOO.hashbufN): Consistently raise `ValueError' if too big.
Mark Wooding [Sun, 13 Oct 2019 23:53:56 +0000 (00:53 +0100)]
algorithms.c (FOO.hashbufN): Consistently raise `ValueError' if too big.

4 years agoalgorithms.c: Implement KMAC in C.
Mark Wooding [Mon, 14 Oct 2019 15:27:51 +0000 (16:27 +0100)]
algorithms.c: Implement KMAC in C.

It's longer this way, but significantly less ugly, and it works
consistently with the other algorithms.

4 years agoalgorithms.c: Set `hashsz', `tagsz', and `name' properties on MAC keys.
Mark Wooding [Sun, 13 Oct 2019 23:56:07 +0000 (00:56 +0100)]
algorithms.c: Set `hashsz', `tagsz', and `name' properties on MAC keys.

The generic MAC objects, and Poly1305.

4 years agoalgorithms.c (KeySZSet): Represent the set as an actual (frozen) set.
Mark Wooding [Sun, 13 Oct 2019 23:52:23 +0000 (00:52 +0100)]
algorithms.c (KeySZSet): Represent the set as an actual (frozen) set.

4 years agoalgorithms.c: Set `KSZ.max' to `None' to indicate no bound.
Mark Wooding [Sun, 13 Oct 2019 23:50:51 +0000 (00:50 +0100)]
algorithms.c: Set `KSZ.max' to `None' to indicate no bound.

4 years agoalgorithms.c (ShakeNN.done): Offer a (sensible) default hash size.
Mark Wooding [Mon, 14 Oct 2019 00:03:25 +0000 (01:03 +0100)]
algorithms.c (ShakeNN.done): Offer a (sensible) default hash size.

4 years agoalgorithms.c (ShakeNN constructor): Support `None' for func/perso args.
Mark Wooding [Mon, 14 Oct 2019 00:01:33 +0000 (01:01 +0100)]
algorithms.c (ShakeNN constructor): Support `None' for func/perso args.

4 years agobuffer.c: Implement `ec2osp' and `os2ecp' as operations on buffers.
Mark Wooding [Sat, 23 Nov 2019 14:26:34 +0000 (14:26 +0000)]
buffer.c: Implement `ec2osp' and `os2ecp' as operations on buffers.

4 years agobuffer.c: Refactor `WriteBuffer.putecptraw'.
Mark Wooding [Sat, 23 Nov 2019 14:22:30 +0000 (14:22 +0000)]
buffer.c: Refactor `WriteBuffer.putecptraw'.

This will better match a function to be added soon.  No functional
change.

4 years agoPort to Python 3.
Mark Wooding [Tue, 22 Oct 2019 18:12:28 +0000 (19:12 +0100)]
Port to Python 3.

Most of this is `#ifdef ...' ... `#endif' noise, with a few tweaks
thrown in.

Some notes on specific parts of the port.

  * buffer.c: The Python 3 buffer protocol is completely different.
    Read buffers work differently, but aren't problematic; write buffers
    can now be held open for an extended period, so we need the locking
    machinery that was added recently.

  * catacomb.c: Module initialization has changed, but isn't a great
    deal more difficult.

  * catacomb/__init__.py, catacomb/pwsafe.py, pock, pwsafe: There are a
    number of places which need language-version switches, but none of
    them is especially interesting.  This diff is noisier than it should
    be because I couldn't adjust the indentation in advance.

  * mp.c: With the abolition of a separate fixnum type, `mp_frompylong'
    needed to express the fast path from a fixnum in a different way.

  * pwsafe: The hacking to alter the error-handling behaviour associated
    with the `stdout' stream is deeply unpleasant.  Sorry.

  * pyke/pyke.h: Most of the porting work happens here, with alternative
    definitions for the various macros introduced earlier.

  * .gitignore: Ignore Python 3 `__pycache__/' turds.  Python 3 leaves
    its pre-tokenized files in `__pycache__/' directories, which somehow
    manage to be much more objectionable than the loose Python 2 `*.pyc'
    files.  Ignore these.

  * debian/: Add the necessary things to build a Python 3 extension
    package.

4 years agoPort to Python 3.
Mark Wooding [Tue, 22 Oct 2019 18:12:28 +0000 (19:12 +0100)]
Port to Python 3.

Most of this is `#ifdef ...' ... `#endif' noise, with a few tweaks
thrown in.

Some notes on specific parts of the port.

  * buffer.c: The Python 3 buffer protocol is completely different.
    Read buffers work differently, but aren't problematic; write buffers
    can now be held open for an extended period, so we need the locking
    machinery that was added recently.

  * catacomb.c: Module initialization has changed, but isn't a great
    deal more difficult.

  * catacomb/__init__.py, catacomb/pwsafe.py, pock, pwsafe: There are a
    number of places which need language-version switches, but none of
    them is especially interesting.  This diff is noisier than it should
    be because I couldn't adjust the indentation in advance.

  * mp.c: With the abolition of a separate fixnum type, `mp_frompylong'
    needed to express the fast path from a fixnum in a different way.

  * pwsafe: The hacking to alter the error-handling behaviour associated
    with the `stdout' stream is deeply unpleasant.  Sorry.

  * pyke/pyke.h: Most of the porting work happens here, with alternative
    definitions for the various macros introduced earlier.

  * .gitignore: Ignore Python 3 `__pycache__/' turds.  Python 3 leaves
    its pre-tokenized files in `__pycache__/' directories, which somehow
    manage to be much more objectionable than the loose Python 2 `*.pyc'
    files.  Ignore these.

  * debian/: Add the necessary things to build a Python 3 extension
    package.

4 years ago*.[ch]: Some preparatory reformatting for the Python 3 porting.
Mark Wooding [Tue, 22 Oct 2019 17:50:19 +0000 (18:50 +0100)]
*.[ch]: Some preparatory reformatting for the Python 3 porting.

Nothing very complicated or profound.  These are intended to make the
upcoming diff easier to check for stupid mistakes.  A lot of this is
whitespace change that disappears in `git show -w'.

4 years ago*.[ch]: Some preparatory reformatting for the Python 3 porting.
Mark Wooding [Tue, 22 Oct 2019 17:50:19 +0000 (18:50 +0100)]
*.[ch]: Some preparatory reformatting for the Python 3 porting.

Nothing very complicated or profound.  These are intended to make the
upcoming diff easier to check for stupid mistakes.  A lot of this is
whitespace change that disappears in `git show -w'.

4 years agomp.c, catacomb/__init__.py, pyke/: Fix mixed-mode arithmetic involving `float'.
Mark Wooding [Tue, 22 Oct 2019 17:31:57 +0000 (18:31 +0100)]
mp.c, catacomb/__init__.py, pyke/: Fix mixed-mode arithmetic involving `float'.

This is a bit embarrassing.

>>> import catacomb as C
>>> x = C.MP(5)
>>> x == 5.1
True
>>> x < 5.1
False
>>> r = x/2
>>> r
5/2
>>> r == 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an integer is required
>>> r == 2.5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an integer is required
>>> r*1.0
5/2
>>> r*1.1
5/2
>>> r*2.0
5
>>> r*2.5
5

Fix this nonsense.

  * Change the `obvious' arithmetic operators so that they notice that
    one of the operands is a float.  Handle this by converting to a
    Python bignum and letting Python handle the arithmetic.  The result
    is a float, which seems sensible inexact contagion.

  * Introduce a rich-comparison method which also detects a float
    operand and hands off to Python.  Python seems to get this right,
    comparing the float to the bignum in its full precision, so that's a
    win.

  * Also, modify the `IntRat' code to apply inexact contagion in the
    same way.  Comparisons may be imperfect here, but that's
    surprisingly hard to get right.

The new results:

>>> import catacomb as C
>>> x = C.MP(5)
>>> x == 5.1
False
>>> x < 5.1
True
>>> r = x/2
>>> r
5/2
>>> r == 2
False
>>> r == 2.5
True
>>> r*1.0
2.5
>>> r*1.1
2.75
>>> r*2.0
5.0
>>> r*2.5
6.25

4 years agofield.c, mp.c: Implement the `nb_index' conversion.
Mark Wooding [Mon, 18 Nov 2019 14:52:54 +0000 (14:52 +0000)]
field.c, mp.c: Implement the `nb_index' conversion.

This is Yet Another Integer Conversion added in 2.5, for the purpose of
/implicit/ conversions (since strings and other strange things will
convert explicitly to integers).

It's significant because the `bin' builtin (conversion to base-2 string,
added in 2.6) works by applying the `index' conversion rather than
having a special-purpose method like `hex' and `oct'.  (Indeed, Python 3
abolishes these methods, and `hex' and `oct' convert via `index' too.)

So add conversions somewhat judiciously.

4 years ago*.c: Separate string function calls according to text/binary usage.
Mark Wooding [Mon, 21 Oct 2019 01:38:59 +0000 (02:38 +0100)]
*.c: Separate string function calls according to text/binary usage.

Don't use the `PyString_...' functions directly.  Instead, define two
collections of macros `TEXT_...' and `BIN_...', which can be used on
text and binary strings respectively.  The two sets are slightly
different, because they've been designed to adapt to Python 3's
different interfaces.

There are no `PyString...' calls remaining outside of these macros.

4 years agorand.c: Cope with large `range' arguments.
Mark Wooding [Fri, 15 Nov 2019 18:26:57 +0000 (18:26 +0000)]
rand.c: Cope with large `range' arguments.

Python 3 will report large numbers as being `int' values, and
`PyInt_AS_LONG' will return nonsense in this case.

4 years ago*.c: Introduce a new input conversion for binary strings.
Mark Wooding [Mon, 21 Oct 2019 00:43:54 +0000 (01:43 +0100)]
*.c: Introduce a new input conversion for binary strings.

One of the major differences in Python 3 is that it firmly distinguishes
between binary and text strings: the former consist of small integers,
while the latter consist of Unicode scalars.  The Python 3 `s#'
conversion's main purpose is to accept text strings, and though it will
also accept binary strings it's not really ideal for the purpose.
Python 3 introduces a new conversion `y#' specifically for binary
strings, though this isn't quite what we want because, for some reason,
it /doesn't/ work with bufferish objects which require explicit release.

The best answer seems to be to introduce our own custom conversion for
binary strings, so we do this here, replacing all of the binary-input
argument conversions.  While we're at it, replace all of the by-steam
argument conversions using `PyObject_AsReadBuffer' too.

4 years agorand.c: Some gratuitous reformatting.
Mark Wooding [Fri, 15 Nov 2019 18:28:35 +0000 (18:28 +0000)]
rand.c: Some gratuitous reformatting.

4 years ago*.c: Use the new `Py_hash_t' type.
Mark Wooding [Sun, 20 Oct 2019 23:33:22 +0000 (00:33 +0100)]
*.c: Use the new `Py_hash_t' type.

4 years agocatacomb/__init__.py, mp.c: Remove `L' suffix from `repr' output.
Mark Wooding [Thu, 21 Nov 2019 22:44:15 +0000 (22:44 +0000)]
catacomb/__init__.py, mp.c: Remove `L' suffix from `repr' output.

Python 3 doesn't produce an `L', and it doesn't really help anything.

4 years ago*.c: Use `PyVarObject_HEAD_INIT' to initialize type object headers.
Mark Wooding [Sun, 20 Oct 2019 23:14:01 +0000 (00:14 +0100)]
*.c: Use `PyVarObject_HEAD_INIT' to initialize type object headers.

Define a suitable version if the Python headers don't do it for us.

4 years agomp.c, catacomb/__init__.py, pyke/: Fix mixed-mode arithmetic involving `float'.
Mark Wooding [Tue, 22 Oct 2019 17:31:57 +0000 (18:31 +0100)]
mp.c, catacomb/__init__.py, pyke/: Fix mixed-mode arithmetic involving `float'.

This is a bit embarrassing.

>>> import catacomb as C
>>> x = C.MP(5)
>>> x == 5.1
True
>>> x < 5.1
False
>>> r = x/2
>>> r
5/2
>>> r == 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an integer is required
>>> r == 2.5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an integer is required
>>> r*1.0
5/2
>>> r*1.1
5/2
>>> r*2.0
5
>>> r*2.5
5

Fix this nonsense.

  * Change the `obvious' arithmetic operators so that they notice that
    one of the operands is a float.  Handle this by converting to a
    Python bignum and letting Python handle the arithmetic.  The result
    is a float, which seems sensible inexact contagion.

  * Introduce a rich-comparison method which also detects a float
    operand and hands off to Python.  Python seems to get this right,
    comparing the float to the bignum in its full precision, so that's a
    win.

  * Also, modify the `IntRat' code to apply inexact contagion in the
    same way.  Comparisons may be imperfect here, but that's
    surprisingly hard to get right.

The new results:

>>> import catacomb as C
>>> x = C.MP(5)
>>> x == 5.1
False
>>> x < 5.1
True
>>> r = x/2
>>> r
5/2
>>> r == 2
False
>>> r == 2.5
True
>>> r*1.0
2.5
>>> r*1.1
2.75
>>> r*2.0
5.0
>>> r*2.5
6.25

4 years ago*.c: Use the new `Py_TYPE' and `Py_SIZE' macros; define them if necessary.
Mark Wooding [Sun, 20 Oct 2019 23:19:44 +0000 (00:19 +0100)]
*.c: Use the new `Py_TYPE' and `Py_SIZE' macros; define them if necessary.

Python 2.6 introduced macros to access object header fields, which is
handy because Python 3 changes the way object headers are
structured.  (I think the binary layout is unchanged, but the C-level
structuring is definitely different.)

This is the start of Python 3 porting work.

4 years agoec.c, field.c: Remove redundant `FOO_pyrichcompare' methods.
Mark Wooding [Tue, 22 Oct 2019 16:53:44 +0000 (17:53 +0100)]
ec.c, field.c: Remove redundant `FOO_pyrichcompare' methods.

The abstract base classes already have the necessary comparison methods,
so there's nothing to be gained by repeating the same methods on
subclasses.  (Indeed, Python might pointlessly allocate more memory for
the corresponding Python-level descriptors, but I haven't checked.)  But
there is something to be lost: Python 3 explicitly clobbers the
`__hash__' methods of subclasses which declare new equality methods.  We
could add duplicates of the hash methods throughout the subclass graph,
but it seems better to delete the pointless equality methods which are
causing the problem.

4 years agopyke/mapping.c, key.c: Make the mapping code more intrusive and complete.
Mark Wooding [Mon, 18 Nov 2019 10:41:12 +0000 (10:41 +0000)]
pyke/mapping.c, key.c: Make the mapping code more intrusive and complete.

Previously, mapping classes would implement a minimum of Python-level
operations, such as iterating over keys and mapping lookups, and the
generic mapping code would just synthesize missing operations in terms
of these.

Instead, introduce a mapping-specific vtable pointer in object
structures which describes the mapping operations in a form similar to
mLib's `sym' interface, which is rather more efficient in terms of hash
probes, and have the generic mapping code synthesize all of the Python-
level operations from these.

Needless to say, this is very messy.  Sorry.

4 years agocatacomb/__init__.py: Implement equality and hashing for `KeyData' objects.
Mark Wooding [Mon, 25 Nov 2019 12:07:16 +0000 (12:07 +0000)]
catacomb/__init__.py: Implement equality and hashing for `KeyData' objects.

Equality is determined by value, so don't use `KeyData' objects as
hashtable keys and then mutate them.

4 years agopyke/mapping.c: Introduce macro for unconstifying common keyword list.
Mark Wooding [Sun, 20 Oct 2019 21:57:54 +0000 (22:57 +0100)]
pyke/mapping.c: Introduce macro for unconstifying common keyword list.

4 years agokey.c: Add hashing and comparison for `Key' objects.
Mark Wooding [Mon, 28 Oct 2019 10:49:55 +0000 (10:49 +0000)]
key.c: Add hashing and comparison for `Key' objects.

4 years agopyke/pyke.c (newtype): Explicitly clear `ht_slots'.
Mark Wooding [Tue, 22 Oct 2019 17:53:50 +0000 (18:53 +0100)]
pyke/pyke.c (newtype): Explicitly clear `ht_slots'.

This makes things go very badly wrong in Python 3.  I'm not sure why it
doesn't go wrong in Python 2...

4 years agokey.c, catacomb/__init__.py: Split key file I/O into Python and C pieces.
Mark Wooding [Tue, 22 Oct 2019 11:35:40 +0000 (12:35 +0100)]
key.c, catacomb/__init__.py: Split key file I/O into Python and C pieces.

The new Catacomb `key_mergeline' and `key_extractline' functions were
specifically added to interface with language-specific I/O systems which
couldn't easily present as a `FILE *'.  Expose these new functions, and
implement the old file-oriented methods in terms of the new bindings.

4 years ago*.c: Split the constant definitions into the various submodules.
Mark Wooding [Sun, 20 Oct 2019 22:18:09 +0000 (23:18 +0100)]
*.c: Split the constant definitions into the various submodules.

4 years agokey.c: Make `None' be the default report-function designator.
Mark Wooding [Tue, 22 Oct 2019 11:34:48 +0000 (12:34 +0100)]
key.c: Make `None' be the default report-function designator.

Now we can pass it in from Python as an explicit argument.

4 years agopyke/pyke.[ch]: Make type skeleton structures be read-only.
Mark Wooding [Sun, 20 Oct 2019 20:18:08 +0000 (21:18 +0100)]
pyke/pyke.[ch]: Make type skeleton structures be read-only.

We couldn't do this before because `INITTYPE_META' would write the
direct superclass to the `tp_base' slot in the skeleton before calling
`inittype'.  To make this work, then, we adjust `inittype' to take the
direct superclass as an extra argument and plug it into the newly
created heap-type; and `INITTYPE_META' needs adjusting to pass this
argument rather than trying to write to the skeleton directly.

Of course, then we need to actually mark the type skeletons as `const'.

4 years agobuffer.c: Publish the internal structure of buffer objects.
Mark Wooding [Mon, 21 Oct 2019 11:01:48 +0000 (12:01 +0100)]
buffer.c: Publish the internal structure of buffer objects.

4 years agopyke/pyke.h: Add a `MEMBER' variant with explicit member name.
Mark Wooding [Sun, 20 Oct 2019 11:43:40 +0000 (12:43 +0100)]
pyke/pyke.h: Add a `MEMBER' variant with explicit member name.

4 years agobuffer.c: Add a lock count which pins a write-buffer's backing store.
Mark Wooding [Tue, 22 Oct 2019 16:14:46 +0000 (17:14 +0100)]
buffer.c: Add a lock count which pins a write-buffer's backing store.

Python 3's buffer protocol allows a long-term acquisition of a buffer's
backing-store address.  It would be Bad if one of our `WriteBuffer'
objects were to reallocate its backing store while something still
thought it had the old address, so keep track of how many times the
buffer has been referenced in this way.

Nothing actually makes use of this machinery yet, but its time will come.

4 years ago*.c: Use Python `METH_NOARGS' methods where applicable.
Mark Wooding [Sun, 20 Oct 2019 20:00:18 +0000 (21:00 +0100)]
*.c: Use Python `METH_NOARGS' methods where applicable.

Rather than rolling our own.  We need a little extra machinery to insert
the table entries, especially for the generic mapping support, but this
still saves 95 lines of code.

The `CONVERT_CAREFULLY' macro recently added will check that we haven't
messed things up too badly.

4 years agobuffer.c: Funnel control through a common exit point.
Mark Wooding [Tue, 22 Oct 2019 10:29:09 +0000 (11:29 +0100)]
buffer.c: Funnel control through a common exit point.

I'm not going on a rampage to fix this throughout the code (yet?), but
while I'm here I might as well.

4 years ago*.c: Use Python's facilities for defining class and static methods.
Mark Wooding [Tue, 19 Nov 2019 00:19:38 +0000 (00:19 +0000)]
*.c: Use Python's facilities for defining class and static methods.

These weren't available when this library was first written, but the
workaround is rather ugly and no longer necessary.

4 years agobuffer.c: Handle curve object as `PyObject *'.
Mark Wooding [Tue, 22 Oct 2019 10:27:49 +0000 (11:27 +0100)]
buffer.c: Handle curve object as `PyObject *'.

I've not checked, but I think this is the only place where a
pre- existing curve object was handled as `PyTypeObject *'.

4 years ago*.c: Make all of the type-definition tables read-only.
Mark Wooding [Sun, 20 Oct 2019 21:46:05 +0000 (22:46 +0100)]
*.c: Make all of the type-definition tables read-only.

The hard part is a new collection of macros which strip the `const'
qualifier from the actual table definitions, after checking that they
actually have the correct type.

And then there's the slog of actually changing all of the definitions
and using the new macros.

4 years agobuffer.c: Delete pointless initialization.
Mark Wooding [Tue, 22 Oct 2019 10:27:12 +0000 (11:27 +0100)]
buffer.c: Delete pointless initialization.

The variable `cobj' will be set by `PyArg_ParseTuple' anyway.

4 years agopyke/pyke.c: Check conversions hidden inside `KWLIST' and `KWMETH'.
Mark Wooding [Sun, 20 Oct 2019 18:24:37 +0000 (19:24 +0100)]
pyke/pyke.c: Check conversions hidden inside `KWLIST' and `KWMETH'.

Introduce a new macro `CONVERT_CAREFULLY' which checks (via a rather
sleazy hack) that its operand is of the expected type before converting
it to some other type.  This is protected by an `#ifdef' guard because
I'm thinking about adding it to a version of mLib, but I want to keep
the Pyke core independent of mLib.

Use this new macro to build better versions of `KWLIST' and `KWMETH',
which have casts hidden inside them, so that we can now be certain that
the method table entries match up with the functions.  (Spoiler: they
didn't, quite, and commit 19bff42f99d41cd9b8953ff61edfe35380b54d88,
backported onto the 1.1.x branch, fixes the bug that was found by this
change.)

4 years agopock: Use floor division on integers.
Mark Wooding [Tue, 22 Oct 2019 11:18:41 +0000 (12:18 +0100)]
pock: Use floor division on integers.

Python 3 wants to give me a float here, which is obviously wrong.

4 years agopyke/pyke.h, key.c: Rename `INDEXERR' to `MAPERR'.
Mark Wooding [Sun, 20 Oct 2019 18:17:41 +0000 (19:17 +0100)]
pyke/pyke.h, key.c: Rename `INDEXERR' to `MAPERR'.

The name `INDEXERR' was pointlessly confusing, given the existing
`IXERR' which actually raises Python's `IndexError'.  It's important,
though, that `KEYERR' be reserved for Catacomb's `KeyError' exception,
which really is an error about (cryptographic) keys.  So `MAPERR' it is.

4 years agopock: Probe for the fixnum width by enquiring the largest fixnum value.
Mark Wooding [Tue, 22 Oct 2019 11:16:37 +0000 (12:16 +0100)]
pock: Probe for the fixnum width by enquiring the largest fixnum value.

Python 3 doesn't distinguish fixnums from bignums at the type level, so
this would run forever.  Instead, get (a guess at) the largest fixnum
value, and use that.

4 years agopyke/, ...: Extract utilities into a sort-of reusable library.
Mark Wooding [Sun, 20 Oct 2019 16:51:13 +0000 (17:51 +0100)]
pyke/, ...: Extract utilities into a sort-of reusable library.

This commit changes no code, but it moves a lot of it about.  Tidying up
will come later.

4 years agopock: Use `MPMul' so that we can avoid `reduce'.
Mark Wooding [Tue, 22 Oct 2019 11:14:10 +0000 (12:14 +0100)]
pock: Use `MPMul' so that we can avoid `reduce'.

For some reason, Python 3 hides `reduce' away in some library module.
Anyway, we have a very efficient mass-multiplier so we might as well use
it.

4 years agocatacomb-python.h: Delete a stray trailing `\'.
Mark Wooding [Tue, 22 Oct 2019 18:22:07 +0000 (19:22 +0100)]
catacomb-python.h: Delete a stray trailing `\'.

This doesn't actually hurt anything because of the following blank line,
but, umm, ...

4 years agopwsafe: Trim an overly-long section boundary.
Mark Wooding [Mon, 21 Oct 2019 17:03:20 +0000 (18:03 +0100)]
pwsafe: Trim an overly-long section boundary.

4 years agocatacomb-python.h: Add a macro to declare module init functions.
Mark Wooding [Sun, 20 Oct 2019 17:18:05 +0000 (18:18 +0100)]
catacomb-python.h: Add a macro to declare module init functions.

4 years agocatacomb/pwsafe.py: Use `binascii' for Base64 conversion.
Mark Wooding [Mon, 21 Oct 2019 17:26:39 +0000 (18:26 +0100)]
catacomb/pwsafe.py: Use `binascii' for Base64 conversion.

The `.encode()' and `.decode()' string methods were apparently too
convenient, so Python 3 doesn't do Base64 conversion like this.
Instead, we have to use the steam-powered `binascii'.  And, to make
things even better, encoding produces `bytes' rather than `str' because,
err, it's not really text or something?  No idea.  Stoats.

4 years agoutil.c: Replace mLib `DISCARD' with a plain `(void)' cast.
Mark Wooding [Sun, 20 Oct 2019 17:56:07 +0000 (18:56 +0100)]
util.c: Replace mLib `DISCARD' with a plain `(void)' cast.

4 years agocatacomb/pwsafe.py: Hack around the change in metaclass syntax.
Mark Wooding [Mon, 21 Oct 2019 17:17:21 +0000 (18:17 +0100)]
catacomb/pwsafe.py: Hack around the change in metaclass syntax.

Python 2 (all versions) want you to set `__metaclass__' within the class
body.  Python 3 ignores this, treating it like an ordinary class
attribute, and wants you to say `metaclass = ...' in the direct-
superclass list; but the latter is a syntax error to Python 2.

Instead, add a hack which constructs a anonymous class with the right
metaclass to use as a direct superclass.  It's awful, but it works.

4 years agoutil.c: Rewrite `addmethods' to remove dependency on <mLib/darray.h>.
Mark Wooding [Sun, 20 Oct 2019 17:03:35 +0000 (18:03 +0100)]
util.c: Rewrite `addmethods' to remove dependency on <mLib/darray.h>.

4 years agocatacomb/pwsafe.py: Mark abstract storage-backend classes as lacking `NAME'.
Mark Wooding [Mon, 21 Oct 2019 17:20:42 +0000 (18:20 +0100)]
catacomb/pwsafe.py: Mark abstract storage-backend classes as lacking `NAME'.

Previously, they'd have a name of `None'.  This will make a later hack
work better.

4 years agocatacomb.c: Use a less awful version comparison.
Mark Wooding [Sun, 20 Oct 2019 20:03:38 +0000 (21:03 +0100)]
catacomb.c: Use a less awful version comparison.

4 years agocatacomb/pwsafe.py: Hack around the difference in octal literal syntax.
Mark Wooding [Mon, 21 Oct 2019 17:06:31 +0000 (18:06 +0100)]
catacomb/pwsafe.py: Hack around the difference in octal literal syntax.

Python 2.5 wants `0DIGITS', while Python 3 insists on `0oDIGITS'.  The
latter is prettier, but the difference is annoying.  We only need these
for Unix permissions, so just set up the ones we want in advance using
an explicit conversion from strings.

4 years agocatacomb.c, util.c: Export `modname' and set it in main entry point.
Mark Wooding [Sun, 20 Oct 2019 16:57:11 +0000 (17:57 +0100)]
catacomb.c, util.c: Export `modname' and set it in main entry point.

This is preliminary work in splitting out the Catacomb-independent
utilities so that they can be used by other projects.