1
// Copyright © 2017-2020 Trust Wallet.
2
//
3
// This file is part of Trust. The full Trust copyright notice, including
4
// terms governing use, modification, and redistribution, is contained in the
5
// file LICENSE at the root of the source code distribution tree.
6

7
#include "PrivateKey.h"
8

9
#include "PublicKey.h"
10

11
#include <TrezorCrypto/bignum.h>
12
#include <TrezorCrypto/ecdsa.h>
13
#include <TrezorCrypto/ed25519-donna/ed25519-blake2b.h>
14
#include <TrezorCrypto/memzero.h>
15
#include <TrezorCrypto/nist256p1.h>
16
#include <TrezorCrypto/rand.h>
17
#include <TrezorCrypto/schnorr.h>
18
#include <TrezorCrypto/secp256k1.h>
19
#include <TrezorCrypto/sodium/keypair.h>
20

21
using namespace TW;
22

23 1
bool PrivateKey::isValid(const Data& data) {
24
    // Check length.  Extended key needs 3*32 bytes.
25 1
    if (data.size() != size && data.size() != extendedSize) {
26 1
        return false;
27
    }
28

29
    // Check for zero address
30 1
    for (size_t i = 0; i < size; ++i) {
31 1
        if (data[i] != 0) {
32 1
            return true;
33
        }
34
    }
35

36 1
    return false;
37
}
38

39 1
bool PrivateKey::isValid(const Data& data, TWCurve curve)
40
{
41
    // check size
42 1
    bool valid = isValid(data);
43 1
    if (!valid) {
44 1
        return false;
45
    }
46

47 1
    const ecdsa_curve *ec_curve = nullptr;
48 1
    switch (curve)
49
    {
50
    case TWCurveSECP256k1:
51 1
        ec_curve = &secp256k1;
52 1
        break;
53
    case TWCurveNIST256p1:
54 1
        ec_curve = &nist256p1;
55 1
        break;
56
    case TWCurveED25519:
57
    case TWCurveED25519Blake2bNano:
58
    case TWCurveED25519Extended:
59
    case TWCurveCurve25519:
60
    case TWCurveNone:
61
    default:
62 1
        break;
63
    }
64

65 1
    if (ec_curve != nullptr) {
66
        bignum256 k;
67 1
        bn_read_be(data.data(), &k);
68 1
        if (!bn_is_less(&k, &ec_curve->order)) {
69 1
            memzero(&k, sizeof(k));
70 1
            return false;
71
        };
72
    }
73

74 1
    return true;
75
}
76

77 1
PrivateKey::PrivateKey(const Data& data) {
78 1
    if (!isValid(data)) {
79 1
        throw std::invalid_argument("Invalid private key data");
80
    }
81 1
    if (data.size() == extendedSize) {
82
        // special extended case
83 1
        *this = PrivateKey(
84 1
            TW::data(data.data(), 32),
85 1
            TW::data(data.data() + 32, 32),
86 1
            TW::data(data.data() + 64, 32));
87 1
    } else {
88
        // default case
89 1
        bytes = data;
90
    }
91
}
92

93 1
PrivateKey::PrivateKey(const Data& data, const Data& ext, const Data& chainCode) {
94 1
    if (!isValid(data) || !isValid(ext) || !isValid(chainCode)) {
95 1
        throw std::invalid_argument("Invalid private key or extended key data");
96
    }
97 1
    bytes = data;
98 1
    extensionBytes = ext;
99 1
    chainCodeBytes = chainCode;
100
}
101

102 1
PublicKey PrivateKey::getPublicKey(TWPublicKeyType type) const {
103 1
    Data result;
104 1
    switch (type) {
105
    case TWPublicKeyTypeSECP256k1:
106 1
        result.resize(PublicKey::secp256k1Size);
107 1
        ecdsa_get_public_key33(&secp256k1, bytes.data(), result.data());
108 1
        break;
109
    case TWPublicKeyTypeSECP256k1Extended:
110 1
        result.resize(PublicKey::secp256k1ExtendedSize);
111 1
        ecdsa_get_public_key65(&secp256k1, bytes.data(), result.data());
112 1
        break;
113
    case TWPublicKeyTypeNIST256p1:
114 1
        result.resize(PublicKey::secp256k1Size);
115 1
        ecdsa_get_public_key33(&nist256p1, bytes.data(), result.data());
116 1
        break;
117
    case TWPublicKeyTypeNIST256p1Extended:
118 1
        result.resize(PublicKey::secp256k1ExtendedSize);
119 1
        ecdsa_get_public_key65(&nist256p1, bytes.data(), result.data());
120 1
        break;
121
    case TWPublicKeyTypeED25519:
122 1
        result.resize(PublicKey::ed25519Size);
123 1
        ed25519_publickey(bytes.data(), result.data());
124 1
        break;
125
    case TWPublicKeyTypeED25519Blake2b:
126 1
        result.resize(PublicKey::ed25519Size);
127 1
        ed25519_publickey_blake2b(bytes.data(), result.data());
128 1
        break;
129
    case TWPublicKeyTypeED25519Extended:
130
        // must be extended key
131 1
        if (bytes.size() + extensionBytes.size() + chainCodeBytes.size() != extendedSize) {
132 1
            throw std::invalid_argument("Invalid extended key");
133
        }
134 1
        result.resize(PublicKey::ed25519ExtendedSize);
135 1
        ed25519_publickey_ext(bytes.data(), extensionBytes.data(), result.data());
136
        // append chainCode to the end of the public key
137 1
        std::copy(chainCodeBytes.begin(), chainCodeBytes.end(), result.begin() + 32);
138 1
        break;
139
    case TWPublicKeyTypeCURVE25519:
140 1
        result.resize(PublicKey::ed25519Size);
141 1
        PublicKey ed25519PublicKey = getPublicKey(TWPublicKeyTypeED25519);
142 1
        ed25519_pk_to_curve25519(result.data(), ed25519PublicKey.bytes.data());
143
        break;
144
    }
145 1
    return PublicKey(result, type);
146
}
147

148 1
Data PrivateKey::sign(const Data& digest, TWCurve curve) const {
149 1
    Data result;
150 1
    bool success = false;
151 1
    switch (curve) {
152
    case TWCurveSECP256k1: {
153 1
        result.resize(65);
154 1
        success = ecdsa_sign_digest(&secp256k1, bytes.data(), digest.data(), result.data(),
155 1
                                    result.data() + 64, nullptr) == 0;
156 1
    } break;
157
    case TWCurveED25519: {
158 1
        result.resize(64);
159 1
        const auto publicKey = getPublicKey(TWPublicKeyTypeED25519);
160 1
        ed25519_sign(digest.data(), digest.size(), bytes.data(), publicKey.bytes.data(), result.data());
161 1
        success = true;
162 1
    } break;
163
    case TWCurveED25519Blake2bNano: {
164 1
        result.resize(64);
165 1
        const auto publicKey = getPublicKey(TWPublicKeyTypeED25519Blake2b);
166 1
        ed25519_sign_blake2b(digest.data(), digest.size(), bytes.data(),
167 1
                             publicKey.bytes.data(), result.data());
168 1
        success = true;
169 1
    } break;
170
    case TWCurveED25519Extended: {
171 1
        result.resize(64);
172 1
        const auto publicKey = getPublicKey(TWPublicKeyTypeED25519Extended);
173 1
        ed25519_sign_ext(digest.data(), digest.size(), bytes.data(), extensionBytes.data(), publicKey.bytes.data(), result.data());
174 1
        success = true;
175 1
    } break;
176
    case TWCurveCurve25519: {
177 1
        result.resize(64);
178 1
        const auto publicKey = getPublicKey(TWPublicKeyTypeED25519);
179 1
        ed25519_sign(digest.data(), digest.size(), bytes.data(), publicKey.bytes.data(),
180 1
                     result.data());
181 1
        const auto sign_bit = publicKey.bytes[31] & 0x80;
182 1
        result[63] = result[63] & 127;
183 1
        result[63] |= sign_bit;
184 1
        success = true;
185 1
    } break;
186
    case TWCurveNIST256p1: {
187 1
        result.resize(65);
188 1
        success = ecdsa_sign_digest(&nist256p1, bytes.data(), digest.data(), result.data(),
189 1
                                    result.data() + 64, nullptr) == 0;
190 1
    } break;
191
    case TWCurveNone:
192
    default: 
193 0
        break;
194
    }
195

196 1
    if (!success) {
197 0
        return {};
198
    }
199 1
    return result;
200
}
201

202 1
Data PrivateKey::sign(const Data& digest, TWCurve curve, int(*canonicalChecker)(uint8_t by, uint8_t sig[64])) const {
203 1
    Data result;
204 1
    bool success = false;
205 1
    switch (curve) {
206
    case TWCurveSECP256k1: {
207 1
        result.resize(65);
208 1
        success = ecdsa_sign_digest(&secp256k1, bytes.data(), digest.data(), result.data() + 1,
209 1
                                    result.data(), canonicalChecker) == 0;
210 1
    } break;
211
    case TWCurveED25519: // not supported
212
    case TWCurveED25519Blake2bNano: // not supported
213
    case TWCurveED25519Extended: // not supported
214
    case TWCurveCurve25519:         // not supported
215 0
        break;
216
    case TWCurveNIST256p1: {
217 1
        result.resize(65);
218 1
        success = ecdsa_sign_digest(&nist256p1, bytes.data(), digest.data(), result.data() + 1,
219 1
                                    result.data(), canonicalChecker) == 0;
220 1
    } break;
221
    case TWCurveNone:
222
    default:
223 0
        break;
224
    }
225

226 1
    if (!success) {
227 0
        return {};
228
    }
229

230
    // graphene adds 31 to the recovery id
231 1
    result[0] += 31;
232 1
    return result;
233
}
234

235 1
Data PrivateKey::signAsDER(const Data& digest, TWCurve curve) const {
236 1
    Data sig(64);
237 1
    bool success =
238 1
        ecdsa_sign_digest(&secp256k1, bytes.data(), digest.data(), sig.data(), nullptr, nullptr) == 0;
239 1
    if (!success) {
240 0
        return {};
241
    }
242

243 1
    Data resultBytes(72);
244 1
    size_t size = ecdsa_sig_to_der(sig.data(), resultBytes.data());
245

246 1
    auto result = Data{};
247 1
    std::copy(resultBytes.begin(), resultBytes.begin() + size, std::back_inserter(result));
248 1
    return result;
249
}
250

251 1
Data PrivateKey::signSchnorr(const Data& message, TWCurve curve) const {
252 1
    bool success = false;
253 1
    Data sig(64);
254 1
    switch (curve) {
255
    case TWCurveSECP256k1: {
256 1
        success = zil_schnorr_sign(&secp256k1, bytes.data(), message.data(), static_cast<uint32_t>(message.size()), sig.data()) == 0;
257 1
    } break;
258

259
    case TWCurveNIST256p1:
260
    case TWCurveED25519:
261
    case TWCurveED25519Blake2bNano:
262
    case TWCurveED25519Extended:
263
    case TWCurveCurve25519:
264
    case TWCurveNone:
265
    default:
266
        // not support
267 1
        break;
268
    }
269

270 1
    if (!success) {
271 1
        return {};
272
    }
273 1
    return sig;
274
}
275

276 1
void PrivateKey::cleanup() {
277 1
    std::fill(bytes.begin(), bytes.end(), 0);
278 1
    std::fill(extensionBytes.begin(), extensionBytes.end(), 0);
279 1
    std::fill(chainCodeBytes.begin(), chainCodeBytes.end(), 0);
280
}

Read our documentation on viewing source code .

Loading