forked from breadwallet/breadwallet-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBRCryptoKey.c
More file actions
354 lines (277 loc) · 11 KB
/
Copy pathBRCryptoKey.c
File metadata and controls
354 lines (277 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
//
// BRCryptoKey.c
// BRCore
//
// Created by Ed Gamble on 7/30/19.
// Copyright © 2019 Breadwinner AG. All rights reserved.
//
// See the LICENSE file at the project root for license information.
// See the CONTRIBUTORS file at the project root for a list of contributors.
#include <assert.h>
#include <stdlib.h>
#include "BRCryptoKey.h"
#include "BRKey.h"
#include "BRBIP39Mnemonic.h"
#include "BRBIP38Key.h"
#include "BRBIP32Sequence.h"
#include "BRKeyECIES.h"
#include "ethereum/util/BRUtil.h"
// We create an arbitary BRAddressParams - disconnected from any know BITCOIN, etc address params.
// We do this until we know how the Key is used. Right now, the only accessors are to get the
// serialized form of the Key. Is somebody expecting a particular encoding? Is somebody expectring
// to decode the serialization and then pass it to some other 'string-y' interface? Until we know
// what those other interfaces require, we don't know appropriate address parameters.
//
// Our serialization/deserialization works because we use the same address params. If the above
// questions are answered, the various cryptoKeyCreate*() functions will need to specify their
// address params AND (AND AND) the serialization will need to WRITE OUT the specific params.
//
// Resulting Base58 Prefix:
// 6: Uncompressed
// T: Compressed
//
#define CRYPTO_PREFIX_OFFET 0x30
#define CRYPTO_ADDRESS_PARAMS ((BRAddressParams) { \
CRYPTO_PREFIX_OFFET + BITCOIN_PUBKEY_PREFIX, \
CRYPTO_PREFIX_OFFET + BITCOIN_SCRIPT_PREFIX, \
CRYPTO_PREFIX_OFFET + BITCOIN_PRIVKEY_PREFIX, \
"cry" \
})
struct BRCryptoKeyRecord {
BRKey core;
BRAddressParams coreAddressParams;
BRCryptoRef ref;
};
IMPLEMENT_CRYPTO_GIVE_TAKE (BRCryptoKey, cryptoKey);
static BRCryptoKey
cryptoKeyCreateInternal (BRKey core, BRAddressParams params) {
BRCryptoKey key = calloc (1, sizeof (struct BRCryptoKeyRecord));
key->core = core;
key->coreAddressParams = params;
key->ref = CRYPTO_REF_ASSIGN(cryptoKeyRelease);
// clean up the key from the stack
BRKeyClean (&core);
return key;
}
static void
cryptoKeyRelease (BRCryptoKey key) {
BRKeyClean (&key->core);
free (key);
}
extern BRCryptoBoolean
cryptoKeyIsProtectedPrivate (const char *privateKey) {
return BRBIP38KeyIsValid (privateKey);
}
private_extern BRCryptoKey
cryptoKeyCreateFromKey (BRKey *key) {
return cryptoKeyCreateInternal (*key, CRYPTO_ADDRESS_PARAMS);
}
extern BRCryptoKey
cryptoKeyCreateFromSecret (BRCryptoSecret secret) {
BRKey core;
BRKeySetSecret (&core, (UInt256*) secret.data, 1);
BRCryptoKey result = cryptoKeyCreateInternal (core, CRYPTO_ADDRESS_PARAMS);
BRKeyClean(&core);
memset (secret.data, 0, sizeof(secret.data));
return result;
}
extern BRCryptoKey
cryptoKeyCreateFromPhraseWithWords (const char *phrase, const char *words[]) {
if (!BRBIP39PhraseIsValid (words, phrase)) return NULL;
UInt512 seed;
BRBIP39DeriveKey (seed.u8, phrase, NULL);
UInt256 *secret = (UInt256*) &seed;
BRKey core;
BRKeySetSecret(&core, secret, 1);
BRCryptoKey result = cryptoKeyCreateInternal(core, CRYPTO_ADDRESS_PARAMS);
BRKeyClean(&core);
seed = UINT512_ZERO;
return result;
}
static BRAddressParams
cryptoKeyFindAddressParams (const char *string) {
if (BRPrivKeyIsValid (BITCOIN_ADDRESS_PARAMS, string)) return BITCOIN_ADDRESS_PARAMS;
if (BRPrivKeyIsValid (BITCOIN_TEST_ADDRESS_PARAMS, string)) return BITCOIN_TEST_ADDRESS_PARAMS;
if (BRPrivKeyIsValid (CRYPTO_ADDRESS_PARAMS, string)) return CRYPTO_ADDRESS_PARAMS;
return EMPTY_ADDRESS_PARAMS;
}
extern BRCryptoKey
cryptoKeyCreateFromStringProtectedPrivate (const char *privateKey, const char * passphrase) {
if (!BRBIP38KeyIsValid (privateKey)) return NULL;
BRKey core;
BRCryptoKey result = (1 == BRKeySetBIP38Key(&core, privateKey, passphrase, BITCOIN_ADDRESS_PARAMS)
? cryptoKeyCreateInternal (core, BITCOIN_ADDRESS_PARAMS)
: (1 == BRKeySetBIP38Key(&core, privateKey, passphrase, BITCOIN_TEST_ADDRESS_PARAMS)
? cryptoKeyCreateInternal (core, BITCOIN_TEST_ADDRESS_PARAMS)
: (1 == BRKeySetBIP38Key(&core, privateKey, passphrase, CRYPTO_ADDRESS_PARAMS)
? cryptoKeyCreateInternal (core, CRYPTO_ADDRESS_PARAMS)
: NULL)));
BRKeyClean (&core);
return result;
}
extern BRCryptoKey
cryptoKeyCreateFromStringPrivate (const char *string) {
BRAddressParams params = cryptoKeyFindAddressParams(string);
BRKey core;
BRCryptoKey result = (1 == BRKeySetPrivKey (&core, params, string)
? cryptoKeyCreateInternal (core, params)
: NULL);
BRKeyClean (&core);
return result;
}
extern BRCryptoKey
cryptoKeyCreateFromStringPublic (const char *string) {
size_t targetLen = strlen (string) / 2;
uint8_t target [targetLen];
decodeHex(target, targetLen, string, strlen (string));
BRKey core;
BRCryptoKey result = (1 == BRKeySetPubKey (&core, target, targetLen)
? cryptoKeyCreateInternal (core, CRYPTO_ADDRESS_PARAMS)
: NULL);
// key doesn't need to be cleaned; just a silly public key
return result;
}
extern BRCryptoKey
cryptoKeyCreateForPigeon (BRCryptoKey privateKey, uint8_t *nonce, size_t nonceCount) {
BRKey pairingKey;
BRKeyPigeonPairingKey (&privateKey->core, &pairingKey, nonce, nonceCount);
BRCryptoKey result = cryptoKeyCreateInternal (pairingKey, CRYPTO_ADDRESS_PARAMS);
BRKeyClean (&pairingKey);
return result;
}
extern BRCryptoKey
cryptoKeyCreateForBIP32ApiAuth (const char *phrase, const char *words[]) {
if (!BRBIP39PhraseIsValid (words, phrase)) return NULL;
UInt512 seed;
BRBIP39DeriveKey (seed.u8, phrase, NULL);
BRKey core;
BRBIP32APIAuthKey (&core, &seed, sizeof (UInt512));
// BRBIP39DeriveKey(&seed, phrase, nil)
// BRBIP32APIAuthKey(&key, &seed, MemoryLayout<UInt512>.size)
// seed = UInt512() // clear seed
// let pkLen = BRKeyPrivKey(&key, nil, 0)
// var pkData = CFDataCreateMutable(secureAllocator, pkLen) as Data
// pkData.count = pkLen
// guard pkData.withUnsafeMutableBytes({ BRKeyPrivKey(&key, $0.baseAddress?.assumingMemoryBound(to: Int8.self), pkLen) }) == pkLen else { return nil }
// key.clean()
BRCryptoKey result = cryptoKeyCreateInternal(core, CRYPTO_ADDRESS_PARAMS);
BRKeyClean (&core);
seed = UINT512_ZERO;
return result;
}
extern BRCryptoKey
cryptoKeyCreateForBIP32BitID (const char *phrase, int index, const char *uri, const char *words[]) {
if (!BRBIP39PhraseIsValid (words, phrase)) return NULL;
UInt512 seed;
BRBIP39DeriveKey (seed.u8, phrase, NULL);
BRKey core;
BRBIP32BitIDKey (&core, &seed, sizeof(UInt512), index, uri);
BRCryptoKey result = cryptoKeyCreateInternal(core, CRYPTO_ADDRESS_PARAMS);
BRKeyClean (&core);
seed = UINT512_ZERO;
return result;
}
#if 0
typedef enum {
SERIALIZE_PUBLIC_IDENTIFIER = 1,
SERIALIZE_PRIVATE_IDENTIFIER = 2
} BRCryptoKeySerializeIdentifier;
extern BRCryptoKey
cryptoKeyCreateFromSerializationPublic (uint8_t *data, size_t dataCount) {
if (dataCount < 1) return NULL;
if (SERIALIZE_PUBLIC_IDENTIFIER != (BRCryptoKeySerializeIdentifier) data[0]) return NULL;
BRKey core;
return (1 == BRKeySetPubKey (&core, &data[1], dataCount - 1)
? cryptoKeyCreateInternal (core, CRYPTO_ADDRESS_PARAMS)
: NULL);
}
extern size_t
cryptoKeySerializePublic (BRCryptoKey key, /* ... */ uint8_t *data, size_t dataCount) {
size_t publicKeySize = BRKeyPubKey (&key->core, NULL, 0);
size_t serializeSize = 1 + publicKeySize;
if (NULL == data) return serializeSize;
if (dataCount < serializeSize) return 0;
data[0] = SERIALIZE_PUBLIC_IDENTIFIER;
BRKeyPubKey (&key->core, &data[1], dataCount);
return dataCount;
}
extern BRCryptoKey
cryptoKeyCreateFromSerializationPrivate (uint8_t *data, size_t dataCount) {
if (dataCount < 1) return NULL;
if (SERIALIZE_PRIVATE_IDENTIFIER != (BRCryptoKeySerializeIdentifier) data[0]) return NULL;
// Get the AddressParms
BRAddressParams addressParams = CRYPTO_ADDRESS_PARAMS;
BRKey core;
// Make a string
char privKey[dataCount];
memcpy (privKey, &data[1], dataCount - 1);
privKey[dataCount - 1] = 0;
if (!BRPrivKeyIsValid (addressParams, privKey)) return NULL;
return (1 == BRKeySetPrivKey (&core, addressParams, privKey)
? cryptoKeyCreateInternal (core, addressParams)
: NULL);
}
extern size_t
cryptoKeySerializePrivate (BRCryptoKey key, /* ... */ uint8_t *data, size_t dataCount) {
// If we encode the BRAddressParams, we'll need to increate the required dataCount
size_t privateKeySize = BRKeyPrivKey (&key->core, NULL, 0, key->coreAddressParams);
size_t serializeSize = 1 + privateKeySize;
if (NULL == data) return serializeSize;
if (dataCount < serializeSize) return 0;
data[0] = SERIALIZE_PRIVATE_IDENTIFIER;
// Make a string
char privKey[dataCount]; // includes 1 for '\0'
memcpy (privKey, &data[1], dataCount - 1);
privKey[dataCount - 1] = 0;
return (0 != BRKeyPrivKey (&key->core, privKey, dataCount - 1, key->coreAddressParams)
? dataCount
: 0);
}
#endif
extern int
cryptoKeyHasSecret (BRCryptoKey key) {
UInt256 zero = UINT256_ZERO;
return 0 != memcmp (key->core.secret.u8, zero.u8, sizeof (zero.u8));
}
extern char *
cryptoKeyEncodePrivate (BRCryptoKey key) {
size_t encodedLength = BRKeyPrivKey (&key->core, NULL, 0, key->coreAddressParams);
char *encoded = malloc (encodedLength + 1);
BRKeyPrivKey (&key->core, encoded, encodedLength, key->coreAddressParams);
encoded[encodedLength] = '\0';
return encoded;
}
extern char *
cryptoKeyEncodePublic (BRCryptoKey key) {
size_t encodedLength = BRKeyPubKey (&key->core, NULL, 0);
uint8_t encoded[encodedLength];
BRKeyPubKey(&key->core, encoded, encodedLength);
return encodeHexCreate (NULL, encoded, encodedLength);
}
extern BRCryptoSecret
cryptoKeyGetSecret (BRCryptoKey key) {
BRCryptoSecret secret;
memcpy (secret.data, key->core.secret.u8, sizeof (secret.data));
return secret;
}
extern int
cryptoKeySecretMatch (BRCryptoKey key1, BRCryptoKey key2) {
return 0 == memcmp (key1->core.secret.u8, key2->core.secret.u8, sizeof (key1->core.secret));
}
extern int
cryptoKeyPublicMatch (BRCryptoKey key1, BRCryptoKey key2) {
return 1 == BRKeyPubKeyMatch (&key1->core, &key2->core);
}
//extern size_t
//cryptoKeySign (BRCryptoKey key, void *sig, size_t sigLen, UInt256 md) {
// return BRKeySign (&key->core, sig, sigLen, md);
//}
extern BRKey *
cryptoKeyGetCore (BRCryptoKey key) {
return &key->core;
}
extern void
cryptoKeyProvidePublicKey (BRCryptoKey key, int useCompressed, int compressed) {
if (useCompressed) BRKeySetCompressed (&key->core, compressed);
BRKeyPubKey (&key->core, NULL, 0);
}