]> Git Repo - VerusCoin.git/blob - src/pubkey.cpp
Merge pull request #128 from miketout/dev
[VerusCoin.git] / src / pubkey.cpp
1 // Copyright (c) 2009-2014 The Bitcoin Core developers
2 // Copyright (c) 2017 The Zcash developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "pubkey.h"
7
8 #include <secp256k1.h>
9 #include <secp256k1_recovery.h>
10
11 namespace
12 {
13 /* Global secp256k1_context object used for verification. */
14 secp256k1_context* secp256k1_context_verify = NULL;
15 }
16
17
18 bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
19     if (!IsValid())
20         return false;
21     secp256k1_pubkey pubkey;
22     secp256k1_ecdsa_signature sig;
23     if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
24         return false;
25     }
26     if (vchSig.size() == 0) {
27         return false;
28     }
29     /* Zcash, unlike Bitcoin, has always enforced strict DER signatures. */
30     if (!secp256k1_ecdsa_signature_parse_der(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
31         return false;
32     }
33     /* libsecp256k1's ECDSA verification requires lower-S signatures, which have
34      * not historically been enforced in Bitcoin or Zcash, so normalize them first. */
35     secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, &sig, &sig);
36     return secp256k1_ecdsa_verify(secp256k1_context_verify, &sig, hash.begin(), &pubkey);
37 }
38
39 bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
40     if (vchSig.size() != COMPACT_SIGNATURE_SIZE)
41         return false;
42     int recid = (vchSig[0] - 27) & 3;
43     bool fComp = ((vchSig[0] - 27) & 4) != 0;
44     secp256k1_pubkey pubkey;
45     secp256k1_ecdsa_recoverable_signature sig;
46     if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_verify, &sig, &vchSig[1], recid)) {
47         return false;
48     }
49     if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, hash.begin())) {
50         return false;
51     }
52     unsigned char pub[PUBLIC_KEY_SIZE];
53     size_t publen = PUBLIC_KEY_SIZE;
54     secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
55     Set(pub, pub + publen);
56     return true;
57 }
58
59 bool CPubKey::IsFullyValid() const {
60     if (!IsValid())
61         return false;
62     secp256k1_pubkey pubkey;
63     return secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size());
64 }
65
66 bool CPubKey::Decompress() {
67     if (!IsValid())
68         return false;
69     secp256k1_pubkey pubkey;
70     if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
71         return false;
72     }
73     unsigned char pub[PUBLIC_KEY_SIZE];
74     size_t publen = PUBLIC_KEY_SIZE;
75     secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
76     Set(pub, pub + publen);
77     return true;
78 }
79
80 bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const {
81     assert(IsValid());
82     assert((nChild >> 31) == 0);
83     assert(size() == COMPRESSED_PUBLIC_KEY_SIZE);
84     unsigned char out[64];
85     BIP32Hash(cc, nChild, *begin(), begin()+1, out);
86     memcpy(ccChild.begin(), out+32, 32);
87     secp256k1_pubkey pubkey;
88     if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
89         return false;
90     }
91     if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) {
92         return false;
93     }
94     unsigned char pub[COMPRESSED_PUBLIC_KEY_SIZE];
95     size_t publen = COMPRESSED_PUBLIC_KEY_SIZE;
96     secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED);
97     pubkeyChild.Set(pub, pub + publen);
98     return true;
99 }
100
101 void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const {
102     code[0] = nDepth;
103     memcpy(code+1, vchFingerprint, 4);
104     code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
105     code[7] = (nChild >>  8) & 0xFF; code[8] = (nChild >>  0) & 0xFF;
106     memcpy(code+9, chaincode.begin(), 32);
107     assert(pubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE);
108     memcpy(code+41, pubkey.begin(), CPubKey::COMPRESSED_PUBLIC_KEY_SIZE);
109 }
110
111 void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {
112     nDepth = code[0];
113     memcpy(vchFingerprint, code+1, 4);
114     nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
115     memcpy(chaincode.begin(), code+9, 32);
116     pubkey.Set(code+41, code+BIP32_EXTKEY_SIZE);
117 }
118
119 bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
120     out.nDepth = nDepth + 1;
121     CKeyID id = pubkey.GetID();
122     memcpy(&out.vchFingerprint[0], &id, 4);
123     out.nChild = nChild;
124     return pubkey.Derive(out.pubkey, out.chaincode, nChild, chaincode);
125 }
126
127 /* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
128     secp256k1_ecdsa_signature sig;
129
130     /* Zcash, unlike Bitcoin, has always enforced strict DER signatures. */
131     if (!secp256k1_ecdsa_signature_parse_der(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
132         return false;
133     }
134     return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, NULL, &sig));
135 }
136
137 /* static */ int ECCVerifyHandle::refcount = 0;
138
139 ECCVerifyHandle::ECCVerifyHandle()
140 {
141     if (refcount == 0) {
142         assert(secp256k1_context_verify == NULL);
143         secp256k1_context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
144         assert(secp256k1_context_verify != NULL);
145     }
146     refcount++;
147 }
148
149 ECCVerifyHandle::~ECCVerifyHandle()
150 {
151     refcount--;
152     if (refcount == 0) {
153         assert(secp256k1_context_verify != NULL);
154         secp256k1_context_destroy(secp256k1_context_verify);
155         secp256k1_context_verify = NULL;
156     }
157 }
This page took 0.031899 seconds and 4 git commands to generate.