Merge branch '0.4.x' into 0.5.x
[novacoin.git] / src / key.h
index f20acb3..d096b39 100644 (file)
--- a/src/key.h
+++ b/src/key.h
@@ -169,6 +169,11 @@ protected:
     EC_KEY* pkey;
     bool fSet;
 
+    void SetCompressedPubKey()
+    {
+        EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
+    }
+
 public:
     CKey()
     {
@@ -257,7 +262,7 @@ public:
 
     CPrivKey GetPrivKey() const
     {
-        unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
+        int nSize = i2d_ECPrivateKey(pkey, NULL);
         if (!nSize)
             throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
         CPrivKey vchPrivKey(nSize, 0);
@@ -278,7 +283,7 @@ public:
 
     std::vector<unsigned char> GetPubKey() const
     {
-        unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
+        int nSize = i2o_ECPublicKey(pkey, NULL);
         if (!nSize)
             throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
         std::vector<unsigned char> vchPubKey(nSize, 0);
@@ -290,13 +295,14 @@ public:
 
     bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
     {
-        vchSig.clear();
-        unsigned char pchSig[10000];
-        unsigned int nSize = 0;
-        if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
+        unsigned int nSize = ECDSA_size(pkey);
+        vchSig.resize(nSize); // Make sure it is big enough
+        if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
+        {
+            vchSig.clear();
             return false;
-        vchSig.resize(nSize);
-        memcpy(&vchSig[0], pchSig, nSize);
+        }
+        vchSig.resize(nSize); // Shrink to fit actual size
         return true;
     }
 
@@ -349,7 +355,8 @@ public:
     {
         if (vchSig.size() != 65)
             return false;
-        if (vchSig[0]<27 || vchSig[0]>=31)
+        int nV = vchSig[0];
+        if (nV<27 || nV>=35)
             return false;
         ECDSA_SIG *sig = ECDSA_SIG_new();
         BN_bin2bn(&vchSig[1],32,sig->r);
@@ -357,7 +364,12 @@ public:
 
         EC_KEY_free(pkey);
         pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
-        if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), vchSig[0] - 27, 0) == 1)
+        if (nV >= 31)
+        {
+            SetCompressedPubKey();
+            nV -= 4;
+        }
+        if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
         {
             fSet = true;
             ECDSA_SIG_free(sig);