88#include " seed.h"
99#include " wally_crypto.h"
1010#include " ur.h"
11+ #include " CborEncoder.h"
12+ #include " CborDecoder.h"
1113
1214namespace seed_internal {
1315
@@ -52,10 +54,11 @@ SSKRShareSeq * SSKRShareSeq::from_seed(Seed const * seed,
5254 sskr_group_descriptor group = { thresh, nshares };
5355 sskr_group_descriptor groups[] = { group };
5456
55- size_t bytes_in_each_share = 0 ;
5657 size_t buff_size = 1024 ;
5758 uint8_t buff[buff_size];
58-
59+
60+ size_t bytes_in_each_share;
61+
5962 size_t share_len = Seed::SIZE + METADATA_LENGTH_BYTES;
6063 int share_count = sskr_count_shards (group_threshold, groups, group_len);
6164
@@ -71,24 +74,25 @@ SSKRShareSeq * SSKRShareSeq::from_seed(Seed const * seed,
7174 buff_size,
7275 NULL ,
7376 randgen);
74- Serial.println (gen_share_count); Serial.println (share_count);
77+
78+ // currently we support only 29 words per share
79+ serial_assert (bytes_in_each_share == BYTES_PER_SHARE);
7580 serial_assert (gen_share_count == (int )share_count);
76- Serial.println (bytes_in_each_share); Serial.println (share_len);
7781 serial_assert (bytes_in_each_share == share_len);
7882
7983
8084 String strings[MAX_SHARES];
8185 String ur_strings[MAX_SHARES];
82- uint8_t v [buff_size];
86+ uint8_t shards_byte[MAX_SHARES] [buff_size];
8387 for (int i = 0 ; i < share_count; i++) {
8488 uint8_t * bytes = buff + (i * bytes_in_each_share);
85- memcpy (v , bytes, bytes_in_each_share);
89+ memcpy (shards_byte[i] , bytes, bytes_in_each_share);
8690
8791 CborDynamicOutput output;
8892 CborWriter writer (output);
8993
9094 writer.writeTag (309 );
91- writer.writeBytes (v , bytes_in_each_share);
95+ writer.writeBytes (shards_byte[i] , bytes_in_each_share);
9296
9397 // Encode cbor payload as bytewords
9498 char *payload_bytewords = bytewords_encode (bw_standard, output.getData (), output.getSize ());
@@ -108,32 +112,138 @@ SSKRShareSeq * SSKRShareSeq::from_seed(Seed const * seed,
108112 }
109113
110114 SSKRShareSeq * sskr = new SSKRShareSeq ();
115+ sskr->nshares = nshares;
116+ sskr->shares_len = thresh;
117+ sskr->bytes_in_each_share = bytes_in_each_share;
111118 sskr->shares_len = share_count;
112119 for (int i=0 ; i<share_count; i++) {
113- sskr->shares [i] = strings[i];
114- sskr->shares_ur [i] = ur_strings[i];
120+ sskr->shares_bytewords [i] = strings[i]; // bytewords format
121+ sskr->shares_ur [i] = ur_strings[i]; // ur format
122+ sskr->set_share (i, shards_byte[i], bytes_in_each_share); // byte format
115123 }
116124
117- // how many words per (bytewords encoded) share are there?
118- // count spaces. 1 space means 2 words, therefore start with 1 word
119- sskr->words_per_share = 1 ;
120- int pos = 0 ;
121- while (pos < strings[0 ].length ()) {
122- pos = strings[0 ].indexOf (" " , pos);
123- if (pos == -1 ) {
124- break ;
125- }
126- else {
127- sskr->words_per_share ++;
128- pos++;
129- }
130- }
131-
132125 return sskr;
133126}
134127
128+ size_t SSKRShareSeq::add_share (uint8_t const * share) {
129+ serial_assert (nshares < MAX_SHARES);
130+ size_t sharesz = sizeof (uint8_t ) * BYTES_PER_SHARE;
131+ shares[nshares] = (uint8_t *) malloc (sharesz);
132+ memcpy (shares[nshares], share, sharesz);
133+ return nshares++;
134+ }
135+
135136String SSKRShareSeq::get_share_word (int sharendx, int wndx) {
136- return get_word_from_sentence (shares[sharendx], ' ' , wndx);
137+ return get_word_from_sentence (shares_bytewords[sharendx], ' ' , wndx);
138+ }
139+
140+ uint8_t const * SSKRShareSeq::get_share (size_t ndx) const {
141+ serial_assert (ndx < nshares);
142+ return shares[ndx];
143+ }
144+
145+ void SSKRShareSeq::set_share (size_t ndx, uint8_t const * share, size_t len) {
146+ Serial.println (" ** **" );
147+ Serial.println (ndx); Serial.println (nshares);
148+ serial_assert (ndx < nshares);
149+ if (shares[ndx])
150+ free (shares[ndx]);
151+ size_t sharesz = sizeof (uint8_t ) * len;
152+ shares[ndx] = (uint8_t *) malloc (sharesz);
153+ memcpy (shares[ndx], share, sharesz);
154+ }
155+
156+ String SSKRShareSeq::get_share_strings (size_t ndx) const {
157+ serial_assert (ndx < nshares);
158+ return shares_bytewords[ndx];
159+ }
160+
161+ Seed * SSKRShareSeq::restore_seed () const {
162+ uint8_t seed_data[Seed::SIZE];
163+
164+ Serial.println (" restore seed" );
165+ Serial.println (bytes_in_each_share);
166+ Serial.println (nshares);
167+
168+ last_rv = sskr_combine (const_cast <const uint8_t **>(shares),
169+ bytes_in_each_share,
170+ nshares,
171+ seed_data,
172+ sizeof (seed_data));
173+ Serial.println (last_rv);
174+ return last_rv < 0 ? NULL : new Seed (seed_data, sizeof (seed_data));
175+ }
176+
177+ class CborListen : public CborListener {
178+ public:
179+ void OnInteger (int32_t value){ };
180+ void OnBytes (unsigned char *data, unsigned int size) {Serial.println (" bytes" ); memcpy (bytes, data, size); len = size;};
181+ void OnString (String &str) {};
182+ void OnArray (unsigned int size) {};
183+ void OnMap (unsigned int size) {};
184+ void OnTag (uint32_t tag) { tag_ = tag; };
185+ void OnSpecial (uint32_t code) {Serial.println (" tag" );};
186+ void OnError (const char *error) {Serial.println (" error" );};
187+
188+ // we are gonna collect the tag and bytes
189+ uint32_t tag_;
190+ uint8_t bytes[200 ];
191+ size_t len;
192+ };
193+
194+ bool SSKRShareSeq::get_share_from_ur (String bytewords, size_t sskr_shard_indx) {
195+ uint8_t * decoded = NULL ;
196+ size_t decoded_len;
197+
198+ bool ret = bytewords_decode (bw_standard, bytewords.c_str (), &decoded, &decoded_len);
199+ if (ret == false ) {
200+ if (decoded)
201+ free (decoded);
202+ return ret;
203+ }
204+
205+ CborInput input (decoded, decoded_len);
206+ CborReader reader (input);
207+ CborListen listener;
208+ reader.SetListener (listener);
209+ reader.Run ();
210+
211+ // https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-011-sskr.md
212+ if (listener.tag_ != 309 )
213+ return false ;
214+
215+ free (decoded);
216+
217+ if (sskr_shard_indx >= nshares) {
218+ // init a new share
219+ uint8_t empty_share[SSKRShareSeq::BYTES_PER_SHARE] = {0 };
220+ add_share (empty_share);
221+ }
222+
223+ set_share (sskr_shard_indx, listener.bytes , listener.len );
224+ bytes_in_each_share = listener.len ;
225+
226+ return true ;
227+ }
228+
229+ void SSKRShareSeq::del_share (size_t ndx) {
230+ serial_assert (ndx < nshares);
231+ if (shares[ndx])
232+ free (shares[ndx]);
233+ // Compact any created gap.
234+ for (size_t ii = ndx; ii < nshares-1 ; ++ii)
235+ shares[ii] = shares[ii+1 ];
236+ nshares -= 1 ;
237+ }
238+
239+
240+ String bytewords_get_word (uint8_t index) {
241+ // FIXME bytewords are currently not exposed in the bytewords library. Once exposed, replace this function
242+ char word[5 ] = {0 };
243+ static const char* bytewords = "ableacidalsoapexaquaarchatomauntawayaxisbackbaldbarnbeltbetabiasbluebodybragbrewbulbbuzzcalmcashcatschefcityclawcodecolacookcostcruxcurlcuspcyandarkdatadaysdelidicedietdoordowndrawdropdrumdulldutyeacheasyechoedgeepicevenexamexiteyesfactfairfernfigsfilmfishfizzflapflewfluxfoxyfreefrogfuelfundgalagamegeargemsgiftgirlglowgoodgraygrimgurugushgyrohalfhanghardhawkheathelphighhillholyhopehornhutsicedideaidleinchinkyintoirisironitemjadejazzjoinjoltjowljudojugsjumpjunkjurykeepkenokeptkeyskickkilnkingkitekiwiknoblamblavalazyleaflegsliarlistlimplionlogoloudloveluaulucklungmainmanymathmazememomenumeowmildmintmissmonknailnavyneednewsnextnoonnotenumbobeyoboeomitonyxopenovalowlspaidpartpeckplaypluspoempoolposepuffpumapurrquadquizraceramprealredorichroadrockroofrubyruinrunsrustsafesagascarsetssilkskewslotsoapsolosongstubsurfswantacotasktaxitenttiedtimetinytoiltombtoystriptunatwinuglyundouniturgeuservastveryvetovialvibeviewvisavoidvowswallwandwarmwaspwavewaxywebswhatwhenwhizwolfworkyankyawnyellyogayurtzapszestzinczonezoomzero";
244+ memcpy (word, &bytewords[index * 4 ], 4 );
245+ word[4 ] = ' \0 ' ;
246+ return String (word);
137247}
138248
139249BIP39Seq * BIP39Seq::from_words (uint16_t * words) {
0 commit comments