2010-07-14 17:54:31 +02:00
|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
2012-02-07 17:28:30 +01:00
|
|
|
// Copyright (c) 2009-2012 The Bitcoin developers
|
2010-07-14 17:54:31 +02:00
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
2012-05-18 16:02:28 +02:00
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
2011-05-15 09:11:04 +02:00
|
|
|
#ifndef BITCOIN_KEY_H
|
|
|
|
#define BITCOIN_KEY_H
|
2010-07-14 17:54:31 +02:00
|
|
|
|
2011-06-26 16:11:56 +02:00
|
|
|
#include <stdexcept>
|
|
|
|
#include <vector>
|
|
|
|
|
2012-04-17 20:37:47 +02:00
|
|
|
#include "allocators.h"
|
2012-05-14 19:07:52 +02:00
|
|
|
#include "serialize.h"
|
2011-06-26 16:11:56 +02:00
|
|
|
#include "uint256.h"
|
2012-12-18 20:56:21 +01:00
|
|
|
#include "hash.h"
|
2011-06-26 16:11:56 +02:00
|
|
|
|
2012-05-16 18:36:38 +02:00
|
|
|
#include <openssl/ec.h> // for EC_KEY definition
|
|
|
|
|
2010-07-14 17:54:31 +02:00
|
|
|
// 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) {}
|
|
|
|
};
|
|
|
|
|
2012-05-14 23:44:52 +02:00
|
|
|
/** A reference to a CKey: the Hash160 of its serialized public key */
|
|
|
|
class CKeyID : public uint160
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CKeyID() : uint160(0) { }
|
|
|
|
CKeyID(const uint160 &in) : uint160(in) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
/** A reference to a CScript: the Hash160 of its serialization (see script.h) */
|
|
|
|
class CScriptID : public uint160
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CScriptID() : uint160(0) { }
|
|
|
|
CScriptID(const uint160 &in) : uint160(in) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
/** An encapsulated public key. */
|
2012-05-14 19:07:52 +02:00
|
|
|
class CPubKey {
|
|
|
|
private:
|
2013-04-30 21:56:04 +02:00
|
|
|
unsigned char vch[65];
|
|
|
|
|
|
|
|
unsigned int static GetLen(unsigned char chHeader) {
|
|
|
|
if (chHeader == 2 || chHeader == 3)
|
|
|
|
return 33;
|
|
|
|
if (chHeader == 4 || chHeader == 6 || chHeader == 7)
|
|
|
|
return 65;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char *begin() {
|
|
|
|
return vch;
|
|
|
|
}
|
|
|
|
|
2012-05-14 19:07:52 +02:00
|
|
|
friend class CKey;
|
|
|
|
|
|
|
|
public:
|
2013-04-30 21:56:04 +02:00
|
|
|
CPubKey() { vch[0] = 0xFF; }
|
|
|
|
|
|
|
|
CPubKey(const std::vector<unsigned char> &vchPubKeyIn) {
|
|
|
|
int len = vchPubKeyIn.empty() ? 0 : GetLen(vchPubKeyIn[0]);
|
|
|
|
if (len) {
|
|
|
|
memcpy(vch, &vchPubKeyIn[0], len);
|
|
|
|
} else {
|
|
|
|
vch[0] = 0xFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int size() const {
|
|
|
|
return GetLen(vch[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
const unsigned char *begin() const {
|
|
|
|
return vch;
|
|
|
|
}
|
2012-05-14 19:07:52 +02:00
|
|
|
|
2013-04-30 21:56:04 +02:00
|
|
|
const unsigned char *end() const {
|
|
|
|
return vch+size();
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator==(const CPubKey &a, const CPubKey &b) { return memcmp(a.vch, b.vch, a.size()) == 0; }
|
|
|
|
friend bool operator!=(const CPubKey &a, const CPubKey &b) { return memcmp(a.vch, b.vch, a.size()) != 0; }
|
|
|
|
friend bool operator<(const CPubKey &a, const CPubKey &b) {
|
|
|
|
return a.vch[0] < b.vch[0] ||
|
|
|
|
(a.vch[0] == b.vch[0] && memcmp(a.vch+1, b.vch+1, a.size() - 1) < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int GetSerializeSize(int nType, int nVersion) const {
|
|
|
|
return size() + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Stream> void Serialize(Stream &s, int nType, int nVersion) const {
|
|
|
|
unsigned int len = size();
|
|
|
|
::Serialize(s, VARINT(len), nType, nVersion);
|
|
|
|
s.write((char*)vch, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Stream> void Unserialize(Stream &s, int nType, int nVersion) {
|
|
|
|
unsigned int len;
|
|
|
|
::Unserialize(s, VARINT(len), nType, nVersion);
|
|
|
|
if (len <= 65) {
|
|
|
|
s.read((char*)vch, len);
|
|
|
|
} else {
|
|
|
|
// invalid pubkey
|
|
|
|
vch[0] = 0xFF;
|
|
|
|
char dummy;
|
|
|
|
while (len--)
|
|
|
|
s.read(&dummy, 1);
|
|
|
|
}
|
|
|
|
}
|
2012-05-14 19:07:52 +02:00
|
|
|
|
2012-05-14 23:44:52 +02:00
|
|
|
CKeyID GetID() const {
|
2013-04-30 21:56:04 +02:00
|
|
|
return CKeyID(Hash160(vch, vch+size()));
|
2012-05-14 19:07:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
uint256 GetHash() const {
|
2013-04-30 21:56:04 +02:00
|
|
|
return Hash(vch, vch+size());
|
2012-05-14 19:07:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsValid() const {
|
2013-04-30 21:56:04 +02:00
|
|
|
return size() > 0;
|
2012-05-14 19:07:52 +02:00
|
|
|
}
|
|
|
|
|
2012-05-14 23:44:52 +02:00
|
|
|
bool IsCompressed() const {
|
2013-04-30 21:56:04 +02:00
|
|
|
return size() == 33;
|
2012-05-14 23:44:52 +02:00
|
|
|
}
|
|
|
|
|
2012-05-14 19:07:52 +02:00
|
|
|
std::vector<unsigned char> Raw() const {
|
2013-04-30 21:56:04 +02:00
|
|
|
return std::vector<unsigned char>(vch, vch+size());
|
2012-05-14 19:07:52 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-07-14 17:54:31 +02:00
|
|
|
|
2012-09-15 12:10:00 +02:00
|
|
|
// secure_allocator is defined in allocators.h
|
2011-11-07 00:05:42 +01:00
|
|
|
// CPrivKey is a serialized private key, with all parameters included (279 bytes)
|
2011-05-15 09:11:04 +02:00
|
|
|
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
|
2011-11-07 00:05:42 +01:00
|
|
|
// CSecret is a serialization of just the secret parameter (32 bytes)
|
2011-06-25 14:57:32 +02:00
|
|
|
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
|
2010-07-14 17:54:31 +02:00
|
|
|
|
2012-03-26 16:48:23 +02:00
|
|
|
/** An encapsulated OpenSSL Elliptic Curve key (public and/or private) */
|
2010-07-14 17:54:31 +02:00
|
|
|
class CKey
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
EC_KEY* pkey;
|
|
|
|
bool fSet;
|
2011-11-21 02:46:28 +01:00
|
|
|
bool fCompressedPubKey;
|
|
|
|
|
2010-07-14 17:54:31 +02:00
|
|
|
public:
|
2012-06-15 18:52:19 +02:00
|
|
|
void SetCompressedPubKey(bool fCompressed = true);
|
2011-11-21 02:46:28 +01:00
|
|
|
|
2012-05-16 18:36:38 +02:00
|
|
|
void Reset();
|
2010-07-14 17:54:31 +02:00
|
|
|
|
2012-05-16 18:36:38 +02:00
|
|
|
CKey();
|
|
|
|
CKey(const CKey& b);
|
2011-11-21 02:46:28 +01:00
|
|
|
|
2012-05-16 18:36:38 +02:00
|
|
|
CKey& operator=(const CKey& b);
|
2010-07-14 17:54:31 +02:00
|
|
|
|
2012-05-16 18:36:38 +02:00
|
|
|
~CKey();
|
2010-07-14 17:54:31 +02:00
|
|
|
|
2012-05-16 18:36:38 +02:00
|
|
|
bool IsNull() const;
|
|
|
|
bool IsCompressed() const;
|
2011-06-25 14:57:32 +02:00
|
|
|
|
2012-05-16 18:36:38 +02:00
|
|
|
void MakeNewKey(bool fCompressed);
|
|
|
|
bool SetPrivKey(const CPrivKey& vchPrivKey);
|
|
|
|
bool SetSecret(const CSecret& vchSecret, bool fCompressed = false);
|
|
|
|
CSecret GetSecret(bool &fCompressed) const;
|
|
|
|
CPrivKey GetPrivKey() const;
|
2012-05-14 19:07:52 +02:00
|
|
|
bool SetPubKey(const CPubKey& vchPubKey);
|
|
|
|
CPubKey GetPubKey() const;
|
2011-06-25 14:57:32 +02:00
|
|
|
|
2012-05-16 18:36:38 +02:00
|
|
|
bool Sign(uint256 hash, std::vector<unsigned char>& vchSig);
|
2010-07-14 17:54:31 +02:00
|
|
|
|
2011-04-25 13:23:29 +02:00
|
|
|
// create a compact signature (65 bytes), which allows reconstructing the used public key
|
2011-11-07 00:05:42 +01:00
|
|
|
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
|
|
|
|
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
|
|
|
|
// 0x1D = second key with even y, 0x1E = second key with odd y
|
2012-05-16 18:36:38 +02:00
|
|
|
bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig);
|
2011-04-25 13:23:29 +02:00
|
|
|
|
|
|
|
// reconstruct public key from a compact signature
|
2011-11-07 00:05:42 +01:00
|
|
|
// This is only slightly more CPU intensive than just verifying it.
|
|
|
|
// If this function succeeds, the recovered public key is guaranteed to be valid
|
|
|
|
// (the signature is a valid signature of the given data for that key)
|
2012-05-16 18:36:38 +02:00
|
|
|
bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig);
|
2011-04-25 13:23:29 +02:00
|
|
|
|
2012-05-16 18:36:38 +02:00
|
|
|
bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig);
|
2011-07-05 20:53:43 +02:00
|
|
|
|
2011-11-07 00:05:42 +01:00
|
|
|
// Verify a compact signature
|
2012-05-16 18:36:38 +02:00
|
|
|
bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig);
|
2012-01-26 19:26:34 +01:00
|
|
|
|
2012-05-16 18:36:38 +02:00
|
|
|
bool IsValid();
|
2010-07-14 17:54:31 +02:00
|
|
|
};
|
2011-05-15 09:11:04 +02:00
|
|
|
|
|
|
|
#endif
|