Merge branches 'mdw/pwsafe' and 'mdw/ec-ptcmpr'
authorMark Wooding <mdw@distorted.org.uk>
Mon, 20 Jul 2015 13:40:18 +0000 (14:40 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 20 Jul 2015 13:40:18 +0000 (14:40 +0100)
* mdw/pwsafe:
  pwsafe: New command `xfer' to transfer data to a new database backend.
  catacomb/pwsafe.py: Add a backend based on SQLite.
  catacomb/pwsafe.py, pwsafe: Make GDBM support conditional.
  catacomb/pwsafe.py: New Git-friendly `DirectoryStorageBackend'.
  catacomb/pwsafe.py: New FlatFileStorageBackend class.
  catacomb/pwsafe.py: Add a new ABRUPTP argument to `close' methods.
  catacomb/pwsafe.py, pwsafe: Dispatching for multiple backends.
  catacomb/pwsafe.py: Split out the GDBM-specifics from StorageBackend.
  catacomb/pwsafe.py: Factor database handling out into a StorageBackend.
  catacomb/pwsafe.py: Commentary fix.
  pwsafe: Abolish the `chomp' function, and only chomp when reading stdin.
  catacomb/pwsafe.py: Make `PW' be a context manager, and use it.
  pwsafe: Get the master passphrase before the new password.
  pwsafe: Report password mismatch as an error, not an exception.
  pwsafe: Some simple reformatting.
  catacomb/pwsafe.py, pwsafe: Replace `PW''s MODE parameter with WRITEP flag.
  catacomb/pwsafe.py: Abolish the `PWIter' class.
  pwsafe: Eliminate the `dump' subcommand.
  pwsafe: Present the list of commands in alphabetical order.
  pwsafe: Don't produce a backtrace on decryption failure.

* mdw/ec-ptcmpr:
  catacomb.c, ec.c: Bindings for the new EC2OSP/OS2ECP functions.

18 files changed:
algorithms.c
algorithms.py
buffer.c
bytestring.c
catacomb-python.h
catacomb.c
catacomb/__init__.py
ec.c
field.c
group.c
key.c
mp.c
passphrase.c
pgen.c
pubkey.c
rand.c
share.c
util.c

index 16d426d..4753cf0 100644 (file)
@@ -230,7 +230,7 @@ static PyMemberDef keyszset_pymembers[] = {
 
 static PyTypeObject keysz_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeySZ",                    /* @tp_name@ */
+  "KeySZ",                             /* @tp_name@ */
   sizeof(keysz_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -278,7 +278,7 @@ static PyTypeObject keysz_pytype_skel = {
 
 static PyTypeObject keyszany_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeySZAny",                 /* @tp_name@ */
+  "KeySZAny",                          /* @tp_name@ */
   sizeof(keysz_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -326,7 +326,7 @@ static PyTypeObject keyszany_pytype_skel = {
 
 static PyTypeObject keyszrange_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeySZRange",               /* @tp_name@ */
+  "KeySZRange",                                /* @tp_name@ */
   sizeof(keyszrange_pyobj),            /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -375,7 +375,7 @@ sizes, and requires the key length to be a multiple of some value.",
 
 static PyTypeObject keyszset_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeySZSet",                 /* @tp_name@ */
+  "KeySZSet",                          /* @tp_name@ */
   sizeof(keyszset_pyobj),              /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -422,6 +422,24 @@ few listed sizes.",
   0                                    /* @tp_is_gc@ */
 };
 
+#define KSZCONVOP(op)                                                  \
+  static PyObject *meth__KeySZ_##op(PyObject *me, PyObject *arg)       \
+  {                                                                    \
+    double x, y;                                                       \
+    if (!PyArg_ParseTuple(arg, "Od:" #op, &me, &x)) return (0);                \
+    y = keysz_##op(x);                                                 \
+    return (PyFloat_FromDouble(y));                                    \
+  }
+KSZCONVOP(fromdl)
+KSZCONVOP(fromschnorr)
+KSZCONVOP(fromif)
+KSZCONVOP(fromec)
+KSZCONVOP(todl)
+KSZCONVOP(toschnorr)
+KSZCONVOP(toif)
+KSZCONVOP(toec)
+#undef KSZCONVOP
+
 /*----- Symmetric encryption ----------------------------------------------*/
 
 PyTypeObject *gccipher_pytype, *gcipher_pytype;
@@ -469,7 +487,7 @@ PyObject *gccipher_pywrap(gccipher *cc)
   g->ty.ht_type.tp_alloc = PyType_GenericAlloc;
   g->ty.ht_type.tp_free = 0;
   g->ty.ht_type.tp_new = gcipher_pynew;
-  PyType_Ready(&g->ty.ht_type);
+  typeready(&g->ty.ht_type);
   return ((PyObject *)g);
 }
 
@@ -589,7 +607,7 @@ static PyMethodDef gcipher_pymethods[] = {
 
 static PyTypeObject gccipher_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GCCipher",                 /* @tp_name@ */
+  "GCCipher",                          /* @tp_name@ */
   sizeof(gccipher_pyobj),              /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -637,7 +655,7 @@ static PyTypeObject gccipher_pytype_skel = {
 
 static PyTypeObject gcipher_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GCipher",                  /* @tp_name@ */
+  "GCipher",                           /* @tp_name@ */
   sizeof(gcipher_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -713,7 +731,7 @@ PyObject *gchash_pywrap(gchash *ch)
   g->ty.ht_type.tp_alloc = PyType_GenericAlloc;
   g->ty.ht_type.tp_free = 0;
   g->ty.ht_type.tp_new = ghash_pynew;
-  PyType_Ready(&g->ty.ht_type);
+  typeready(&g->ty.ht_type);
   return ((PyObject *)g);
 }
 
@@ -824,7 +842,7 @@ static PyMethodDef ghash_pymethods[] = {
 
 static PyTypeObject gchash_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GCHash",                   /* @tp_name@ */
+  "GCHash",                            /* @tp_name@ */
   sizeof(gchash_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -872,7 +890,7 @@ static PyTypeObject gchash_pytype_skel = {
 
 static PyTypeObject ghash_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GHash",                    /* @tp_name@ */
+  "GHash",                             /* @tp_name@ */
   sizeof(ghash_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -968,7 +986,7 @@ PyObject *gcmac_pywrap(gcmac *cm)
   g->ty.ht_type.tp_alloc = PyType_GenericAlloc;
   g->ty.ht_type.tp_free = 0;
   g->ty.ht_type.tp_new = gmac_pynew;
-  PyType_Ready(&g->ty.ht_type);
+  typeready(&g->ty.ht_type);
   return ((PyObject *)g);
 }
 
@@ -988,7 +1006,7 @@ PyObject *gmac_pywrap(PyObject *cobj, gmac *m, unsigned f)
   g->ty.ht_type.tp_alloc = PyType_GenericAlloc;
   g->ty.ht_type.tp_free = 0;
   g->ty.ht_type.tp_new = gmhash_pynew;
-  PyType_Ready(&g->ty.ht_type);
+  typeready(&g->ty.ht_type);
   g->m = m;
   g->f = f;
   return ((PyObject *)g);
@@ -1022,7 +1040,7 @@ static PyGetSetDef gcmac_pygetset[] = {
 
 static PyTypeObject gcmac_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GCMAC",                    /* @tp_name@ */
+  "GCMAC",                             /* @tp_name@ */
   sizeof(gchash_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1070,7 +1088,7 @@ static PyTypeObject gcmac_pytype_skel = {
 
 static PyTypeObject gmac_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GMAC",                     /* @tp_name@ */
+  "GMAC",                              /* @tp_name@ */
   sizeof(gmac_pyobj),                  /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1118,7 +1136,7 @@ static PyTypeObject gmac_pytype_skel = {
 
 static PyTypeObject gmhash_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GMACHash",                 /* @tp_name@ */
+  "GMACHash",                          /* @tp_name@ */
   sizeof(ghash_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1257,7 +1275,7 @@ static PyObject *gcprp_pywrap(const prpinfo *prp)
   g->ty.ht_type.tp_alloc = PyType_GenericAlloc;
   g->ty.ht_type.tp_free = 0;
   g->ty.ht_type.tp_new = gprp_pynew;
-  PyType_Ready(&g->ty.ht_type);
+  typeready(&g->ty.ht_type);
   return ((PyObject *)g);
 }
 
@@ -1315,7 +1333,7 @@ static PyMethodDef gprp_pymethods[] = {
 
 static PyTypeObject gcprp_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GCPRP",                    /* @tp_name@ */
+  "GCPRP",                             /* @tp_name@ */
   sizeof(gcprp_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1363,7 +1381,7 @@ static PyTypeObject gcprp_pytype_skel = {
 
 static PyTypeObject gprp_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GPRP",                     /* @tp_name@ */
+  "GPRP",                              /* @tp_name@ */
   sizeof(gprp_pyobj),                  /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1411,6 +1429,28 @@ static PyTypeObject gprp_pytype_skel = {
 
 /*----- Main code ---------------------------------------------------------*/
 
+static PyMethodDef methods[] = {
+#define METHNAME(func) meth_##func
+  METH (_KeySZ_fromdl,         "\
+fromdl(N) -> M: convert integer discrete log field size to work factor")
+  METH (_KeySZ_fromschnorr,    "\
+fromschnorr(N) -> M: convert Schnorr group order to work factor")
+  METH (_KeySZ_fromif,         "\
+fromif(N) -> M: convert integer factorization problem size to work factor")
+  METH (_KeySZ_fromec,         "\
+fromec(N) -> M: convert elliptic curve group order to work factor")
+  METH (_KeySZ_todl,           "\
+todl(N) -> M: convert work factor to integer discrete log field size")
+  METH (_KeySZ_toschnorr,      "\
+toschnorr(N) -> M: convert work factor to Schnorr group order")
+  METH (_KeySZ_toif,           "\
+toif(N) -> M: convert work factor to integer factorization problem size")
+  METH (_KeySZ_toec,           "\
+toec(N) -> M: convert work factor to elliptic curve group order")
+#undef METHNAME
+  { 0 }
+};
+
 void algorithms_pyinit(void)
 {
   INITTYPE(keysz, root);
@@ -1426,6 +1466,7 @@ void algorithms_pyinit(void)
   INITTYPE(gmhash, ghash);
   INITTYPE(gcprp, type);
   INITTYPE(gprp, root);
+  addmethods(methods);
 }
 
 GEN(gcciphers, cipher)
index 3aae0f0..3ceb207 100644 (file)
@@ -29,6 +29,11 @@ ecb cbc cfb ofb counter
 streamciphers = '''
 rc4 seal
 '''.split()
+latindances = '''
+salsa20 salsa20/12 salsa20/8 xsalsa20 xsalsa20/12 xsalsa20/8
+chacha20 chacha12 chacha8 xchacha20 xchacha12 xchacha8
+'''.split()
+streamciphers += map(lambda s: s.translate(None, '/'), latindances)
 hashes = '''
 md2 md4 md5 tiger has160
 sha sha224 sha256 sha384 sha512
@@ -57,23 +62,31 @@ print
 
 print '#define PRPS(_) \\'
 for i in prps:
-  print '  _(%s, %s) \\' % (i.upper(), i)
-print '         /* end */'
-print
-
-print '#define RNGF_INT 1u'
+  print '\t_(%s, %s) \\' % (i.upper(), i)
+print '\t/* end */'
 print
 
 print '#define RNGS(_) \\'
 for i in (cross(prps, ['ofb', 'counter'])):
-  print ('  _("%(prim)s-%(mode)s", %(prim)s_keysz, ' +
-        '%(prim)s_%(mode)srand, 0) \\') % \
-        {'prim': i[0], 'mode': i[1]}
+  print ('\t_("%(prim)s-%(mode)s", %(prim)s_keysz, ' +
+         '%(prim)s_%(mode)srand, 0, 0) \\') % \
+         {'prim': i[0], 'mode': i[1]}
 for i in (cross(hashes, 'mgf')):
-  print ('  _("%(prim)s-%(mode)s", %(prim)s_%(mode)skeysz, ' +
-        '%(prim)s_%(mode)srand, 0) \\') % \
-        {'prim': i[0], 'mode': i[1]}
-print '         _("rc4", rc4_keysz, rc4_rand, 0) \\'
-print '         _("seal", seal_keysz, seal_rand, RNGF_INT) \\'
-print '         /* end */'
+  print ('\t_("%(prim)s-%(mode)s", %(prim)s_%(mode)skeysz, ' +
+         '%(prim)s_%(mode)srand, 0, 0) \\') % \
+         {'prim': i[0], 'mode': i[1]}
+print '\t_("rc4", rc4_keysz, rc4_rand, 0, 0) \\'
+print '\t_("seal", seal_keysz, seal_rand, RNGF_INT, 0) \\'
+for i in latindances:
+  for r in ['salsa20', 'xsalsa20', 'chacha', 'xchacha']:
+    if i.startswith(r):
+      root = r
+      break
+  else:
+    raise ValueError, 'failed to find root name for %s' % i
+  print ('\t_("%(name)s", %(root)s_keysz, %(id)s_rand, ' +
+         'RNGF_NONCE, %(ROOT)s_NONCESZ) \\') % \
+      {'name': i, 'id': i.translate(None, '/'),
+       'root': root, 'ROOT': root.upper()}
+print '\t/* end */'
 print
index ea38e65..507e6b8 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -285,7 +285,7 @@ static PyBufferProcs rbuf_pybuffer = {
 
 static PyTypeObject rbuf_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ReadBuffer",               /* @tp_name@ */
+  "ReadBuffer",                                /* @tp_name@ */
   sizeof(buf_pyobj),                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -518,7 +518,7 @@ static PyBufferProcs wbuf_pybuffer = {
 
 static PyTypeObject wbuf_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.WriteBuffer",              /* @tp_name@ */
+  "WriteBuffer",                       /* @tp_name@ */
   sizeof(buf_pyobj),                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
index 6b45d24..99c114c 100644 (file)
@@ -130,7 +130,7 @@ static PyBufferProcs bytestring_pybuffer;
 
 static PyTypeObject bytestring_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ByteString",               /* @tp_name@ */
+  "ByteString",                                /* @tp_name@ */
   0,                                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
index a384097..b287450 100644 (file)
@@ -44,6 +44,7 @@
 #include <mLib/dstr.h>
 #include <mLib/macros.h>
 #include <mLib/quis.h>
+#include <mLib/unihash.h>
 
 #include <catacomb/buf.h>
 
@@ -75,6 +76,7 @@
 #include <catacomb/mpmont.h>
 #include <catacomb/mpbarrett.h>
 #include <catacomb/mpreduce.h>
+#include <catacomb/mp-fibonacci.h>
 
 #include <catacomb/pgen.h>
 #include <catacomb/pfilt.h>
 #define VALERR(str) EXCERR(PyExc_ValueError, str)
 #define TYERR(str) EXCERR(PyExc_TypeError, str)
 #define ZDIVERR(str) EXCERR(PyExc_ZeroDivisionError, str)
-#define SYNERR(str) EXCERR(PyExc_SyntaxError, str)
 #define SYSERR(str) EXCERR(PyExc_SystemError, str)
 #define NIERR(str) EXCERR(PyExc_NotImplementedError, str)
 #define INDEXERR(idx) do {                                             \
   { #name, ty, offsetof(MEMBERSTRUCT, name), f, doc },
 
 #define MODULES(_)                                                     \
+  _(util)                                                              \
   _(bytestring) _(buffer)                                              \
   _(rand) _(algorithms) _(pubkey) _(pgen)                              \
   _(mp) _(field) _(ec) _(group)                                                \
-  _(passphrase) _(share) _(key)                                                \
-  _(util)
+  _(passphrase) _(share) _(key)
 #define DOMODINIT(m) m##_pyinit();
 #define DOMODINSERT(m) m##_pyinsert(mod);
 #define INIT_MODULES do { MODULES(DOMODINIT) } while (0)
@@ -244,7 +245,8 @@ extern PyObject *getbool(int);
 extern PyObject *getulong(unsigned long);
 extern void *newtype(PyTypeObject *, const PyTypeObject *, const char *);
 
-extern PyObject * mkexc(PyObject *, PyObject *, const char *, PyMethodDef *);
+extern PyObject *mkexc(PyObject *, PyObject *, const char *, PyMethodDef *);
+extern void typeready(PyTypeObject *);
 extern PyTypeObject *inittype(PyTypeObject *);
 extern void addmethods(const PyMethodDef *);
 extern PyMethodDef *donemethods(void);
index 3aebea3..49d0f40 100644 (file)
@@ -44,6 +44,7 @@ static const struct nameval consts[] = {
   C(KF_CATMASK), C(KCAT_SYMM), C(KCAT_PRIV), C(KCAT_PUB), C(KCAT_SHARE),
   C(KF_NONSECRET),
   C(KF_BURN), C(KF_OPT),
+  C(EC_XONLY), C(EC_YBIT), C(EC_LSB), C(EC_CMPR), C(EC_EXPLY), C(EC_SORT),
 #define ENTRY(tag, val, str) C(KERR_##tag),
   KEY_ERRORS(ENTRY)
 #undef ENTRY
@@ -144,11 +145,27 @@ static PyMethodDef methods[] = {
   { 0 }
 };
 
+static void init_random(void)
+{
+#if PY_MAJOR_VERSION >= 3 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 6)
+  char *seed;
+  uint32 r;
+
+  if (!Py_HashRandomizationFlag) return;
+  seed = getenv("PYTHONHASHSEED");
+  if (!seed || strcmp(seed, "random") == 0) r = GR_WORD(&rand_global);
+  else r = strtoul(seed, 0, 0);
+  if (!r) r = 0xe011f220; /* zero doesn't work well */
+  unihash_setkey(&unihash_global, r);
+#endif
+}
+
 void init_base(void)
 {
   PyObject *mod;
   addmethods(methods);
   INIT_MODULES;
+  init_random();
   mod = Py_InitModule("catacomb._base", donemethods());
   INSERT_MODULES;
   INSERT("smallprimes", smallprimes());
index 8dac0b4..120ef11 100644 (file)
@@ -47,7 +47,7 @@ def _init():
             'DHInfo', 'BinDHInfo', 'RSAPriv', 'BBSPriv',
             'PrimeFilter', 'RabinMiller',
             'Group', 'GE',
-            'KeyData']:
+            'KeySZ', 'KeyData']:
     c = d[i]
     pre = '_' + i + '_'
     plen = len(pre)
@@ -56,9 +56,9 @@ def _init():
         setattr(c, j[plen:], classmethod(b[j]))
   for i in [gcciphers, gchashes, gcmacs, gcprps]:
     for c in i.itervalues():
-      d[c.name.replace('-', '_')] = c
+      d[c.name.replace('-', '_').translate(None, '/')] = c
   for c in gccrands.itervalues():
-    d[c.name.replace('-', '_') + 'rand'] = c
+    d[c.name.replace('-', '_').translate(None, '/') + 'rand'] = c
 _init()
 
 ## A handy function for our work: add the methods of a named class to an
@@ -99,6 +99,59 @@ bytes = ByteString.fromhex
 ###--------------------------------------------------------------------------
 ### Multiprecision integers and binary polynomials.
 
+def _split_rat(x):
+  if isinstance(x, BaseRat): return x._n, x._d
+  else: return x, 1
+class BaseRat (object):
+  """Base class implementing fields of fractions over Euclidean domains."""
+  def __new__(cls, a, b):
+    a, b = cls.RING(a), cls.RING(b)
+    q, r = divmod(a, b)
+    if r == 0: return q
+    g = b.gcd(r)
+    me = super(BaseRat, cls).__new__(cls)
+    me._n = a//g
+    me._d = b//g
+    return me
+  @property
+  def numer(me): return me._n
+  @property
+  def denom(me): return me._d
+  def __str__(me): return '%s/%s' % (me._n, me._d)
+  def __repr__(me): return '%s(%s, %s)' % (type(me).__name__, me._n, me._d)
+
+  def __add__(me, you):
+    n, d = _split_rat(you)
+    return type(me)(me._n*d + n*me._d, d*me._d)
+  __radd__ = __add__
+  def __sub__(me, you):
+    n, d = _split_rat(you)
+    return type(me)(me._n*d - n*me._d, d*me._d)
+  def __rsub__(me, you):
+    n, d = _split_rat(you)
+    return type(me)(n*me._d - me._n*d, d*me._d)
+  def __mul__(me, you):
+    n, d = _split_rat(you)
+    return type(me)(me._n*n, me._d*d)
+  def __div__(me, you):
+    n, d = _split_rat(you)
+    return type(me)(me._n*d, me._d*n)
+  def __rdiv__(me, you):
+    n, d = _split_rat(you)
+    return type(me)(me._d*n, me._n*d)
+  def __cmp__(me, you):
+    n, d = _split_rat(you)
+    return type(me)(me._n*d, n*me._d)
+  def __rcmp__(me, you):
+    n, d = _split_rat(you)
+    return cmp(n*me._d, me._n*d)
+
+class IntRat (BaseRat):
+  RING = MP
+
+class GFRat (BaseRat):
+  RING = GF
+
 class _tmp:
   def negp(x): return x < 0
   def posp(x): return x > 0
@@ -108,11 +161,8 @@ class _tmp:
   def mont(x): return MPMont(x)
   def barrett(x): return MPBarrett(x)
   def reduce(x): return MPReduce(x)
-  def factorial(x):
-    'factorial(X) -> X!'
-    if x < 0: raise ValueError, 'factorial argument must be > 0'
-    return MPMul.product(xrange(1, x + 1))
-  factorial = staticmethod(factorial)
+  def __div__(me, you): return IntRat(me, you)
+  def __rdiv__(me, you): return IntRat(you, me)
 _augment(MP, _tmp)
 
 class _tmp:
@@ -122,6 +172,8 @@ class _tmp:
   def halftrace(x, y): return x.reduce().halftrace(y)
   def modsqrt(x, y): return x.reduce().sqrt(y)
   def quadsolve(x, y): return x.reduce().quadsolve(y)
+  def __div__(me, you): return GFRat(me, you)
+  def __rdiv__(me, you): return GFRat(you, me)
 _augment(GF, _tmp)
 
 class _tmp:
@@ -141,6 +193,7 @@ _augment(Field, _tmp)
 
 class _tmp:
   def __repr__(me): return '%s(%sL)' % (type(me).__name__, me.p)
+  def __hash__(me): return 0x114401de ^ hash(me.p)
   def ec(me, a, b): return ECPrimeProjCurve(me, a, b)
 _augment(PrimeField, _tmp)
 
@@ -150,6 +203,18 @@ class _tmp:
 _augment(BinField, _tmp)
 
 class _tmp:
+  def __hash__(me): return 0x23e4701c ^ hash(me.p)
+_augment(BinPolyField, _tmp)
+
+class _tmp:
+  def __hash__(me):
+    h = 0x9a7d6240
+    h ^=   hash(me.p)
+    h ^= 2*hash(me.beta) & 0xffffffff
+    return h
+_augment(BinNormField, _tmp)
+
+class _tmp:
   def __str__(me): return str(me.value)
   def __repr__(me): return '%s(%s)' % (repr(me.field), repr(me.value))
 _augment(FE, _tmp)
@@ -169,6 +234,24 @@ class _tmp:
 _augment(ECCurve, _tmp)
 
 class _tmp:
+  def __hash__(me):
+    h = 0x6751d341
+    h ^=   hash(me.field)
+    h ^= 2*hash(me.a) ^ 0xffffffff
+    h ^= 5*hash(me.b) ^ 0xffffffff
+    return h
+_augment(ECPrimeCurve, _tmp)
+
+class _tmp:
+  def __hash__(me):
+    h = 0x2ac203c5
+    h ^=   hash(me.field)
+    h ^= 2*hash(me.a) ^ 0xffffffff
+    h ^= 5*hash(me.b) ^ 0xffffffff
+    return h
+_augment(ECBinCurve, _tmp)
+
+class _tmp:
   def __repr__(me):
     if not me: return 'ECPt()'
     return 'ECPt(%s, %s)' % (me.ix, me.iy)
@@ -181,6 +264,11 @@ class _tmp:
   def __repr__(me):
     return 'ECInfo(curve = %r, G = %r, r = %s, h = %s)' % \
            (me.curve, me.G, me.r, me.h)
+  def __hash__(me):
+    h = 0x9bedb8de
+    h ^=   hash(me.curve)
+    h ^= 2*hash(me.G) & 0xffffffff
+    return h
   def group(me):
     return ECGroup(me)
 _augment(ECInfo, _tmp)
@@ -248,6 +336,30 @@ class _tmp:
 _augment(Group, _tmp)
 
 class _tmp:
+  def __hash__(me):
+    info = me.info
+    h = 0xbce3cfe6
+    h ^=   hash(info.p)
+    h ^= 2*hash(info.r) & 0xffffffff
+    h ^= 5*hash(info.g) & 0xffffffff
+    return h
+_augment(PrimeGroup, _tmp)
+
+class _tmp:
+  def __hash__(me):
+    info = me.info
+    h = 0x80695949
+    h ^=   hash(info.p)
+    h ^= 2*hash(info.r) & 0xffffffff
+    h ^= 5*hash(info.g) & 0xffffffff
+    return h
+_augment(BinGroup, _tmp)
+
+class _tmp:
+  def __hash__(me): return 0x0ec23dab ^ hash(me.info)
+_augment(ECGroup, _tmp)
+
+class _tmp:
   def __repr__(me):
     return '%r(%r)' % (me.group, str(me))
 _augment(GE, _tmp)
diff --git a/ec.c b/ec.c
index 21aa352..9d4d6e7 100644 (file)
--- a/ec.c
+++ b/ec.c
@@ -193,16 +193,20 @@ static PyObject *ecpt_pymul(PyObject *x, PyObject *y)
 
 static long ecpt_pyhash(PyObject *me)
 {
-  long i;
+  uint32 h;
+  buf b;
   ec p = EC_INIT;
+  size_t sz = 2*ECPT_C(me)->f->noctets + 1;
+  octet *q = xmalloc(sz);
 
+  h = 0xe0fdd039 + ECPT_C(me)->f->ops->ty;
+  buf_init(&b, q, sz);
   EC_OUT(ECPT_C(me), &p, ECPT_P(me));
-  i = 0xe0fdd039; /* random perturbance */
-  if (p.x) i ^= mp_tolong(p.x);
-  if (p.y) i ^= mp_tolong(p.y);
-  if (i == -1) i = -2;
+  ec_putraw(ECPT_C(me), &b, &p);
   EC_DESTROY(&p);
-  return (i);
+  xfree(q);
+  h = unihash_hash(&unihash_global, h, BBASE(&b), BLEN(&b));
+  return (h % LONG_MAX);
 }
 
 static PyObject *ecpt_pyrichcompare(PyObject *x, PyObject *y, int op)
@@ -286,6 +290,34 @@ static PyObject *epmeth_toraw(PyObject *me, PyObject *arg)
   return (rc);
 }
 
+static PyObject *epmeth_ec2osp(PyObject *me, PyObject *arg, PyObject *kw)
+{
+  buf b;
+  PyObject *rc;
+  char *p;
+  ec_curve *c = ECPT_C(me);
+  ec pp = EC_INIT;
+  int f = EC_EXPLY;
+  int len;
+  char *kwlist[] = { "flags", 0 };
+
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "|i:ectosp", kwlist, &f))
+    return (0);
+  len = c->f->noctets * 2 + 1;
+  rc = bytestring_pywrap(0, len);
+  p = PyString_AS_STRING(rc);
+  buf_init(&b, p, len);
+  EC_OUT(c, &pp, ECPT_P(me));
+  if (ec_ec2osp(c, f, &b, &pp)) {
+    Py_DECREF(rc); rc = 0;
+    VALERR("invalid flags");
+  }
+  EC_DESTROY(&pp);
+  _PyString_Resize(&rc, BLEN(&b));
+end:
+  return (rc);
+}
+
 static PyObject *epget_curve(PyObject *me, void *hunoz)
   { RETURN_OBJ(ECPT_COBJ(me)); }
 
@@ -432,7 +464,7 @@ static int ecptxl_1(ec_curve *c, ec *p, PyObject *x)
     qd.p = q;
     qd.e = 0;
     if (!ec_ptparse(&qd, p))
-      SYNERR(qd.e);
+      VALERR(qd.e);
     goto fix;
   } else if (c && (xx = tomp(x)) != 0) {
     xx = F_IN(c->f, xx, xx);
@@ -589,7 +621,7 @@ static PyNumberMethods ecpt_pynumber = {
 
 static PyTypeObject ecpt_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ECPt",                     /* @tp_name@ */
+  "ECPt",                              /* @tp_name@ */
   sizeof(ecpt_pyobj),                  /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -652,6 +684,7 @@ static PyGetSetDef ecpt_pygetset[] = {
 static PyMethodDef ecpt_pymethods[] = {
 #define METHNAME(func) epmeth_##func
   METH (toraw,         "X.toraw() -> BIN")
+  KWMETH(ec2osp,       "X.ec2osp([flags = EC_EXPLY]) -> BIN")
   METH (dbl,           "X.dbl() -> X + X")
   METH (oncurvep,      "X.oncurvep() -> BOOL")
 #undef METHNAME
@@ -703,7 +736,7 @@ static PyNumberMethods ecptcurve_pynumber = {
 
 static PyTypeObject ecptcurve_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ECPtCurve",                        /* @tp_name@ */
+  "ECPtCurve",                         /* @tp_name@ */
   sizeof(ecpt_pyobj),                  /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -813,7 +846,31 @@ static PyObject *meth__ECPtCurve_fromraw(PyObject *me, PyObject *arg)
   buf_init(&b, p, len);
   cc = ECCURVE_C(me);
   if (ec_getraw(cc, &b, &pp))
-    SYNERR("bad point");
+    VALERR("bad point");
+  EC_IN(cc, &pp, &pp);
+  rc = Py_BuildValue("(NN)", ecpt_pywrap(me, &pp), bytestring_pywrapbuf(&b));
+end:
+  return (rc);
+}
+
+static PyObject *meth__ECPtCurve_os2ecp(PyObject *me,
+                                       PyObject *arg, PyObject *kw)
+{
+  char *p;
+  int len;
+  buf b;
+  PyObject *rc = 0;
+  ec_curve *cc;
+  int f = EC_XONLY | EC_LSB | EC_SORT | EC_EXPLY;
+  ec pp = EC_INIT;
+  char *kwlist[] = { "buf", "flags", 0 };
+
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "Os#|f:os2ecp", kwlist,
+                                  &me, &p, &len, &f))
+    return (0);
+  buf_init(&b, p, len);
+  cc = ECCURVE_C(me);
+  if (ec_os2ecp(cc, f, &b, &pp)) VALERR("bad point");
   EC_IN(cc, &pp, &pp);
   rc = Py_BuildValue("(NN)", ecpt_pywrap(me, &pp), bytestring_pywrapbuf(&b));
 end:
@@ -847,7 +904,7 @@ static PyObject *meth__ECPt_parse(PyObject *me, PyObject *arg)
   if (!PyArg_ParseTuple(arg, "Os:parse", &me, &p)) goto end;
   qd.p = p;
   qd.e = 0;
-  if (!ec_ptparse(&qd, &pp)) SYNERR(qd.e);
+  if (!ec_ptparse(&qd, &pp)) VALERR(qd.e);
   rc = Py_BuildValue("(Ns)", ecpt_pywrapout(me, &pp), qd.p);
 end:
   return (rc);
@@ -912,7 +969,7 @@ static PyObject *eccurve_dopywrap(PyTypeObject *ty,
   cobj->ty.ht_type.tp_alloc = PyType_GenericAlloc;
   cobj->ty.ht_type.tp_free = 0;
   cobj->ty.ht_type.tp_new = ecpt_pynew;
-  PyType_Ready(&cobj->ty.ht_type);
+  typeready(&cobj->ty.ht_type);
   return ((PyObject *)cobj);
 }
 
@@ -971,7 +1028,7 @@ static PyObject *meth__ECCurve_parse(PyObject *me, PyObject *arg)
   qd.p = p;
   qd.e = 0;
   if ((c = ec_curveparse(&qd)) == 0)
-    SYNERR(qd.e);
+    VALERR(qd.e);
   rc = eccurve_pywrap(0, c);
 end:
   return (rc);
@@ -1015,7 +1072,7 @@ E.mmul([(P0, N0), (P1, N1), ...]) = N0 P0 + N1 P1 + ...")
 
 static PyTypeObject eccurve_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ECCurve",                  /* @tp_name@ */
+  "ECCurve",                           /* @tp_name@ */
   sizeof(eccurve_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1069,7 +1126,7 @@ static PyObject *ecprimecurve_pynew(PyTypeObject *ty,
 
 static PyTypeObject ecprimecurve_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ECPrimeCurve",             /* @tp_name@ */
+  "ECPrimeCurve",                      /* @tp_name@ */
   sizeof(eccurve_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1123,7 +1180,7 @@ static PyObject *ecprimeprojcurve_pynew(PyTypeObject *ty,
 
 static PyTypeObject ecprimeprojcurve_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ECPrimeProjCurve",         /* @tp_name@ */
+  "ECPrimeProjCurve",                  /* @tp_name@ */
   sizeof(eccurve_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1177,7 +1234,7 @@ static PyObject *ecbincurve_pynew(PyTypeObject *ty,
 
 static PyTypeObject ecbincurve_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ECBinCurve",               /* @tp_name@ */
+  "ECBinCurve",                                /* @tp_name@ */
   sizeof(eccurve_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1231,7 +1288,7 @@ static PyObject *ecbinprojcurve_pynew(PyTypeObject *ty,
 
 static PyTypeObject ecbinprojcurve_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ECBinProjCurve",           /* @tp_name@ */
+  "ECBinProjCurve",                    /* @tp_name@ */
   sizeof(eccurve_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1351,7 +1408,7 @@ static PyObject *meth__ECInfo_parse(PyObject *me, PyObject *arg)
   qd.p = p;
   qd.e = 0;
   if (ec_infoparse(&qd, &ei))
-    SYNERR(qd.e);
+    VALERR(qd.e);
   rc = Py_BuildValue("(Ns)", ecinfo_pywrap(&ei), qd.p);
 end:
   return (rc);
@@ -1436,7 +1493,7 @@ static PyMethodDef ecinfo_pymethods[] = {
 
 static PyTypeObject ecinfo_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ECInfo",                   /* @tp_name@ */
+  "ECInfo",                            /* @tp_name@ */
   sizeof(ecinfo_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1488,6 +1545,7 @@ static PyMethodDef methods[] = {
 #define METHNAME(func) meth_##func
   METH (_ECPt_frombuf,         "frombuf(E, STR) -> (P, REST)")
   METH (_ECPtCurve_fromraw,    "fromraw(E, STR) -> (P, REST)")
+  KWMETH(_ECPtCurve_os2ecp,    "os2ecp(E, STR, [flags = ...]) -> (P, REST)")
   METH (_ECPt_parse,           "parse(E, STR) -> (P, REST)")
   METH (_ECCurve_parse,        "parse(STR) -> (E, REST)")
   METH (_ECInfo_parse,         "parse(STR) -> (I, REST)")
diff --git a/field.c b/field.c
index eafa42f..2807c1c 100644 (file)
--- a/field.c
+++ b/field.c
@@ -66,7 +66,7 @@ static PyObject *field_dopywrap(PyTypeObject *ty, field *f)
   fobj->ty.ht_type.tp_alloc = PyType_GenericAlloc;
   fobj->ty.ht_type.tp_free = 0;
   fobj->ty.ht_type.tp_new = fe_pynew;
-  PyType_Ready(&fobj->ty.ht_type);
+  typeready(&fobj->ty.ht_type);
   return ((PyObject *)fobj);
 }
 
@@ -230,11 +230,13 @@ end:
 
 static long fe_pyhash(PyObject *me)
 {
-  long i = mp_tolong(FE_X(me));
-  i ^= 0xdcf62d6c; /* random perturbance */
-  if (i == -1)
-    i = -2;
-  return (i);
+  size_t sz = FE_F(me)->noctets;
+  uint32 h = 0xe0c127ca + FE_F(me)->ops->ty;
+  octet *p = xmalloc(sz);
+  mp_storeb(FE_X(me), p, sz);
+  h = unihash_hash(&unihash_global, h, p, sz);
+  xfree(p);
+  return (h % LONG_MAX);
 }
 
 static int fe_pycoerce(PyObject **x, PyObject **y)
@@ -406,7 +408,7 @@ static PyNumberMethods fe_pynumber = {
 
 static PyTypeObject fe_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.FE",                       /* @tp_name@ */
+  "FE",                                        /* @tp_name@ */
   sizeof(fe_pyobj),                    /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -536,7 +538,7 @@ static PyMethodDef field_pymethods[] = {
 
 static PyTypeObject field_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.Field",                    /* @tp_name@ */
+  "Field",                             /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -614,7 +616,7 @@ static PyGetSetDef primefield_pygetset[] = {
 
 static PyTypeObject primefield_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.PrimeField",               /* @tp_name@ */
+  "PrimeField",                                /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -681,7 +683,7 @@ end:
 
 static PyTypeObject niceprimefield_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.NicePrimeField",           /* @tp_name@ */
+  "NicePrimeField",                    /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -741,7 +743,7 @@ static PyGetSetDef binfield_pygetset[] = {
 
 static PyTypeObject binfield_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.BinField",                 /* @tp_name@ */
+  "BinField",                          /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -814,7 +816,7 @@ static PyGetSetDef binpolyfield_pygetset[] = {
 
 static PyTypeObject binpolyfield_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.BinPolyField",             /* @tp_name@ */
+  "BinPolyField",                      /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -896,7 +898,7 @@ static PyGetSetDef binnormfield_pygetset[] = {
 
 static PyTypeObject binnormfield_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.BinNormField",             /* @tp_name@ */
+  "BinNormField",                      /* @tp_name@ */
   sizeof(field_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -956,7 +958,7 @@ static PyObject *meth__Field_parse(PyObject *me, PyObject *arg)
   qd.p = p;
   qd.e = 0;
   if ((f = field_parse(&qd)) == 0)
-    SYNERR(qd.e);
+    VALERR(qd.e);
   rc = Py_BuildValue("(Ns)", field_pywrap(f), qd.p);
 end:
   return (rc);
diff --git a/group.c b/group.c
index 1f733a0..5cc40e5 100644 (file)
--- a/group.c
+++ b/group.c
@@ -264,7 +264,7 @@ static PyObject *meth__parse(PyObject *me, PyObject *arg, PyTypeObject *ty,
   if (!PyArg_ParseTuple(arg, "Os:parse", &me, &p)) goto end;
   qd.p = p;
   qd.e = 0;
-  if (parse(&qd, &gp)) SYNERR(qd.e);
+  if (parse(&qd, &gp)) VALERR(qd.e);
   rc = fginfo_pywrap(&gp, ty);
 end:
   return (rc);
@@ -302,7 +302,7 @@ static PyGetSetDef bindhinfo_pygetset[] = {
 
 static PyTypeObject fginfo_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.FGInfo",                   /* @tp_name@ */
+  "FGInfo",                            /* @tp_name@ */
   sizeof(fginfo_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -350,7 +350,7 @@ static PyTypeObject fginfo_pytype_skel = {
 
 static PyTypeObject dhinfo_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.DHInfo",                   /* @tp_name@ */
+  "DHInfo",                            /* @tp_name@ */
   sizeof(fginfo_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -398,7 +398,7 @@ static PyTypeObject dhinfo_pytype_skel = {
 
 static PyTypeObject bindhinfo_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.BinDHInfo",                        /* @tp_name@ */
+  "BinDHInfo",                         /* @tp_name@ */
   sizeof(fginfo_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -517,7 +517,7 @@ static PyObject *ge_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
     sc.buf = PyString_AS_STRING(x);
     sc.lim = sc.buf + PyString_GET_SIZE(x);
     if (G_READ(g, xx, &mptext_stringops, &sc) || sc.buf < sc.lim)
-      SYNERR("malformed group element string");
+      VALERR("malformed group element string");
   } else
     TYERR("can't convert to group element");
   return (ge_pywrap((PyObject *)ty, xx));
@@ -542,7 +542,7 @@ static PyObject *group_dopywrap(PyTypeObject *ty, group *g)
   gobj->ty.ht_type.tp_alloc = PyType_GenericAlloc;
   gobj->ty.ht_type.tp_free = 0;
   gobj->ty.ht_type.tp_new = ge_pynew;
-  PyType_Ready(&gobj->ty.ht_type);
+  typeready(&gobj->ty.ht_type);
   return ((PyObject *)gobj);
 }
 
@@ -868,7 +868,7 @@ static PyObject *meth__GE_fromstring(PyObject *me, PyObject *arg)
   g = GROUP_G(me);
   x = G_CREATE(g);
   if (G_READ(g, x, &mptext_stringops, &sc))
-    SYNERR("bad group element string");
+    VALERR("bad group element string");
   return (Py_BuildValue("(Ns#)", ge_pywrap(me, x),
                        sc.buf, (int)(sc.lim - sc.buf)));
 end:
@@ -887,7 +887,7 @@ static PyObject *meth__Group_parse(PyObject *me, PyObject *arg)
   qd.p = p;
   qd.e = 0;
   if ((g = group_parse(&qd)) == 0)
-    SYNERR(qd.e);
+    VALERR(qd.e);
   return (group_pywrap(g));
 end:
   return (0);
@@ -914,6 +914,20 @@ static PyObject *gget_g(PyObject *me, void *hunoz)
   G_COPY(g, x, g->g); return (ge_pywrap(me, x));
 }
 
+static long ge_pyhash(PyObject *me)
+{
+  buf b;
+  size_t sz = GE_G(me)->noctets + 4;
+  uint32 h = 0xf672c776 + GE_G(me)->ops->ty;
+  octet *p = xmalloc(sz);
+  buf_init(&b, p, sz);
+  G_TOBUF(GE_G(me), &b, GE_X(me));
+  assert(BOK(&b));
+  h = unihash_hash(&unihash_global, h, BBASE(&b), BLEN(&b));
+  xfree(p);
+  return (h % LONG_MAX);
+}
+
 static PyObject *gget_r(PyObject *me, void *hunoz)
   { return (mp_pywrap(MP_COPY(GROUP_G(me)->r))); }
 
@@ -986,7 +1000,7 @@ static PyNumberMethods ge_pynumber = {
 
 static PyTypeObject ge_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GE",                       /* @tp_name@ */
+  "GE",                                        /* @tp_name@ */
   sizeof(ge_pyobj),                    /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -999,7 +1013,7 @@ static PyTypeObject ge_pytype_skel = {
   &ge_pynumber,                                /* @tp_as_number@ */
   0,                                   /* @tp_as_sequence@ */
   0,                                   /* @tp_as_mapping@ */
-  0,                                   /* @tp_hash@ */
+  ge_pyhash,                           /* @tp_hash@ */
   0,                                   /* @tp_call@ */
   ge_pystr,                            /* @tp_str@ */
   0,                                   /* @tp_getattro@ */
@@ -1056,7 +1070,7 @@ G.mexp([(X0, N0), (X1, N1), ...]) -> X0^N0 X1^N1 ...")
 
 static PyTypeObject group_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.Group",                    /* @tp_name@ */
+  "Group",                             /* @tp_name@ */
   sizeof(group_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1133,7 +1147,7 @@ static PyObject *primegroup_pynew(PyTypeObject *ty,
 
 static PyTypeObject primegroup_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.PrimeGroup",               /* @tp_name@ */
+  "PrimeGroup",                                /* @tp_name@ */
   sizeof(group_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1210,7 +1224,7 @@ static PyObject *bingroup_pynew(PyTypeObject *ty,
 
 static PyTypeObject bingroup_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.BinGroup",                 /* @tp_name@ */
+  "BinGroup",                          /* @tp_name@ */
   sizeof(group_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1288,7 +1302,7 @@ static PyObject *ecgroup_pynew(PyTypeObject *ty,
 
 static PyTypeObject ecgroup_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ECGroup",                  /* @tp_name@ */
+  "ECGroup",                           /* @tp_name@ */
   sizeof(group_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
diff --git a/key.c b/key.c
index 2af0019..6a601c9 100644 (file)
--- a/key.c
+++ b/key.c
@@ -483,7 +483,7 @@ static PyGetSetDef keydata_pygetset[] = {
 
 static PyTypeObject keydata_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyData",                  /* @tp_name@ */
+  "KeyData",                           /* @tp_name@ */
   sizeof(keydata_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -560,7 +560,7 @@ static PyGetSetDef keydatabin_pygetset[] = {
 
 static PyTypeObject keydatabin_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyDataBinary",            /* @tp_name@ */
+  "KeyDataBinary",                     /* @tp_name@ */
   sizeof(keydata_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -697,7 +697,7 @@ static PyGetSetDef keydataenc_pygetset[] = {
 
 static PyTypeObject keydataenc_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyDataEncrypted",         /* @tp_name@ */
+  "KeyDataEncrypted",                  /* @tp_name@ */
   sizeof(keydata_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -773,7 +773,7 @@ static PyGetSetDef keydatamp_pygetset[] = {
 
 static PyTypeObject keydatamp_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyDataMP",                        /* @tp_name@ */
+  "KeyDataMP",                         /* @tp_name@ */
   sizeof(keydata_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -848,7 +848,7 @@ static PyGetSetDef keydatastr_pygetset[] = {
 
 static PyTypeObject keydatastr_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyDataString",            /* @tp_name@ */
+  "KeyDataString",                     /* @tp_name@ */
   sizeof(keydata_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -928,7 +928,7 @@ static PyGetSetDef keydataec_pygetset[] = {
 
 static PyTypeObject keydataec_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyDataECPt",              /* @tp_name@ */
+  "KeyDataECPt",                       /* @tp_name@ */
   sizeof(keydata_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -999,7 +999,7 @@ static void subkeyiter_pydealloc(PyObject *me)
 
 static PyTypeObject subkeyiter_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.SubKeyIter",               /* @tp_name@ */
+  "SubKeyIter",                                /* @tp_name@ */
   sizeof(subkeyiter_pyobj),            /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1134,7 +1134,7 @@ static PyMappingMethods keydatastruct_pymapping = {
 
 static PyTypeObject keydatastruct_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyDataStructured",                /* @tp_name@ */
+  "KeyDataStructured",                 /* @tp_name@ */
   sizeof(keydata_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1210,7 +1210,7 @@ static void keyattriter_pydealloc(PyObject *me)
 
 static PyTypeObject keyattriter_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyAttributeIter",         /* @tp_name@ */
+  "KeyAttributeIter",                  /* @tp_name@ */
   sizeof(keyattriter_pyobj),           /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1320,7 +1320,7 @@ static PyMappingMethods keyattrs_pymapping = {
 
 static PyTypeObject keyattrs_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyAttributes",            /* @tp_name@ */
+  "KeyAttributes",                     /* @tp_name@ */
   sizeof(keyattrs_pyobj),              /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1622,7 +1622,7 @@ static PyGetSetDef key_pygetset[] = {
 
 static PyTypeObject key_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.Key",                      /* @tp_name@ */
+  "Key",                               /* @tp_name@ */
   sizeof(key_pyobj),                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1696,7 +1696,7 @@ static void keyiter_pydealloc(PyObject *me)
 
 static PyTypeObject keyiter_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyFileIter",              /* @tp_name@ */
+  "KeyFileIter",                       /* @tp_name@ */
   sizeof(keyiter_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -2017,7 +2017,7 @@ static PyMappingMethods keyfile_pymapping = {
 
 static PyTypeObject keyfile_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KeyFile",                  /* @tp_name@ */
+  "KeyFile",                           /* @tp_name@ */
   sizeof(keyfile_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
diff --git a/mp.c b/mp.c
index 705a65e..2434eaf 100644 (file)
--- a/mp.c
+++ b/mp.c
@@ -848,7 +848,7 @@ static PyNumberMethods mp_pynumber = {
 
 static PyTypeObject mp_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.MP",                       /* @tp_name@ */
+  "MP",                                        /* @tp_name@ */
   sizeof(mp_pyobj),                    /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -921,12 +921,31 @@ static PyObject *meth__MP_fromstring(PyObject *me,
   if (!good_radix_p(r, 1)) VALERR("bad radix");
   sc.buf = p; sc.lim = p + len;
   if ((zz = mp_read(MP_NEW, r, &mptext_stringops, &sc)) == 0)
-    SYNERR("bad integer");
+    VALERR("bad integer");
   z = Py_BuildValue("(Ns#)", mp_pywrap(zz), sc.buf, (int)(sc.lim - sc.buf));
 end:
   return (z);
 }
 
+static PyObject *meth__MP_factorial(PyObject *me, PyObject *arg)
+{
+  unsigned long i;
+  mp *x;
+  if (!PyArg_ParseTuple(arg, "OO&:factorial", &me, convulong, &i))
+    return (0);
+  x = mp_factorial(i);
+  return mp_pywrap(x);
+}
+
+static PyObject *meth__MP_fibonacci(PyObject *me, PyObject *arg)
+{
+  long i;
+  mp *x;
+  if (!PyArg_ParseTuple(arg, "Ol:fibonacci", &me, &i)) return (0);
+  x = mp_fibonacci(i);
+  return mp_pywrap(x);
+}
+
 #define LOADOP(pre, py, name)                                          \
   static PyObject *meth__##py##_##name(PyObject *me, PyObject *arg)    \
   {                                                                    \
@@ -1041,7 +1060,7 @@ static PyMethodDef mpmul_pymethods[] = {
 
 static PyTypeObject *mpmul_pytype, mpmul_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.MPMul",                    /* @tp_name@ */
+  "MPMul",                             /* @tp_name@ */
   sizeof(mpmul_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1308,7 +1327,7 @@ B.mexp([(X0, N0), (X1, N1), ...]) = X0^N0 X1^N1 mod B.m\n\
 
 static PyTypeObject *mpmont_pytype, mpmont_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.MPMont",                   /* @tp_name@ */
+  "MPMont",                            /* @tp_name@ */
   sizeof(mpmont_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1447,7 +1466,7 @@ B.mexp([(X0, N0), (X1, N1), ...]) = X0^N0 X1^N1 mod B.m\n\
 
 static PyTypeObject *mpbarrett_pytype, mpbarrett_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.MPBarrett",                        /* @tp_name@ */
+  "MPBarrett",                         /* @tp_name@ */
   sizeof(mpbarrett_pyobj),             /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1575,7 +1594,7 @@ static PyMethodDef mpreduce_pymethods[] = {
 
 static PyTypeObject *mpreduce_pytype, mpreduce_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.MPReduce",                 /* @tp_name@ */
+  "MPReduce",                          /* @tp_name@ */
   sizeof(mpreduce_pyobj),              /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1744,7 +1763,7 @@ static PyMethodDef mpcrt_pymethods[] = {
 
 static PyTypeObject *mpcrt_pytype, mpcrt_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.MPCRT",                    /* @tp_name@ */
+  "MPCRT",                             /* @tp_name@ */
   sizeof(mpcrt_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -2026,7 +2045,7 @@ static PyNumberMethods gf_pynumber = {
 
 static PyTypeObject gf_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GF",                       /* @tp_name@ */
+  "GF",                                        /* @tp_name@ */
   sizeof(mp_pyobj),                    /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -2104,7 +2123,7 @@ static PyObject *meth__GF_fromstring(PyObject *me,
   if ((zz = mp_read(MP_NEW, r, &mptext_stringops, &sc)) == 0 ||
       MP_NEGP(zz)) {
     if (zz) MP_DROP(zz);
-    SYNERR("bad binary polynomial");
+    VALERR("bad binary polynomial");
   }
   z = Py_BuildValue("(Ns#)", gf_pywrap(zz), sc.buf, (int)(sc.lim - sc.buf));
 end:
@@ -2249,7 +2268,7 @@ static PyMethodDef gfreduce_pymethods[] = {
 
 static PyTypeObject *gfreduce_pytype, gfreduce_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GFReduce",                 /* @tp_name@ */
+  "GFReduce",                          /* @tp_name@ */
   sizeof(gfreduce_pyobj),              /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -2383,7 +2402,7 @@ static PyMethodDef gfn_pymethods[] = {
 
 static PyTypeObject gfn_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GFN",                      /* @tp_name@ */
+  "GFN",                               /* @tp_name@ */
   sizeof(gfn_pyobj),                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -2446,6 +2465,10 @@ fromstring(STR, radix = 0) -> (X, REST)\n\
 Parse STR as a binary polynomial, according to radix.  If radix is zero,\n\
 read a prefix from STR to decide radix: allow `0' for octal, `0x' for hex\n\
 or `R_' for other radix R.")
+  METH (_MP_factorial,         "\
+factorial(I) -> I!: compute factorial")
+  METH (_MP_fibonacci,         "\
+fibonacci(I) -> F(I): compute Fibonacci number")
   METH (_MP_loadl,             "\
 loadl(STR) -> X: read little-endian bytes")
   METH (_MP_loadb,             "\
index 3d8c84b..7e28f93 100644 (file)
@@ -129,7 +129,7 @@ static PyMethodDef pixie_pymethods[] = {
 
 static PyTypeObject pixie_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.Pixie",                    /* @tp_name@ */
+  "Pixie",                             /* @tp_name@ */
   sizeof(pixie_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
diff --git a/pgen.c b/pgen.c
index 4758c78..15d1f6a 100644 (file)
--- a/pgen.c
+++ b/pgen.c
@@ -197,7 +197,7 @@ static PyNumberMethods pfilt_pynumber = {
 
 static PyTypeObject pfilt_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.PrimeFilter",              /* @tp_name@ */
+  "PrimeFilter",                       /* @tp_name@ */
   sizeof(pfilt_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -330,7 +330,7 @@ static PyMethodDef rabin_pymethods[] = {
 
 static PyTypeObject rabin_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.RabinMiller",              /* @tp_name@ */
+  "RabinMiller",                       /* @tp_name@ */
   sizeof(rabin_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -448,7 +448,7 @@ static PyGetSetDef pgevent_pygetset[] = {
 
 static PyTypeObject pgevent_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.PrimeGenEvent",            /* @tp_name@ */
+  "PrimeGenEvent",                     /* @tp_name@ */
   sizeof(pgevent_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -629,7 +629,7 @@ static PyMethodDef pgev_pymethods[] = {
 
 static PyTypeObject pgev_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.PrimeGenBuiltinHandler",   /* @tp_name@ */
+  "PrimeGenBuiltinHandler",            /* @tp_name@ */
   sizeof(pgev_pyobj),                  /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -703,7 +703,7 @@ static PyGetSetDef pgstep_pygetset[] = {
 
 static PyTypeObject pgstep_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.PrimeGenStepper",          /* @tp_name@ */
+  "PrimeGenStepper",                   /* @tp_name@ */
   sizeof(pgstep_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -785,7 +785,7 @@ static PyGetSetDef pgjump_pygetset[] = {
 
 static PyTypeObject pgjump_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.PrimeGenJumper",           /* @tp_name@ */
+  "PrimeGenJumper",                    /* @tp_name@ */
   sizeof(pgjump_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -846,7 +846,7 @@ end:
 
 static PyTypeObject pgtest_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.PrimeGenTester",           /* @tp_name@ */
+  "PrimeGenTester",                    /* @tp_name@ */
   sizeof(pgtest_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
index 8790e40..4c4eb1d 100644 (file)
--- a/pubkey.c
+++ b/pubkey.c
@@ -210,7 +210,7 @@ static PyMemberDef dsapriv_pymembers[] = {
 
 static PyTypeObject dsapub_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.DSAPub",                   /* @tp_name@ */
+  "DSAPub",                            /* @tp_name@ */
   sizeof(dsa_pyobj),                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -258,7 +258,7 @@ static PyTypeObject dsapub_pytype_skel = {
 
 static PyTypeObject dsapriv_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.DSAPriv",                  /* @tp_name@ */
+  "DSAPriv",                           /* @tp_name@ */
   sizeof(dsa_pyobj),                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -423,7 +423,7 @@ static PyMethodDef kcdsapriv_pymethods[] = {
 
 static PyTypeObject kcdsapub_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KCDSAPub",                 /* @tp_name@ */
+  "KCDSAPub",                          /* @tp_name@ */
   sizeof(dsa_pyobj),                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -471,7 +471,7 @@ static PyTypeObject kcdsapub_pytype_skel = {
 
 static PyTypeObject kcdsapriv_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.KCDSAPriv",                        /* @tp_name@ */
+  "KCDSAPriv",                         /* @tp_name@ */
   sizeof(dsa_pyobj),                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -764,7 +764,7 @@ static PyMethodDef rsapriv_pymethods[] = {
 
 static PyTypeObject rsapub_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.RSAPub",                   /* @tp_name@ */
+  "RSAPub",                            /* @tp_name@ */
   sizeof(rsapub_pyobj),                        /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -812,7 +812,7 @@ static PyTypeObject rsapub_pytype_skel = {
 
 static PyTypeObject rsapriv_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.RSAPriv",                  /* @tp_name@ */
+  "RSAPriv",                           /* @tp_name@ */
   sizeof(rsapriv_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
diff --git a/rand.c b/rand.c
index 3bcd0a9..49aaa38 100644 (file)
--- a/rand.c
+++ b/rand.c
@@ -270,7 +270,7 @@ static PyMethodDef grand_pymethods[] = {
 
 static PyTypeObject grand_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GRand",                    /* @tp_name@ */
+  "GRand",                             /* @tp_name@ */
   sizeof(grand_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -327,7 +327,7 @@ static PyObject *lcrand_pynew(PyTypeObject *me, PyObject *arg, PyObject *kw)
 
 static PyTypeObject lcrand_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.LCRand",                   /* @tp_name@ */
+  "LCRand",                            /* @tp_name@ */
   sizeof(grand_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -384,7 +384,7 @@ static PyObject *fibrand_pynew(PyTypeObject *me, PyObject *arg, PyObject *kw)
 
 static PyTypeObject fibrand_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.FibRand",                  /* @tp_name@ */
+  "FibRand",                           /* @tp_name@ */
   sizeof(grand_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -529,7 +529,7 @@ static PyGetSetDef truerand_pygetset[] = {
 
 static PyTypeObject truerand_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.TrueRand",                 /* @tp_name@ */
+  "TrueRand",                          /* @tp_name@ */
   sizeof(grand_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -581,26 +581,31 @@ static PyTypeObject *gccrand_pytype, *gcrand_pytype;
 
 typedef grand *gcrand_func(const void *, size_t sz);
 typedef grand *gcirand_func(const void *, size_t sz, uint32);
+typedef grand *gcnrand_func(const void *, size_t sz, const void *);
 typedef struct gccrand_info {
   const char *name;
   const octet *keysz;
   unsigned f;
+  size_t noncesz;
   gcrand_func *func;
 } gccrand_info;
 
+#define RNGF_INT 1u
+#define RNGF_NONCE 2u
+
 typedef struct gccrand_pyobj {
   PyHeapTypeObject ty;
   const gccrand_info *info;
 } gccrand_pyobj;
 #define GCCRAND_INFO(o) (((gccrand_pyobj *)(o))->info)
 
-#define GCCRAND_DEF(name, ksz, func, f)                                        \
+#define GCCRAND_DEF(name, ksz, func, f, nsz)                           \
   static const gccrand_info func##_info =                              \
-    { name, ksz, f, (gcrand_func *)func };
+    { name, ksz, f, nsz, (gcrand_func *)func };
 RNGS(GCCRAND_DEF)
 
 static const gccrand_info *const gcrandtab[] = {
-#define GCCRAND_ENTRY(name, ksz, func, f) &func##_info,
+#define GCCRAND_ENTRY(name, ksz, func, f, nsz) &func##_info,
   RNGS(GCCRAND_ENTRY)
   0
 };
@@ -639,6 +644,25 @@ end:
   return (0);
 }
 
+static PyObject *gcnrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
+{
+  const gccrand_info *info = GCCRAND_INFO(ty);
+  static char *kwlist[] = { "key", "nonce", 0 };
+  char *k, *n;
+  int ksz, nsz;
+
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#:new", kwlist,
+                                  &k, &ksz, &n, &nsz))
+    goto end;
+  if (keysz(ksz, info->keysz) != ksz) VALERR("bad key length");
+  if (nsz != info->noncesz) VALERR("bad nonce length");
+  return (grand_dopywrap(ty,
+                        ((gcnrand_func *)info->func)(k, ksz, n),
+                        f_freeme));
+end:
+  return (0);
+}
+
 static PyObject *gccrand_pywrap(const gccrand_info *info)
 {
   gccrand_pyobj *g = newtype(gccrand_pytype, 0, info->name);
@@ -651,11 +675,10 @@ static PyObject *gccrand_pywrap(const gccrand_info *info)
                            Py_TPFLAGS_HEAPTYPE);
   g->ty.ht_type.tp_alloc = PyType_GenericAlloc;
   g->ty.ht_type.tp_free = 0;
-  if (info->f & RNGF_INT)
-    g->ty.ht_type.tp_new = gcirand_pynew;
-  else
-    g->ty.ht_type.tp_new = gcrand_pynew;
-  PyType_Ready(&g->ty.ht_type);
+  if (info->f & RNGF_INT) g->ty.ht_type.tp_new = gcirand_pynew;
+  else if (info->f & RNGF_NONCE) g->ty.ht_type.tp_new = gcnrand_pynew;
+  else g->ty.ht_type.tp_new = gcrand_pynew;
+  typeready(&g->ty.ht_type);
   return ((PyObject *)g);
 }
 
@@ -674,7 +697,7 @@ static PyGetSetDef gccrand_pygetset[] = {
 
 static PyTypeObject gccrand_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GCCRand",                  /* @tp_name@ */
+  "GCCRand",                           /* @tp_name@ */
   sizeof(gccrand_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -722,7 +745,7 @@ static PyTypeObject gccrand_pytype_skel = {
 
 static PyTypeObject gcrand_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.GCRand",                   /* @tp_name@ */
+  "GCRand",                            /* @tp_name@ */
   sizeof(grand_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -823,7 +846,7 @@ end:
 
 static PyTypeObject sslprf_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.SSLRand",                  /* @tp_name@ */
+  "SSLRand",                           /* @tp_name@ */
   sizeof(grand_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -871,7 +894,7 @@ static PyTypeObject sslprf_pytype_skel = {
 
 static PyTypeObject tlsdx_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.TLSDataExpansion",         /* @tp_name@ */
+  "TLSDataExpansion",                  /* @tp_name@ */
   sizeof(grand_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -919,7 +942,7 @@ static PyTypeObject tlsdx_pytype_skel = {
 
 static PyTypeObject tlsprf_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.TLSPRF",                   /* @tp_name@ */
+  "TLSPRF",                            /* @tp_name@ */
   sizeof(grand_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -999,7 +1022,7 @@ static PyGetSetDef dsarand_pygetset[] = {
 
 static PyTypeObject dsarand_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.DSARand",                  /* @tp_name@ */
+  "DSARand",                           /* @tp_name@ */
   sizeof(grand_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1130,7 +1153,7 @@ static PyGetSetDef bbs_pygetset[] = {
 
 static PyTypeObject bbs_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.BlumBlumShub",             /* @tp_name@ */
+  "BlumBlumShub",                      /* @tp_name@ */
   sizeof(grand_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -1288,7 +1311,7 @@ static PyGetSetDef bbspriv_pygetset[] = {
 
 static PyTypeObject bbspriv_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.BBSPriv",                  /* @tp_name@ */
+  "BBSPriv",                           /* @tp_name@ */
   sizeof(bbspriv_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
diff --git a/share.c b/share.c
index 7e58783..ad56d31 100644 (file)
--- a/share.c
+++ b/share.c
@@ -63,7 +63,7 @@ static PyGetSetDef gfshare_pygetset[]= {
 
 static PyTypeObject gfshare_pytype_skel = {
   PyObject_HEAD_INIT(&PyType_Type) 0,  /* Header */
-  "catacomb.GFShare",                  /* @tp_name@ */
+  "GFShare",                           /* @tp_name@ */
   sizeof(gfshare_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -151,7 +151,7 @@ static PyMethodDef gfsharesplit_pymethods[] = {
 
 static PyTypeObject gfsharesplit_pytype_skel = {
   PyObject_HEAD_INIT(&PyType_Type) 0,  /* Header */
-  "catacomb.GFShareSplit",             /* @tp_name@ */
+  "GFShareSplit",                      /* @tp_name@ */
   sizeof(gfshare_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -272,7 +272,7 @@ static PyGetSetDef gfsharejoin_pygetset[]= {
 
 static PyTypeObject gfsharejoin_pytype_skel = {
   PyObject_HEAD_INIT(&PyType_Type) 0,  /* Header */
-  "catacomb.GFShareJoin",              /* @tp_name@ */
+  "GFShareJoin",                       /* @tp_name@ */
   sizeof(gfshare_pyobj),               /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -353,7 +353,7 @@ static PyGetSetDef share_pygetset[]= {
 
 static PyTypeObject share_pytype_skel = {
   PyObject_HEAD_INIT(&PyType_Type) 0,  /* Header */
-  "catacomb.Share",                    /* @tp_name@ */
+  "Share",                             /* @tp_name@ */
   sizeof(share_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -444,7 +444,7 @@ static PyMethodDef sharesplit_pymethods[] = {
 
 static PyTypeObject sharesplit_pytype_skel = {
   PyObject_HEAD_INIT(&PyType_Type) 0,  /* Header */
-  "catacomb.ShareSplit",               /* @tp_name@ */
+  "ShareSplit",                                /* @tp_name@ */
   sizeof(share_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -567,7 +567,7 @@ static PyGetSetDef sharejoin_pygetset[]= {
 
 static PyTypeObject sharejoin_pytype_skel = {
   PyObject_HEAD_INIT(&PyType_Type) 0,  /* Header */
-  "catacomb.ShareJoin",                        /* @tp_name@ */
+  "ShareJoin",                         /* @tp_name@ */
   sizeof(share_pyobj),                 /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
diff --git a/util.c b/util.c
index f56c7fd..8a0c06c 100644 (file)
--- a/util.c
+++ b/util.c
 
 #include "catacomb-python.h"
 
+/*----- External values ---------------------------------------------------*/
+
+static PyObject *modname = 0;
+
 /*----- Conversions -------------------------------------------------------*/
 
 PyObject *getulong(unsigned long w)
@@ -168,11 +172,17 @@ void *newtype(PyTypeObject *metaty,
   return (ty);
 }
 
+void typeready(PyTypeObject *ty)
+{
+  PyType_Ready(ty);
+  PyDict_SetItemString(ty->tp_dict, "__module__", modname);
+}
+
 PyTypeObject *inittype(PyTypeObject *tyskel)
 {
   PyTypeObject *ty = newtype(&PyType_Type, tyskel, 0);
   ty->tp_flags |= Py_TPFLAGS_HEAPTYPE;
-  PyType_Ready(ty);
+  typeready(ty);
   return (ty);
 }
 
@@ -634,6 +644,7 @@ PyMethodDef gmap_pymethods[] = {
 
 void util_pyinit(void)
 {
+  modname = PyString_FromString("catacomb");
   INITTYPE(itemiter, root);
   INITTYPE(valiter, root);
 }