aboutsummaryrefslogtreecommitdiff
path: root/src/key.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/key.h')
-rw-r--r--src/key.h175
1 files changed, 175 insertions, 0 deletions
diff --git a/src/key.h b/src/key.h
new file mode 100644
index 0000000000..c973d6eb82
--- /dev/null
+++ b/src/key.h
@@ -0,0 +1,175 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_KEY_H
+#define BITCOIN_KEY_H
+
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/obj_mac.h>
+
+// secp160k1
+// const unsigned int PRIVATE_KEY_SIZE = 192;
+// const unsigned int PUBLIC_KEY_SIZE = 41;
+// const unsigned int SIGNATURE_SIZE = 48;
+//
+// secp192k1
+// const unsigned int PRIVATE_KEY_SIZE = 222;
+// const unsigned int PUBLIC_KEY_SIZE = 49;
+// const unsigned int SIGNATURE_SIZE = 57;
+//
+// secp224k1
+// const unsigned int PRIVATE_KEY_SIZE = 250;
+// const unsigned int PUBLIC_KEY_SIZE = 57;
+// const unsigned int SIGNATURE_SIZE = 66;
+//
+// secp256k1:
+// const unsigned int PRIVATE_KEY_SIZE = 279;
+// const unsigned int PUBLIC_KEY_SIZE = 65;
+// const unsigned int SIGNATURE_SIZE = 72;
+//
+// see www.keylength.com
+// script supports up to 75 for single byte push
+
+
+
+class key_error : public std::runtime_error
+{
+public:
+ explicit key_error(const std::string& str) : std::runtime_error(str) {}
+};
+
+
+// secure_allocator is defined in serialize.h
+typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
+
+
+
+class CKey
+{
+protected:
+ EC_KEY* pkey;
+ bool fSet;
+
+public:
+ CKey()
+ {
+ pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
+ if (pkey == NULL)
+ throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
+ fSet = false;
+ }
+
+ CKey(const CKey& b)
+ {
+ pkey = EC_KEY_dup(b.pkey);
+ if (pkey == NULL)
+ throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
+ fSet = b.fSet;
+ }
+
+ CKey& operator=(const CKey& b)
+ {
+ if (!EC_KEY_copy(pkey, b.pkey))
+ throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
+ fSet = b.fSet;
+ return (*this);
+ }
+
+ ~CKey()
+ {
+ EC_KEY_free(pkey);
+ }
+
+ bool IsNull() const
+ {
+ return !fSet;
+ }
+
+ void MakeNewKey()
+ {
+ if (!EC_KEY_generate_key(pkey))
+ throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
+ fSet = true;
+ }
+
+ bool SetPrivKey(const CPrivKey& vchPrivKey)
+ {
+ const unsigned char* pbegin = &vchPrivKey[0];
+ if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
+ return false;
+ fSet = true;
+ return true;
+ }
+
+ CPrivKey GetPrivKey() const
+ {
+ unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
+ if (!nSize)
+ throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
+ CPrivKey vchPrivKey(nSize, 0);
+ unsigned char* pbegin = &vchPrivKey[0];
+ if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
+ throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
+ return vchPrivKey;
+ }
+
+ bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
+ {
+ const unsigned char* pbegin = &vchPubKey[0];
+ if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
+ return false;
+ fSet = true;
+ return true;
+ }
+
+ std::vector<unsigned char> GetPubKey() const
+ {
+ unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
+ if (!nSize)
+ throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
+ std::vector<unsigned char> vchPubKey(nSize, 0);
+ unsigned char* pbegin = &vchPubKey[0];
+ if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
+ throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
+ return vchPubKey;
+ }
+
+ 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))
+ return false;
+ vchSig.resize(nSize);
+ memcpy(&vchSig[0], pchSig, nSize);
+ return true;
+ }
+
+ bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
+ {
+ // -1 = error, 0 = bad sig, 1 = good
+ if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
+ return false;
+ return true;
+ }
+
+ static bool Sign(const CPrivKey& vchPrivKey, uint256 hash, std::vector<unsigned char>& vchSig)
+ {
+ CKey key;
+ if (!key.SetPrivKey(vchPrivKey))
+ return false;
+ return key.Sign(hash, vchSig);
+ }
+
+ static bool Verify(const std::vector<unsigned char>& vchPubKey, uint256 hash, const std::vector<unsigned char>& vchSig)
+ {
+ CKey key;
+ if (!key.SetPubKey(vchPubKey))
+ return false;
+ return key.Verify(hash, vchSig);
+ }
+};
+
+#endif