Ticket #3: diff.patch.txt

File diff.patch.txt, 25.1 KB (added by zooko, at 2009-03-24T04:40:49Z)

version of this patch which attempts to use the old technique of the Python object having a pointer to the C++ object, instead of the new and very segfaulty technique of having the Python object contain the C++ object directly

Line 
1diff -rN -u old-trunk-hashedformat-ecdsa-with-Brian/pycryptopp/publickey/ecdsamodule.cpp new-trunk-hashedformat-ecdsa-with-Brian/pycryptopp/publickey/ecdsamodule.cpp
2--- old-trunk-hashedformat-ecdsa-with-Brian/pycryptopp/publickey/ecdsamodule.cpp        2009-03-23 22:39:53.000000000 -0600
3+++ new-trunk-hashedformat-ecdsa-with-Brian/pycryptopp/publickey/ecdsamodule.cpp        2009-03-23 22:39:54.000000000 -0600
4@@ -1,9 +1,12 @@
5 /**
6  * ecdsamodule.cpp -- Python wrappers around Crypto++'s
7- * ECDSA(1363)/EMSA1(SHA-256), more precisely: <a
8- * href="http://www.weidai.com/scan-mirror/sig.html#ECDSA">ECDSA</a> with GF(P)
9- * ("ECP") as the elliptic curve group parameters and SHA-256 as the hash
10- * function
11+ * ECDSA(1363)/EMSA1(Tiger) -- <a
12+ * href="http://www.weidai.com/scan-mirror/sig.html#ECDSA">ECDSA</a>.
13+ *
14+ * The keys (192-bit) use the curve ASN1::secp192r1() and Tiger as the hash
15+ * function.  There is a custom Key Derivation Protocol to generate private
16+ * (signing) keys from unguessable seeds -- see source code for details and
17+ * doc string for usage.
18  */
19 
20 #include <Python.h>
21@@ -20,23 +23,44 @@
22 #include <crypto++/osrng.h>
23 #include <crypto++/eccrypto.h>
24 #include <crypto++/oids.h>
25+#include <crypto++/tiger.h>
26+#include <crypto++/sha.h>
27+#include <crypto++/pubkey.h>
28+// only needed for debugging -- the _dump() function
29+#include <iostream>
30+#include <crypto++/ecp.h>
31+#include <crypto++/hex.h>
32 #else
33 #include <cryptopp/filters.h>
34 #include <cryptopp/osrng.h>
35 #include <cryptopp/eccrypto.h>
36 #include <cryptopp/oids.h>
37+#include <cryptopp/tiger.h>
38+#include <cryptopp/sha.h>
39+#include <cryptopp/pubkey.h>
40+// only needed for debugging -- the _dump() function
41+#include <iostream>
42+#include <cryptopp/ecp.h>
43+#include <cryptopp/hex.h>
44 #endif
45 
46+/* The ECDSA key size that pycryptopp currently supports -- you should do your own research, and
47+   I recommend http://keylength.com , but basically this is probably secure for most purposes
48+   for at least the next few years, especially if you have more than mere billions of keys that
49+   an attacker could target. */
50+/* NOTE: we -- Zooko and Brian Warner -- are currently thinking of increasing this keysize to 224 bits. */
51+static const int SMALL_KEY_SIZE_BITS=192;
52+
53 USING_NAMESPACE(CryptoPP)
54 
55 PyDoc_STRVAR(ecdsa__doc__,
56-"ecdsa -- ECDSA(1363)/EMSA1(SHA-256) signatures\n\
57+"ecdsa -- ECDSA(1363)/EMSA1(Tiger) signatures\n\
58 \n\
59-To create a new ECDSA signing key from the operating system's random number generator, call generate().\n\
60-To deserialize an ECDSA signing key from a string, call create_signing_key_from_string().\n\
61+To create a new ECDSA signing key (deterministically from a 12-byte seed), construct an instance of the class, passing the seed as argument, i.e. SigningKey(seed).  If you call serialize() on that instance, you'll get that seed back.\n\
62 \n\
63-To get an ECDSA verifying key from an ECDSA signing key, call get_verifying_key() on the signing key.\n\
64-To deserialize an ECDSA verifying key from a string, call create_verifying_key_from_string().");
65+To get a verifying key from a signing key, call get_verifying_key() on the signing key instance.\n\
66+\n\
67+To deserialize an ECDSA verifying key from a string, call VerifyingKey(serialized_verifying_key).");
68 
69 static PyObject *ecdsa_error;
70 
71@@ -44,12 +68,49 @@
72     PyObject_HEAD
73 
74     /* internal */
75-    ECDSA<ECP, SHA256>::Verifier *k;
76+    ECDSA<ECP, Tiger>::Verifier *k;
77 } VerifyingKey;
78 
79 PyDoc_STRVAR(VerifyingKey__doc__,
80 "an ECDSA verifying key");
81 
82+static int
83+VerifyingKey___init__(PyObject* self, PyObject* args, PyObject* kwdict) {
84+    static const char *kwlist[] = { "serializedverifyingkey", NULL };
85+    const char *serializedverifyingkey;
86+    Py_ssize_t serializedverifyingkeysize = 0;
87+
88+    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:VerifyingKey__init__", const_cast<char**>(kwlist), &serializedverifyingkey, &serializedverifyingkeysize))
89+        return NULL;
90+    assert (serializedverifyingkeysize >= 0);
91+
92+    if (serializedverifyingkeysize != 25) {
93+        PyErr_Format(ecdsa_error, "Precondition violation: size in bits is required to be %d (for %d-bit key), but it was %d", 25, SMALL_KEY_SIZE_BITS, serializedverifyingkeysize);
94+        return -1;
95+    }
96+
97+    VerifyingKey *mself = reinterpret_cast<VerifyingKey*>(self);
98+
99+    StringSource ss(reinterpret_cast<const byte*>(serializedverifyingkey), serializedverifyingkeysize, true);
100+
101+    ECP::Element element;
102+    DL_GroupParameters_EC<ECP> params(ASN1::secp192r1());
103+    params.SetPointCompression(true);
104+    try {
105+        element = params.DecodeElement(reinterpret_cast<const byte*>(serializedverifyingkey), true);
106+        mself->k = new ECDSA<ECP, Tiger>::Verifier(params, element);
107+        if (!mself->k) {
108+            PyErr_NoMemory();
109+            return -1;
110+        }
111+    } catch (InvalidDataFormat le) {
112+        PyErr_Format(ecdsa_error, "Serialized verifying key was corrupted.  Crypto++ gave this exception: %s", le.what());
113+        return -1;
114+    }
115+
116+    return 0;
117+}
118+
119 static void
120 VerifyingKey_dealloc(VerifyingKey* self) {
121     if (self->k)
122@@ -69,13 +130,6 @@
123     assert (msgsize >= 0);
124     assert (signaturesize >= 0);
125 
126-    Py_ssize_t sigsize = self->k->SignatureLength();
127-    if (sigsize != signaturesize)
128-        return PyErr_Format(ecdsa_error, "Precondition violation: signatures are required to be of size %zu, but it was %zu", sigsize, signaturesize);
129-    assert (sigsize >= 0);
130-
131-    assert (signaturesize == sigsize);
132-
133     if (self->k->VerifyMessage(reinterpret_cast<const byte*>(msg), msgsize, reinterpret_cast<const byte*>(signature), signaturesize))
134         Py_RETURN_TRUE;
135     else
136@@ -87,14 +141,19 @@
137 
138 static PyObject *
139 VerifyingKey_serialize(VerifyingKey *self, PyObject *dummy) {
140-    std::string outstr;
141-    StringSink ss(outstr);
142-    self->k->DEREncode(ss);
143-    PyStringObject* result = reinterpret_cast<PyStringObject*>(PyString_FromStringAndSize(outstr.c_str(), outstr.size()));
144+    const DL_PublicKey_EC<ECP>* pubkey;
145+    pubkey = dynamic_cast<const DL_PublicKey_EC<ECP>*>(&(self->k->GetPublicKey()));
146+    const DL_GroupParameters_EC<ECP>& params = pubkey->GetGroupParameters();
147+
148+    Py_ssize_t len = params.GetEncodedElementSize(true);
149+//XXX   params.SetPointCompression(true);
150+    PyObject* result = PyString_FromStringAndSize(NULL, len);
151     if (!result)
152         return NULL;
153 
154-    return reinterpret_cast<PyObject*>(result);
155+    params.EncodeElement(true, pubkey->GetPublicElement(), reinterpret_cast<byte*>(PyString_AS_STRING(result)));
156+
157+    return result;
158 }
159 
160 PyDoc_STRVAR(VerifyingKey_serialize__doc__,
161@@ -104,6 +163,7 @@
162 static PyMethodDef VerifyingKey_methods[] = {
163     {"verify", reinterpret_cast<PyCFunction>(VerifyingKey_verify), METH_KEYWORDS, VerifyingKey_verify__doc__},
164     {"serialize", reinterpret_cast<PyCFunction>(VerifyingKey_serialize), METH_NOARGS, VerifyingKey_serialize__doc__},
165+    {"_dump", reinterpret_cast<PyCFunction>(VerifyingKey__dump), METH_NOARGS, VerifyingKey__dump__doc__},
166     {NULL},
167 };
168 
169@@ -113,7 +173,7 @@
170     "ecdsa.VerifyingKey", /*tp_name*/
171     sizeof(VerifyingKey),             /*tp_basicsize*/
172     0,                         /*tp_itemsize*/
173-    reinterpret_cast<destructor>(VerifyingKey_dealloc), /*tp_dealloc*/
174+    VerifyingKey_dealloc,                         /*tp_dealloc*/
175     0,                         /*tp_print*/
176     0,                         /*tp_getattr*/
177     0,                         /*tp_setattr*/
178@@ -130,25 +190,23 @@
179     0,                         /*tp_as_buffer*/
180     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
181     VerifyingKey__doc__,           /* tp_doc */
182-    0,                        /* tp_traverse */
183-    0,                        /* tp_clear */
184-    0,                        /* tp_richcompare */
185-    0,                        /* tp_weaklistoffset */
186-    0,                        /* tp_iter */
187-    0,                        /* tp_iternext */
188+    0,                               /* tp_traverse */
189+    0,                               /* tp_clear */
190+    0,                               /* tp_richcompare */
191+    0,                               /* tp_weaklistoffset */
192+    0,                               /* tp_iter */
193+    0,                               /* tp_iternext */
194     VerifyingKey_methods,             /* tp_methods */
195+    0,                         /* tp_members */
196+    0,                         /* tp_getset */
197+    0,                         /* tp_base */
198+    0,                         /* tp_dict */
199+    0,                         /* tp_descr_get */
200+    0,                         /* tp_descr_set */
201+    0,                         /* tp_dictoffset */
202+    VerifyingKey___init__,       /* tp_init */
203 };
204 
205-/** This function is only for internal use by ecdsamodule.cpp. */
206-static VerifyingKey*
207-VerifyingKey_construct() {
208-    VerifyingKey *self = reinterpret_cast<VerifyingKey*>(VerifyingKey_type.tp_alloc(&VerifyingKey_type, 0));
209-    if (!self)
210-        return NULL;
211-    self->k = NULL;
212-    return self;
213-}
214-
215 PyDoc_STRVAR(SigningKey__doc__,
216 "an ECDSA signing key");
217 
218@@ -156,7 +214,7 @@
219     PyObject_HEAD
220 
221     /* internal */
222-    ECDSA<ECP, SHA256>::Signer *k;
223+    ECDSA<ECP, Tiger>::Signer *k;
224 } SigningKey;
225 
226 static void
227@@ -166,6 +224,136 @@
228     self->ob_type->tp_free((PyObject*)self);
229 }
230 
231+static const char* TAG_AND_SALT = "102:pycryptopp v0.5.3 key derivation algorithm using Tiger hash to generate ECDSA 192-bit secret exponents," \
232+    "16:H1yGNvUONoc0FD1d,";
233+static const size_t TAG_AND_SALT_len = 127;
234+
235+static int
236+SigningKey___init__(PyObject* self, PyObject* args, PyObject* kwdict) {
237+    static const char *kwlist[] = { "seed", NULL };
238+    const char* seed;
239+    int seedlen;
240+    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:SigningKey___init__", const_cast<char**>(kwlist), &seed, &seedlen)) {
241+        return -1;
242+    }
243+
244+    if (seedlen != 12) {
245+        PyErr_Format(ecdsa_error, "Precondition violation: seed is required to be of length 12, but it was %d", seedlen);
246+        return -1;
247+    }
248+
249+    OID curve;
250+    Integer grouporderm1;
251+    byte privexpbytes[24] = {0};
252+    Integer privexponentm1;
253+    privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); assert (priveexponentm1 == 0); // just checking..
254+
255+    curve = ASN1::secp192r1();
256+    grouporderm1 = DL_GroupParameters_EC<ECP>(curve).GetGroupOrder() - 1;
257+    Tiger t;
258+
259+    t.Update(reinterpret_cast<const byte*>(TAG_AND_SALT), TAG_AND_SALT_len);
260+    t.Update(reinterpret_cast<const byte*>(seed), seedlen);
261+    t.TruncatedFinal(privexpbytes, Tiger::DIGESTSIZE);
262+    privexponentm1.Decode(privexpbytes, sizeof(privexpbytes));
263+
264+    while (privexponentm1 >= grouporderm1) {
265+        Tiger t2;
266+        t2.Update(reinterpret_cast<const byte*>(TAG_AND_SALT), TAG_AND_SALT_len);
267+        std::cerr << "WHEE " << sizeof(privexpbytes) << "\n";std::cerr.flush();
268+        t2.Update(privexpbytes, sizeof(privexpbytes));
269+        t2.TruncatedFinal(privexpbytes, Tiger::DIGESTSIZE);
270+        privexponentm1.Decode(privexpbytes, sizeof(privexpbytes));
271+    }
272+
273+    SigningKey* mself = reinterpret_cast<SigningKey*>(self);
274+    mself->k = new ECDSA<ECP, Tiger>(curve, privexponentm1+1);
275+    if (!mself->k) {
276+        PyErr_NoMemory();
277+        return -1;
278+    }
279+
280+    return 0;
281+}
282+
283+PyDoc_STRVAR(SigningKey__init____doc__,
284+"Create a signing key (192 bits) deterministically from the given seed.\n\
285+\n\
286+This implies that if someone can guess the seed then they can learn the signing key.  A good way to get an unguessable seed is os.urandom(12).\n\
287+\n\
288+@param seed seed\n\
289+\n\
290+@precondition len(seed) >= ceil(sizeinbits/16.0)");
291+
292+static PyObject *
293+SigningKey__dump(SigningKey *self, PyObject *dummy) {
294+    const DL_GroupParameters_EC<ECP>& gp = self->k->GetKey().GetGroupParameters();
295+    std::cout << "whee " << gp.GetEncodedElementSize(true) << "\a";
296+    std::cout << "booo " << gp.GetEncodedElementSize(false) << "\n";
297+
298+    ECPPoint p = gp.GetSubgroupGenerator();
299+    std::cout << "generator " << p.x << ", " << p.y << "\n";
300+
301+    std::cout << "GroupOrder: ";
302+    std::cout << gp.GetGroupOrder();
303+    std::cout << "\n";
304+
305+    std::string s;
306+    StringSink* ss = new StringSink(s);
307+    HexEncoder he(ss);
308+    std::cout << "AlgorithmID: ";
309+    gp.GetAlgorithmID().DEREncode(he);
310+    std::cout << s << "\n";
311+
312+    const ECP& ec = gp.GetCurve();
313+    Integer fieldsize = ec.FieldSize();
314+    std::cout << "field size " << fieldsize.BitCount() << " " << fieldsize.ByteCount() << " " << ec.FieldSize() << "\n";
315+    std::cout << "Curve: ";
316+    std::cout << "curve field max element bit length: " << ec.GetField().MaxElementBitLength() << "\n";
317+    std::cout << "curve field modulus: " << ec.GetField().GetModulus() << "\n";
318+    std::cout << "curve A: " << ec.GetA() << ", curve B: " << ec.GetB();
319+
320+    const ECP::Field& f = ec.GetField();
321+    std::cout << "curve field modulus: " << f.GetModulus() << "\n";
322+    std::cout << "curve field identity: " << f.Identity() << "\n";
323+
324+    std::string cfs;
325+    StringSink* cfss = new StringSink(cfs);
326+    HexEncoder cfhe(cfss);
327+    f.DEREncode(cfhe);
328+    std::cout << "curve field derencoding: " << cfs << "\n";
329+
330+    const CryptoMaterial& cm = self->k->GetMaterial();
331+    Integer i;
332+    cm.GetValue("SubgroupOrder", i);
333+    std::cout << "\n";
334+    std::cout << "SubgroupOrder: ";
335+    std::cout << i;
336+    std::cout << "\n";
337+    ECP::Element e;
338+    cm.GetValue("SubgroupGenerator", e);
339+    std::cout << "SubgroupGenerator: ";
340+    std::cout << e.x << ", " << e.y;
341+    std::cout << "\n";
342+
343+    std::cout << "private key: ";
344+
345+    const PrivateKey& privkey = self->k->GetPrivateKey();
346+
347+    std::cout << privkey.GetValueNames() << "\n";
348+
349+    Integer privi;
350+    privkey.GetValue("PrivateExponent", privi);
351+    std::cout << privi << "\n";
352+    std::cout << "numbits: " << privi.BitCount() << "\n";
353+    std::cout << "numbytes: " << privi.ByteCount() << "\n";
354+
355+    Py_RETURN_NONE;
356+}
357+
358+PyDoc_STRVAR(SigningKey__dump__doc__,
359+"Print to stdout some descriptions of the math pieces.");
360+
361 static PyObject *
362 SigningKey_sign(SigningKey *self, PyObject *msgobj) {
363     const char *msg;
364@@ -173,22 +361,32 @@
365     PyString_AsStringAndSize(msgobj, const_cast<char**>(&msg), reinterpret_cast<Py_ssize_t*>(&msgsize));
366     assert (msgsize >= 0);
367 
368-    Py_ssize_t sigsize = self->k->SignatureLength();
369+    Py_ssize_t sigsize;
370+    sigsize = self->k->SignatureLength();
371+
372     PyStringObject* result = reinterpret_cast<PyStringObject*>(PyString_FromStringAndSize(NULL, sigsize));
373     if (!result)
374         return NULL;
375     assert (sigsize >= 0);
376 
377-    AutoSeededRandomPool randpool(false);
378-    Py_ssize_t siglengthwritten = self->k->SignMessage(
379-        randpool,
380-        reinterpret_cast<const byte*>(msg),
381-        msgsize,
382-        reinterpret_cast<byte*>(PyString_AS_STRING(result)));
383+    AutoSeededRandomPool randpool(false); //XXX
384+
385+    Py_ssize_t siglengthwritten;
386+    try {
387+        siglengthwritten = self->k->SignMessage(
388+            randpool,
389+            reinterpret_cast<const byte*>(msg),
390+            msgsize,
391+            reinterpret_cast<byte*>(PyString_AS_STRING(result)));
392+    } catch (InvalidDataFormat le) {
393+        Py_DECREF(result);
394+        return PyErr_Format(ecdsa_error, "Signing key was corrupted.  Crypto++ gave this exception: %s", le.what());
395+    }
396+
397     if (siglengthwritten < sigsize)
398         fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was shorter than expected.");
399     else if (siglengthwritten > sigsize) {
400-        fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was longer than expected, so invalid memory was overwritten.");
401+        fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was longer than expected, so memory was invalidly overwritten.");
402         abort();
403     }
404     assert (siglengthwritten >= 0);
405@@ -197,43 +395,29 @@
406 }
407 
408 PyDoc_STRVAR(SigningKey_sign__doc__,
409-"Return a signature on the argument.");
410+     "Return a signature on the argument."); //XXX  If randseed is not None then it is required to be an  "); // XXX randseed!
411 
412 static PyObject *
413 SigningKey_get_verifying_key(SigningKey *self, PyObject *dummy) {
414-    VerifyingKey *verifier = reinterpret_cast<VerifyingKey*>(VerifyingKey_construct());
415+    VerifyingKey *verifier = PyObject_New(VerifyingKey, &VerifyingKey_type);
416+
417     if (!verifier)
418         return NULL;
419 
420-    verifier->k = new ECDSA<ECP, SHA256>::Verifier(*(self->k));
421+    verifier->k = new ECDSA<ECP, Tiger>::Verifier(self->k);
422     if (!verifier->k)
423         return PyErr_NoMemory();
424+
425     return reinterpret_cast<PyObject*>(verifier);
426 }
427 
428 PyDoc_STRVAR(SigningKey_get_verifying_key__doc__,
429 "Return the corresponding verifying key.");
430 
431-static PyObject *
432-SigningKey_serialize(SigningKey *self, PyObject *dummy) {
433-    Py_ssize_t len = self->k->GetKey().GetGroupParameters().GetSubgroupOrder().ByteCount();
434-    PyObject* result = PyString_FromStringAndSize(NULL, len);
435-
436-    const DL_PrivateKey_EC<ECP>& privkey = dynamic_cast<const DL_PrivateKey_EC<ECP>&>(self->k->GetPrivateKey());
437-
438-    privkey.GetPrivateExponent().Encode(reinterpret_cast<byte*>(PyString_AS_STRING(result)), len);
439-
440-    return result;
441-}
442-
443-PyDoc_STRVAR(SigningKey_serialize__doc__,
444-"Return a string containing the key material.  The string can be passed to \n\
445-create_signing_key_from_string() to instantiate a new copy of this key.");
446-
447 static PyMethodDef SigningKey_methods[] = {
448     {"sign", reinterpret_cast<PyCFunction>(SigningKey_sign), METH_O, SigningKey_sign__doc__},
449+    {"_dump", reinterpret_cast<PyCFunction>(SigningKey__dump), METH_NOARGS, SigningKey__dump__doc__},
450     {"get_verifying_key", reinterpret_cast<PyCFunction>(SigningKey_get_verifying_key), METH_NOARGS, SigningKey_get_verifying_key__doc__},
451-    {"serialize", reinterpret_cast<PyCFunction>(SigningKey_serialize), METH_NOARGS, SigningKey_serialize__doc__},
452     {NULL},
453 };
454 
455@@ -243,7 +427,7 @@
456     "ecdsa.SigningKey", /*tp_name*/
457     sizeof(SigningKey),             /*tp_basicsize*/
458     0,                         /*tp_itemsize*/
459-    (destructor)SigningKey_dealloc, /*tp_dealloc*/
460+    SigningKey_dealloc,                         /*tp_dealloc*/
461     0,                         /*tp_print*/
462     0,                         /*tp_getattr*/
463     0,                         /*tp_setattr*/
464@@ -258,143 +442,31 @@
465     0,                         /*tp_getattro*/
466     0,                         /*tp_setattro*/
467     0,                         /*tp_as_buffer*/
468-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
469-    SigningKey__doc__,           /* tp_doc */
470-    0,                        /* tp_traverse */
471-    0,                        /* tp_clear */
472-    0,                        /* tp_richcompare */
473-    0,                        /* tp_weaklistoffset */
474-    0,                        /* tp_iter */
475-    0,                        /* tp_iternext */
476-    SigningKey_methods             /* tp_methods */
477+    Py_TPFLAGS_DEFAULT,        /*tp_flags*/
478+    SigningKey__doc__,         /* tp_doc */
479+    0,                               /* tp_traverse */
480+    0,                               /* tp_clear */
481+    0,                               /* tp_richcompare */
482+    0,                               /* tp_weaklistoffset */
483+    0,                               /* tp_iter */
484+    0,                               /* tp_iternext */
485+    SigningKey_methods,             /* tp_methods */
486+    0,                         /* tp_members */
487+    0,                         /* tp_getset */
488+    0,                         /* tp_base */
489+    0,                         /* tp_dict */
490+    0,                         /* tp_descr_get */
491+    0,                         /* tp_descr_set */
492+    0,                         /* tp_dictoffset */
493+    SigningKey___init__,       /* tp_init */
494 };
495 
496-/** This function is only for internal use by ecdsamodule.cpp. */
497-static SigningKey*
498-SigningKey_construct() {
499-    SigningKey *self = reinterpret_cast<SigningKey*>(SigningKey_type.tp_alloc(&SigningKey_type, 0));
500-    if (!self)
501-        return NULL;
502-    self->k = NULL;
503-    return self;
504-}
505-
506-/* The smaller ECDSA key size that pycryptopp supports -- you should do your
507-   own research, and I recommend http://keylength.com , but basically this is
508-   probably secure for most purposes for at least the next few years, and
509-   possibly for longer. */
510-static const int SMALL_KEY_SIZE_BITS=192;
511-
512-/* The larger ECDSA key size that pycryptopp supports -- you should do your
513-   own research, and I recommend http://keylength.com , but basically this is
514-   probably secure for many years, unless there is a surprising breakthrough in
515-   the theory of elliptic curve cryptography. */
516-static const int LARGE_KEY_SIZE_BITS=521;
517-
518-static PyObject *
519-generate(PyObject *dummy, PyObject *args, PyObject *kwdict) {
520-    static const char *kwlist[] = {
521-        "sizeinbits",
522-        NULL
523-    };
524-    int sizeinbits;
525-
526-    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "i:generate", const_cast<char**>(kwlist), &sizeinbits))
527-        return NULL;
528-
529-    if (sizeinbits != SMALL_KEY_SIZE_BITS && sizeinbits != LARGE_KEY_SIZE_BITS)
530-        return PyErr_Format(ecdsa_error, "Precondition violation: size in bits is required to be either %d or %d, but it was %d", SMALL_KEY_SIZE_BITS, LARGE_KEY_SIZE_BITS, sizeinbits);
531-
532-    AutoSeededRandomPool osrng(false);
533-    SigningKey *signer = SigningKey_construct();
534-    if (!signer)
535-        return NULL;
536-
537-    OID curve;
538-    if (sizeinbits == 192)
539-        curve = ASN1::secp192r1();
540-    else
541-        curve = ASN1::secp521r1();
542-
543-    signer->k = new ECDSA<ECP, SHA256>::Signer(osrng, curve);
544-    if (!signer->k)
545-        return PyErr_NoMemory();
546-    return reinterpret_cast<PyObject*>(signer);
547-}
548-
549-PyDoc_STRVAR(generate__doc__,
550-"Create a signing key using the operating system's random number generator.\n\
551-\n\
552-@param sizeinbits size of the key in bits\n\
553-\n\
554-@precondition sizeinbits in (192, 521)");
555-
556-static PyObject *
557-create_verifying_key_from_string(PyObject *dummy, PyObject *args, PyObject *kwdict) {
558-    static const char *kwlist[] = {
559-        "serializedverifyingkey",
560-        NULL
561-    };
562-    const char *serializedverifyingkey;
563-    Py_ssize_t serializedverifyingkeysize = 0;
564-
565-    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:create_verifying_key_from_string", const_cast<char**>(kwlist), &serializedverifyingkey, &serializedverifyingkeysize))
566-        return NULL;
567-    assert (serializedverifyingkeysize >= 0);
568-
569-    VerifyingKey *verifier = reinterpret_cast<VerifyingKey*>(VerifyingKey_construct());
570-    if (!verifier)
571-        return NULL;
572-    StringSource ss(reinterpret_cast<const byte*>(serializedverifyingkey), serializedverifyingkeysize, true);
573-
574-    verifier->k = new ECDSA<ECP, SHA256>::Verifier(ss);
575-    if (!verifier->k)
576-        return PyErr_NoMemory();
577-    return reinterpret_cast<PyObject*>(verifier);
578-}
579-
580 PyDoc_STRVAR(create_verifying_key_from_string__doc__,
581-"Create a verifying key from its serialized state.");
582-
583-static PyObject *
584-create_signing_key_from_string(PyObject *dummy, PyObject *args, PyObject *kwdict) {
585-    static const char *kwlist[] = {
586-        "serializedsigningkey",
587-        NULL
588-    };
589-    const char *serializedsigningkey;
590-    Py_ssize_t serializedsigningkeysize = 0;
591-
592-    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:create_signing_key_from_string", const_cast<char**>(kwlist), &serializedsigningkey, &serializedsigningkeysize))
593-        return NULL;
594-    if (serializedsigningkeysize != 24 && serializedsigningkeysize != 66)
595-        return PyErr_Format(ecdsa_error, "Precondition violation: size in bytes of the serialized signing key is required to be either %d (for %d-bit keys) or %d (for %d-bit keys), but it was %d", 24, SMALL_KEY_SIZE_BITS, 66, LARGE_KEY_SIZE_BITS, serializedsigningkeysize);
596-
597-
598-    SigningKey *verifier = SigningKey_construct();
599-    if (!verifier)
600-        return NULL;
601-
602-    OID curve;
603-    if (serializedsigningkeysize == 24)
604-        curve = ASN1::secp192r1();
605-    else
606-        curve = ASN1::secp521r1();
607-    Integer privexponent(reinterpret_cast<const byte*>(serializedsigningkey), serializedsigningkeysize);
608-
609-    verifier->k = new ECDSA<ECP, SHA256>::Signer(curve, privexponent);
610-    if (!verifier->k)
611-        return PyErr_NoMemory();
612-    return reinterpret_cast<PyObject*>(verifier);
613-}
614-
615-PyDoc_STRVAR(create_signing_key_from_string__doc__,
616-"Create a signing key from its serialized state.");
617+"Create a verifying key from its serialized state.\n\
618+\n\
619+@precondition Length of serialized key is required to be 24 (for 192-bit key)."); //XXX actually 25 length
620 
621 static PyMethodDef ecdsa_functions[] = {
622-    {"generate", reinterpret_cast<PyCFunction>(generate), METH_KEYWORDS, generate__doc__},
623-    {"create_verifying_key_from_string", reinterpret_cast<PyCFunction>(create_verifying_key_from_string), METH_KEYWORDS, create_verifying_key_from_string__doc__},
624-    {"create_signing_key_from_string", reinterpret_cast<PyCFunction>(create_signing_key_from_string), METH_KEYWORDS, create_signing_key_from_string__doc__},
625     {NULL, NULL, 0, NULL}  /* sentinel */
626 };
627 
628@@ -406,8 +478,10 @@
629     PyObject *module;
630     PyObject *module_dict;
631 
632+    VerifyingKey_type.tp_new = PyType_GenericNew;
633     if (PyType_Ready(&VerifyingKey_type) < 0)
634         return;
635+    SigningKey_type.tp_new = PyType_GenericNew;
636     if (PyType_Ready(&SigningKey_type) < 0)
637         return;
638 
639