1 | diff -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 | |
---|