diff options
| author | Micah Anderson <micah@riseup.net> | 2013-08-22 16:39:52 -0400 | 
|---|---|---|
| committer | Micah Anderson <micah@riseup.net> | 2013-08-22 16:39:52 -0400 | 
| commit | 5e60e0e3af85f22aa0afe8bf0ecf85619afacfeb (patch) | |
| tree | 6a91a3de86fa8de0b4167cc947ab72991bf8da31 /pycryptopp/publickey/ecdsamodule.cpp | |
| parent | 30e9097985656920f01a72efc1088caa2b8d41b3 (diff) | |
Imported Upstream version 0.6.0.12upstream/0.6.0.12
Diffstat (limited to 'pycryptopp/publickey/ecdsamodule.cpp')
| -rw-r--r-- | pycryptopp/publickey/ecdsamodule.cpp | 523 | 
1 files changed, 0 insertions, 523 deletions
| diff --git a/pycryptopp/publickey/ecdsamodule.cpp b/pycryptopp/publickey/ecdsamodule.cpp deleted file mode 100644 index 95df348..0000000 --- a/pycryptopp/publickey/ecdsamodule.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/** -* Things to do: -* Make it work and pass tests. -* compressed pub keys -- check out Wei Dai's example code on mailinglist as linked to from pycryptopp trac by Brian -* Make new KDF (standard, Crypto++-compatible). -*  in C++ -*  in Python -* use Crypto++ Randomize()'s -* provide RNG class which is P1363-SHA-256 - -* Profit! -* Migrate pair-programming to Bespin. -* Put a Tahoe backend under Bespin. -*/ - -/** - * ecdsamodule.cpp -- Python wrappers around Crypto++'s - * ECDSA(1363)/EMSA1(SHA-256) -- <a - * href="http://www.weidai.com/scan-mirror/sig.html#ECDSA">ECDSA</a>. - * - * The keys (192-bit) use the curve ASN1::secp192r1() and SHA-256 as the - * hash function.  The Key Derivation Protocol is P1363_KDF2<SHA256> - * http://www.users.zetnet.co.uk/hopwood/crypto/scan/prf.html#KDF2 - * to generate private (signing) keys from unguessable seeds -- see - * source code for details and doc string for usage. - */ - -#define PY_SSIZE_T_CLEAN -#include <Python.h> -#if (PY_VERSION_HEX < 0x02050000) -typedef int Py_ssize_t; -#endif - -#include <math.h> - -#include "ecdsamodule.hpp" - -/* from Crypto++ */ -#ifdef DISABLE_EMBEDDED_CRYPTOPP -#include <cryptopp/filters.h> -#include <cryptopp/osrng.h> -#include <cryptopp/eccrypto.h> -#include <cryptopp/oids.h> -#include <cryptopp/tiger.h> -#include <cryptopp/sha.h> -#include <cryptopp/pubkey.h> -// only needed for debugging -- the _dump() function -#include <iostream> -#include <cryptopp/ecp.h> -#include <cryptopp/hex.h> -#else -#include <embeddedcryptopp/filters.h> -#include <embeddedcryptopp/osrng.h> -#include <embeddedcryptopp/eccrypto.h> -#include <embeddedcryptopp/oids.h> -#include <embeddedcryptopp/tiger.h> -#include <embeddedcryptopp/sha.h> -#include <embeddedcryptopp/pubkey.h> -// only needed for debugging -- the _dump() function -#include <iostream> -#include <embeddedcryptopp/ecp.h> -#include <embeddedcryptopp/hex.h> -#endif - -static const int KEY_SIZE_BITS=192; - -USING_NAMESPACE(CryptoPP) - -static const char*const ecdsa___doc__ = "ecdsa -- ECDSA(1363)/EMSA1(Tiger) signatures\n\ -\n\ -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).\n\ -\n\ -To get a verifying key from a signing key, call get_verifying_key() on the signing key instance.\n\ -\n\ -To deserialize an ECDSA verifying key from a string, call VerifyingKey(serialized_verifying_key)."; - -static PyObject *ecdsa_error; - -typedef struct { -    PyObject_HEAD - -    /* internal */ -    ECDSA<ECP, Tiger>::Verifier *k; -} VerifyingKey; - -PyDoc_STRVAR(VerifyingKey__doc__, -"an ECDSA verifying key"); - -static int -VerifyingKey___init__(PyObject* self, PyObject* args, PyObject* kwdict) { -    static const char *kwlist[] = { "serializedverifyingkey", NULL }; -    const char *serializedverifyingkey; -    Py_ssize_t serializedverifyingkeysize = 0; - -    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:VerifyingKey__init__", const_cast<char**>(kwlist), &serializedverifyingkey, &serializedverifyingkeysize)) -        return NULL; -    assert (serializedverifyingkeysize >= 0); - -    if (serializedverifyingkeysize != 25) { -        PyErr_Format(ecdsa_error, "Precondition violation: size in bits is required to be %d (for %d-bit key), but it was %Zd", 25, KEY_SIZE_BITS, serializedverifyingkeysize); -        return -1; -    } - -    VerifyingKey *mself = reinterpret_cast<VerifyingKey*>(self); - -    StringSource ss(reinterpret_cast<const byte*>(serializedverifyingkey), serializedverifyingkeysize, true); - -    ECP::Element element; -    DL_GroupParameters_EC<ECP> params(ASN1::secp192r1()); -    params.SetPointCompression(true); -    try { -        element = params.DecodeElement(reinterpret_cast<const byte*>(serializedverifyingkey), true); -        mself->k = new ECDSA<ECP, Tiger>::Verifier(params, element); -        if (!mself->k) { -            PyErr_NoMemory(); -            return -1; -        } -    } catch (InvalidDataFormat le) { -        PyErr_Format(ecdsa_error, "Serialized verifying key was corrupted.  Crypto++ gave this exception: %s", le.what()); -        return -1; -    } - -    return 0; -} - -static void -VerifyingKey_dealloc(VerifyingKey* self) { -    if (self->k) -        delete self->k; -    self->ob_type->tp_free((PyObject*)self); -} - -static PyObject * -VerifyingKey_verify(VerifyingKey *self, PyObject *args, PyObject *kwdict) { -    static const char *kwlist[] = { "msg", "signature", NULL }; -    const char *msg; -    Py_ssize_t msgsize; -    const char *signature; -    Py_ssize_t signaturesize = 0; -    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#t#:verify", const_cast<char**>(kwlist), &msg, &msgsize, &signature, &signaturesize)) -        return NULL; -    assert (msgsize >= 0); -    assert (signaturesize >= 0); - -    if (self->k->VerifyMessage(reinterpret_cast<const byte*>(msg), msgsize, reinterpret_cast<const byte*>(signature), signaturesize)) -        Py_RETURN_TRUE; -    else -        Py_RETURN_FALSE; -} - -PyDoc_STRVAR(VerifyingKey_verify__doc__, -"Return whether the signature is a valid signature on the msg."); - -static PyObject * -VerifyingKey_serialize(VerifyingKey *self, PyObject *dummy) { -    ECDSA<ECP, Tiger>::Verifier *pubkey; -    pubkey = new ECDSA<ECP, Tiger>::Verifier(*(self->k)); -    const DL_GroupParameters_EC<ECP>& params = pubkey->GetKey().GetGroupParameters(); - -    Py_ssize_t len = params.GetEncodedElementSize(true); -    PyObject* result = PyString_FromStringAndSize(NULL, len); -    if (!result) -        return NULL; - -    params.EncodeElement(true, pubkey->GetKey().GetPublicElement(), -                         reinterpret_cast<byte*>(PyString_AS_STRING(result))); - -    return result; -} - -PyDoc_STRVAR(VerifyingKey_serialize__doc__, -"Return a string containing the key material.  The string can be passed to \n\ -the constructor of VerifyingKey to instantiate a new copy of this key."); - -static PyMethodDef VerifyingKey_methods[] = { -    {"verify", reinterpret_cast<PyCFunction>(VerifyingKey_verify), METH_KEYWORDS, VerifyingKey_verify__doc__}, -    {"serialize", reinterpret_cast<PyCFunction>(VerifyingKey_serialize), METH_NOARGS, VerifyingKey_serialize__doc__}, -    {NULL}, -}; - -static PyTypeObject VerifyingKey_type = { -    PyObject_HEAD_INIT(NULL) -    0,                         /*ob_size*/ -    "ecdsa.VerifyingKey", /*tp_name*/ -    sizeof(VerifyingKey),             /*tp_basicsize*/ -    0,                         /*tp_itemsize*/ -    (destructor)VerifyingKey_dealloc,                         /*tp_dealloc*/ -    0,                         /*tp_print*/ -    0,                         /*tp_getattr*/ -    0,                         /*tp_setattr*/ -    0,                         /*tp_compare*/ -    0,                         /*tp_repr*/ -    0,                         /*tp_as_number*/ -    0,                         /*tp_as_sequence*/ -    0,                         /*tp_as_mapping*/ -    0,                         /*tp_hash */ -    0,                         /*tp_call*/ -    0,                         /*tp_str*/ -    0,                         /*tp_getattro*/ -    0,                         /*tp_setattro*/ -    0,                         /*tp_as_buffer*/ -    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ -    VerifyingKey__doc__,           /* tp_doc */ -    0,                               /* tp_traverse */ -    0,                               /* tp_clear */ -    0,                               /* tp_richcompare */ -    0,                               /* tp_weaklistoffset */ -    0,                               /* tp_iter */ -    0,                               /* tp_iternext */ -    VerifyingKey_methods,             /* tp_methods */ -    0,                         /* tp_members */ -    0,                         /* tp_getset */ -    0,                         /* tp_base */ -    0,                         /* tp_dict */ -    0,                         /* tp_descr_get */ -    0,                         /* tp_descr_set */ -    0,                         /* tp_dictoffset */ -    VerifyingKey___init__,       /* tp_init */ -}; - -typedef struct { -    PyObject_HEAD - -    /* internal */ -    ECDSA<ECP, Tiger>::Signer *k; -} SigningKey; - -static void -SigningKey_dealloc(SigningKey* self) { -    if (self->k) -        delete self->k; -    self->ob_type->tp_free((PyObject*)self); -} - -static const char* TAG_AND_SALT = "102:pycryptopp v0.5.3 key derivation algorithm using Tiger hash to generate ECDSA 192-bit secret exponents," \ -    "16:H1yGNvUONoc0FD1d,"; -static const size_t TAG_AND_SALT_len = 127; - -/** copied from Crypto++'s integer.cpp */ -/** The following is in Crypto++'s integer.cpp and we use them: -* void Integer::Randomize(RandomNumberGenerator &rng, size_t nbits) -* { -* 	const size_t nbytes = nbits/8 + 1; -* 	SecByteBlock buf(nbytes); -* 	rng.GenerateBlock(buf, nbytes); -* 	if (nbytes) -* 		buf[0] = (byte)Crop(buf[0], nbits % 8); -* 	Decode(buf, nbytes, UNSIGNED); -* } -* void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max) -* { -* 	if (min > max) -* 		throw InvalidArgument("Integer: Min must be no greater than Max"); -* -* 	Integer range = max - min; -* 	const unsigned int nbits = range.BitCount(); -* -* 	do -* 	{ -* 		Randomize(rng, nbits); -* 	} -* 	while (*this > range); -* -* 	*this += min; -* } -* -*/ - -static int -SigningKey___init__(PyObject* self, PyObject* args, PyObject* kwdict) { -    static const char *kwlist[] = { "seed", NULL }; -    const char* seed; -    Py_ssize_t seedlen; -    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:SigningKey___init__", const_cast<char**>(kwlist), &seed, &seedlen)) { -        return -1; -    } - -    if (seedlen != 12) { -        PyErr_Format(ecdsa_error, "Precondition violation: seed is required to be of length 12, but it was %zd", seedlen); -        return -1; -    } - -    OID curve; -    Integer grouporderm1; -    byte privexpbytes[24] = {0}; -    Integer privexponentm1; -    privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); assert (privexponentm1 == 0); // just checking.. - -    DL_GroupParameters_EC<ECP> params(ASN1::secp192r1()); -    params.SetPointCompression(true); -    grouporderm1 = params.GetGroupOrder() - 1; -    Tiger t; - -    t.Update(reinterpret_cast<const byte*>(TAG_AND_SALT), TAG_AND_SALT_len); -    t.Update(reinterpret_cast<const byte*>(seed), seedlen); -    t.TruncatedFinal(privexpbytes, Tiger::DIGESTSIZE); -    privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); - -    while (privexponentm1 >= grouporderm1) { -        Tiger t2; -        t2.Update(reinterpret_cast<const byte*>(TAG_AND_SALT), TAG_AND_SALT_len); -        std::cerr << "WHEE " << sizeof(privexpbytes) << "\n";std::cerr.flush(); -        t2.Update(privexpbytes, sizeof(privexpbytes)); -        t2.TruncatedFinal(privexpbytes, Tiger::DIGESTSIZE); -        privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); -    } - -    SigningKey* mself = reinterpret_cast<SigningKey*>(self); - -    mself->k = new ECDSA<ECP, Tiger>::Signer(params, privexponentm1+1); - -    if (!mself->k) { -        PyErr_NoMemory(); -        return -1; -    } - -    return 0; -} - -PyDoc_STRVAR(SigningKey__init____doc__, -"Create a signing key (192 bits) deterministically from the given seed.\n\ -\n\ -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\ -\n\ -@param seed seed\n\ -\n\ -@precondition len(seed) >= ceil(sizeinbits/16.0)"); - -static PyObject * -SigningKey__dump(SigningKey *self, PyObject *dummy) { -    const DL_GroupParameters_EC<ECP>& gp = self->k->GetKey().GetGroupParameters(); -    std::cout << "whee " << gp.GetEncodedElementSize(true) << "\a"; -    std::cout << "booo " << gp.GetEncodedElementSize(false) << "\n"; - -    ECPPoint p = gp.GetSubgroupGenerator(); -    std::cout << "generator " << p.x << ", " << p.y << "\n"; - -    std::cout << "GroupOrder: "; -    std::cout << gp.GetGroupOrder(); -    std::cout << "\n"; - -    std::string s; -    StringSink* ss = new StringSink(s); -    HexEncoder he(ss); -    std::cout << "AlgorithmID: "; -    gp.GetAlgorithmID().DEREncode(he); -    std::cout << s << "\n"; - -    const ECP& ec = gp.GetCurve(); -    Integer fieldsize = ec.FieldSize(); -    std::cout << "field size " << fieldsize.BitCount() << " " << fieldsize.ByteCount() << " " << ec.FieldSize() << "\n"; -    std::cout << "Curve: "; -    std::cout << "curve field max element bit length: " << ec.GetField().MaxElementBitLength() << "\n"; -    std::cout << "curve field modulus: " << ec.GetField().GetModulus() << "\n"; -    std::cout << "curve A: " << ec.GetA() << ", curve B: " << ec.GetB(); - -    const ECP::Field& f = ec.GetField(); -    std::cout << "curve field modulus: " << f.GetModulus() << "\n"; -    std::cout << "curve field identity: " << f.Identity() << "\n"; - -    std::string cfs; -    StringSink* cfss = new StringSink(cfs); -    HexEncoder cfhe(cfss); -    f.DEREncode(cfhe); -    std::cout << "curve field derencoding: " << cfs << "\n"; - -    const CryptoMaterial& cm = self->k->GetMaterial(); -    Integer i; -    cm.GetValue("SubgroupOrder", i); -    std::cout << "\n"; -    std::cout << "SubgroupOrder: "; -    std::cout << i; -    std::cout << "\n"; -    ECP::Element e; -    cm.GetValue("SubgroupGenerator", e); -    std::cout << "SubgroupGenerator: "; -    std::cout << e.x << ", " << e.y; -    std::cout << "\n"; - -    std::cout << "private key: "; - -    const PrivateKey& privkey = self->k->GetPrivateKey(); - -    std::cout << privkey.GetValueNames() << "\n"; - -    Integer privi; -    privkey.GetValue("PrivateExponent", privi); -    std::cout << privi << "\n"; -    std::cout << "numbits: " << privi.BitCount() << "\n"; -    std::cout << "numbytes: " << privi.ByteCount() << "\n"; - -    Py_RETURN_NONE; -} - -PyDoc_STRVAR(SigningKey__dump__doc__, -"Print to stdout some descriptions of the math pieces."); - -static PyObject * -SigningKey_sign(SigningKey *self, PyObject *msgobj) { -    const char *msg; -    Py_ssize_t msgsize; -    PyString_AsStringAndSize(msgobj, const_cast<char**>(&msg), reinterpret_cast<Py_ssize_t*>(&msgsize)); -    assert (msgsize >= 0); - -    Py_ssize_t sigsize; -    sigsize = self->k->SignatureLength(); - -    PyStringObject* result = reinterpret_cast<PyStringObject*>(PyString_FromStringAndSize(NULL, sigsize)); -    if (!result) -        return NULL; -    assert (sigsize >= 0); - -    AutoSeededRandomPool randpool(false); //XXX - -    Py_ssize_t siglengthwritten; -    try { -        siglengthwritten = self->k->SignMessage( -            randpool, -            reinterpret_cast<const byte*>(msg), -            msgsize, -            reinterpret_cast<byte*>(PyString_AS_STRING(result))); -    } catch (InvalidDataFormat le) { -        Py_DECREF(result); -        return PyErr_Format(ecdsa_error, "Signing key was corrupted.  Crypto++ gave this exception: %s", le.what()); -    } - -    if (siglengthwritten < sigsize) -        fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was shorter than expected."); -    else if (siglengthwritten > sigsize) { -        fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was longer than expected, so memory was invalidly overwritten."); -        abort(); -    } -    assert (siglengthwritten >= 0); - -    return reinterpret_cast<PyObject*>(result); -} - -PyDoc_STRVAR(SigningKey_sign__doc__, -     "Return a signature on the argument."); //XXX  If randseed is not None then it is required to be an  "); // XXX randseed! - -static PyObject * -SigningKey_get_verifying_key(SigningKey *self, PyObject *dummy) { -    VerifyingKey *verifier = PyObject_New(VerifyingKey, &VerifyingKey_type); -    if (!verifier) -        return NULL; - -    verifier->k = new ECDSA<ECP, Tiger>::Verifier(*(self->k)); -    if (!verifier->k) -        return PyErr_NoMemory(); -    verifier->k->AccessKey().AccessGroupParameters().SetPointCompression(true); - -    return reinterpret_cast<PyObject*>(verifier); -} - -PyDoc_STRVAR(SigningKey_get_verifying_key__doc__, -"Return the corresponding verifying key."); - -static PyMethodDef SigningKey_methods[] = { -    {"sign", reinterpret_cast<PyCFunction>(SigningKey_sign), METH_O, SigningKey_sign__doc__}, -    {"_dump", reinterpret_cast<PyCFunction>(SigningKey__dump), METH_NOARGS, SigningKey__dump__doc__}, -    {"get_verifying_key", reinterpret_cast<PyCFunction>(SigningKey_get_verifying_key), METH_NOARGS, SigningKey_get_verifying_key__doc__}, -    {NULL}, -}; - -static PyTypeObject SigningKey_type = { -    PyObject_HEAD_INIT(NULL) -    0,                         /*ob_size*/ -    "ecdsa.SigningKey", /*tp_name*/ -    sizeof(SigningKey),             /*tp_basicsize*/ -    0,                         /*tp_itemsize*/ -    (destructor)SigningKey_dealloc,                         /*tp_dealloc*/ -    0,                         /*tp_print*/ -    0,                         /*tp_getattr*/ -    0,                         /*tp_setattr*/ -    0,                         /*tp_compare*/ -    0,                         /*tp_repr*/ -    0,                         /*tp_as_number*/ -    0,                         /*tp_as_sequence*/ -    0,                         /*tp_as_mapping*/ -    0,                         /*tp_hash */ -    0,                         /*tp_call*/ -    0,                         /*tp_str*/ -    0,                         /*tp_getattro*/ -    0,                         /*tp_setattro*/ -    0,                         /*tp_as_buffer*/ -    Py_TPFLAGS_DEFAULT,        /*tp_flags*/ -    SigningKey__init____doc__,         /* tp_doc */ -    0,                               /* tp_traverse */ -    0,                               /* tp_clear */ -    0,                               /* tp_richcompare */ -    0,                               /* tp_weaklistoffset */ -    0,                               /* tp_iter */ -    0,                               /* tp_iternext */ -    SigningKey_methods,             /* tp_methods */ -    0,                         /* tp_members */ -    0,                         /* tp_getset */ -    0,                         /* tp_base */ -    0,                         /* tp_dict */ -    0,                         /* tp_descr_get */ -    0,                         /* tp_descr_set */ -    0,                         /* tp_dictoffset */ -    SigningKey___init__,       /* tp_init */ -}; - -void -init_ecdsa(PyObject*const module) { -    VerifyingKey_type.tp_new = PyType_GenericNew; -    if (PyType_Ready(&VerifyingKey_type) < 0) -        return; -    Py_INCREF(&VerifyingKey_type); -    PyModule_AddObject(module, "ecdsa_VerifyingKey", (PyObject *)&VerifyingKey_type); - -    SigningKey_type.tp_new = PyType_GenericNew; -    if (PyType_Ready(&SigningKey_type) < 0) -        return; -    Py_INCREF(&SigningKey_type); -    PyModule_AddObject(module, "ecdsa_SigningKey", (PyObject *)&SigningKey_type); - -    ecdsa_error = PyErr_NewException(const_cast<char*>("_ecdsa.Error"), NULL, NULL); -    PyModule_AddObject(module, "ecdsa_Error", ecdsa_error); - -    PyModule_AddStringConstant(module, "ecdsa___doc__", const_cast<char*>(ecdsa___doc__)); -} | 
