upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/key.h
diff options
context:
space:
mode:
authorbitflash-coin <bookofshamers@outlook.com>2026-08-04 06:34:32 -0700
committerbitflash-coin <bookofshamers@outlook.com>2026-08-04 06:34:32 -0700
commit5ce650382352c1503f40abf08129ada69402af55 (patch)
tree6a18198901f1e2c4933f1ac53c9365eec512bf63 /src/key.h
parentf34113291da7e5e3dc7d2468d4f9c212c05c584b (diff)
public commit
Diffstat (limited to 'src/key.h')
-rw-r--r--src/key.h190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/key.h b/src/key.h
new file mode 100644
index 0000000..6cc2a24
--- /dev/null
+++ b/src/key.h
@@ -0,0 +1,190 @@
1// Copyright (c) 2009 Satoshi Nakamoto
2// Distributed under the MIT/X11 software license, see the accompanying
3// file license.txt or http://www.opensource.org/licenses/mit-license.php.
4
5
6// secp160k1
7// const unsigned int PRIVATE_KEY_SIZE = 192;
8// const unsigned int PUBLIC_KEY_SIZE = 41;
9// const unsigned int SIGNATURE_SIZE = 48;
10//
11// secp192k1
12// const unsigned int PRIVATE_KEY_SIZE = 222;
13// const unsigned int PUBLIC_KEY_SIZE = 49;
14// const unsigned int SIGNATURE_SIZE = 57;
15//
16// secp224k1
17// const unsigned int PRIVATE_KEY_SIZE = 250;
18// const unsigned int PUBLIC_KEY_SIZE = 57;
19// const unsigned int SIGNATURE_SIZE = 66;
20//
21// secp256k1:
22// const unsigned int PRIVATE_KEY_SIZE = 279;
23// const unsigned int PUBLIC_KEY_SIZE = 65;
24// const unsigned int SIGNATURE_SIZE = 72;
25//
26// see www.keylength.com
27// script supports up to 75 for single byte push
28
29
30
31class key_error : public std::runtime_error
32{
33public:
34 explicit key_error(const std::string& str) : std::runtime_error(str) {}
35};
36
37
38// secure_allocator is defined is serialize.h
39typedef vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
40
41
42
43class CKey
44{
45protected:
46 EC_KEY* pkey;
47
48public:
49 CKey()
50 {
51 pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
52 if (pkey == NULL)
53 throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
54 }
55
56 CKey(const CKey& b)
57 {
58 pkey = EC_KEY_dup(b.pkey);
59 if (pkey == NULL)
60 throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
61 }
62
63 CKey& operator=(const CKey& b)
64 {
65 if (!EC_KEY_copy(pkey, b.pkey))
66 throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
67 return (*this);
68 }
69
70 ~CKey()
71 {
72 EC_KEY_free(pkey);
73 }
74
75 void MakeNewKey()
76 {
77 if (!EC_KEY_generate_key(pkey))
78 throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
79 }
80
81 bool SetPrivKey(const CPrivKey& vchPrivKey)
82 {
83 const unsigned char* pbegin = &vchPrivKey[0];
84 if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
85 return false;
86 return true;
87 }
88
89 // Load a raw 32-byte scalar, the form BIP32 derivation produces.
90 //
91 // SetPrivKey above takes DER and cannot be used for this: handing it a
92 // scalar makes d2i_ECPrivateKey fail, and if the caller ignores the return
93 // value -- as one attempt at this did -- the key is left with no material
94 // at all and the address it produces has no private half. Coins paid there
95 // are gone. Hence a separate entry point rather than a looser SetPrivKey.
96 //
97 // The public half is computed here rather than read from anywhere:
98 // pub = G * secret.
99 bool SetSecret(const std::vector<unsigned char>& vchSecret)
100 {
101 if (vchSecret.size() != 32)
102 return false;
103
104 bool fOk = false;
105 BIGNUM* bn = BN_bin2bn(&vchSecret[0], 32, NULL);
106 EC_POINT* pubkey = NULL;
107 if (bn && EC_KEY_set_private_key(pkey, bn))
108 {
109 const EC_GROUP* group = EC_KEY_get0_group(pkey);
110 pubkey = EC_POINT_new(group);
111 if (pubkey &&
112 EC_POINT_mul(group, pubkey, bn, NULL, NULL, NULL) &&
113 EC_KEY_set_public_key(pkey, pubkey))
114 fOk = true;
115 }
116 if (pubkey)
117 EC_POINT_free(pubkey);
118 if (bn)
119 BN_clear_free(bn); // it held the secret
120 return fOk;
121 }
122
123 CPrivKey GetPrivKey() const
124 {
125 unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
126 if (!nSize)
127 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
128 CPrivKey vchPrivKey(nSize, 0);
129 unsigned char* pbegin = &vchPrivKey[0];
130 if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
131 throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
132 return vchPrivKey;
133 }
134
135 bool SetPubKey(const vector<unsigned char>& vchPubKey)
136 {
137 const unsigned char* pbegin = &vchPubKey[0];
138 if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
139 return false;
140 return true;
141 }
142
143 vector<unsigned char> GetPubKey() const
144 {
145 unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
146 if (!nSize)
147 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
148 vector<unsigned char> vchPubKey(nSize, 0);
149 unsigned char* pbegin = &vchPubKey[0];
150 if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
151 throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
152 return vchPubKey;
153 }
154
155 bool Sign(uint256 hash, vector<unsigned char>& vchSig)
156 {
157 vchSig.clear();
158 unsigned char pchSig[10000];
159 unsigned int nSize = 0;
160 if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
161 return false;
162 vchSig.resize(nSize);
163 memcpy(&vchSig[0], pchSig, nSize);
164 return true;
165 }
166
167 bool Verify(uint256 hash, const vector<unsigned char>& vchSig)
168 {
169 // -1 = error, 0 = bad sig, 1 = good
170 if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
171 return false;
172 return true;
173 }
174
175 static bool Sign(const CPrivKey& vchPrivKey, uint256 hash, vector<unsigned char>& vchSig)
176 {
177 CKey key;
178 if (!key.SetPrivKey(vchPrivKey))
179 return false;
180 return key.Sign(hash, vchSig);
181 }
182
183 static bool Verify(const vector<unsigned char>& vchPubKey, uint256 hash, const vector<unsigned char>& vchSig)
184 {
185 CKey key;
186 if (!key.SetPubKey(vchPubKey))
187 return false;
188 return key.Verify(hash, vchSig);
189 }
190};