@@ -41,14 +41,27 @@ struct derived_t {
4141 unsigned char half2 [BIP38_DERIVED_KEY_LEN / 2 ];
4242};
4343
44+ struct bip38_sublayout_t {
45+ uint32_t hash ;
46+ unsigned char half1 [AES_BLOCK_LEN ];
47+ unsigned char half2 [AES_BLOCK_LEN ];
48+ };
49+
50+ struct bip38_sublayout_swapped_t {
51+ unsigned char half1 [AES_BLOCK_LEN ];
52+ unsigned char half2 [AES_BLOCK_LEN ];
53+ uint32_t hash ;
54+ };
55+
4456struct bip38_layout_t {
4557 unsigned char pad1 ;
4658 unsigned char prefix ;
4759 unsigned char ec_type ;
4860 unsigned char flags ;
49- uint32_t hash ;
50- unsigned char half1 [AES_BLOCK_LEN ];
51- unsigned char half2 [AES_BLOCK_LEN ];
61+ union {
62+ struct bip38_sublayout_t normal ;
63+ struct bip38_sublayout_swapped_t swapped ;
64+ } u ;
5265 unsigned char decode_hash [BASE58_CHECKSUM_LEN ];
5366};
5467
@@ -58,6 +71,8 @@ static void assert_bip38_assumptions(void)
5871{
5972 /* derived_t/bip38_layout_t must be contiguous */
6073 BUILD_ASSERT (sizeof (struct derived_t ) == BIP38_DERIVED_KEY_LEN );
74+ /* swapped and normal sublayouts must be the same size */
75+ BUILD_ASSERT (sizeof (struct bip38_sublayout_t ) == sizeof (struct bip38_sublayout_swapped_t ));
6176 /* 44 -> pad1 + 39 + BASE58_CHECKSUM_LEN */
6277 BUILD_ASSERT (sizeof (struct bip38_layout_t ) == 44u );
6378 BUILD_ASSERT ((sizeof (struct bip38_layout_t ) - BASE58_CHECKSUM_LEN - 1 ) ==
@@ -140,35 +155,39 @@ int bip38_raw_from_private_key(const unsigned char *bytes, size_t bytes_len,
140155 goto finish ;
141156
142157 if (flags & BIP38_KEY_RAW_MODE )
143- buf .hash = base58_get_checksum (bytes , bytes_len );
158+ buf .u . normal . hash = base58_get_checksum (bytes , bytes_len );
144159 else {
145160 const unsigned char network = flags & 0xff ;
146161 char * addr58 = NULL ;
147162 if ((ret = address_from_private_key (bytes , bytes_len ,
148163 network , compressed , & addr58 )))
149164 goto finish ;
150165
151- buf .hash = base58_get_checksum ((unsigned char * )addr58 , strlen (addr58 ));
166+ buf .u . normal . hash = base58_get_checksum ((unsigned char * )addr58 , strlen (addr58 ));
152167 wally_free_string (addr58 );
153168 }
154169
155170 ret = wally_scrypt (pass , pass_len ,
156- (unsigned char * )& buf .hash , sizeof (buf .hash ), 16384 , 8 , 8 ,
171+ (unsigned char * )& buf .u .normal .hash , sizeof (buf .u .normal .hash ),
172+ 16384 , 8 , 8 ,
157173 (unsigned char * )& derived , sizeof (derived ));
158174 if (ret )
159175 goto finish ;
160176
161177 buf .prefix = BIP38_PREFIX ;
162178 buf .ec_type = BIP38_NO_ECMUL ; /* FIXME: EC-Multiply support */
163179 buf .flags = BIP38_FLAG_DEFAULT | (compressed ? BIP38_FLAG_COMPRESSED : 0 );
164- aes_enc_impl (bytes + 0 , derived .half1_lo , derived .half2 , buf .half1 );
165- aes_enc_impl (bytes + 16 , derived .half1_hi , derived .half2 , buf .half2 );
180+ aes_enc_impl (bytes + 0 , derived .half1_lo , derived .half2 , buf .u . normal . half1 );
181+ aes_enc_impl (bytes + 16 , derived .half1_hi , derived .half2 , buf .u . normal . half2 );
166182
167183 if (flags & BIP38_KEY_SWAP_ORDER ) {
168- /* Shuffle hash from the beginning to the end */
169- uint32_t tmp = buf .hash ;
170- memmove (& buf .hash , buf .half1 , AES_BLOCK_LEN * 2 );
171- memcpy (buf .decode_hash - sizeof (uint32_t ), & tmp , sizeof (uint32_t ));
184+ /* Shuffle hash from the beginning to the end (normal->swapped) */
185+ struct bip38_sublayout_swapped_t swapped ;
186+ swapped .hash = buf .u .normal .hash ;
187+ memcpy (swapped .half1 , buf .u .normal .half1 , sizeof (buf .u .normal .half1 ));
188+ memcpy (swapped .half2 , buf .u .normal .half2 , sizeof (buf .u .normal .half2 ));
189+ memcpy (& buf .u .swapped , & swapped , sizeof (swapped ));
190+ wally_clear (& swapped , sizeof (swapped ));
172191 }
173192
174193 memcpy (bytes_out , & buf .prefix , BIP38_SERIALIZED_LEN );
@@ -250,11 +269,13 @@ static int to_private_key(const char *bip38,
250269 }
251270
252271 if (flags & BIP38_KEY_SWAP_ORDER ) {
253- /* Shuffle hash from the end to the beginning */
254- uint32_t tmp ;
255- memcpy (& tmp , buf .decode_hash - sizeof (uint32_t ), sizeof (uint32_t ));
256- memmove (buf .half1 , & buf .hash , AES_BLOCK_LEN * 2 );
257- buf .hash = tmp ;
272+ /* Shuffle hash from the end to the beginning (swapped->normal) */
273+ struct bip38_sublayout_t normal ;
274+ normal .hash = buf .u .swapped .hash ;
275+ memcpy (normal .half1 , buf .u .swapped .half1 , sizeof (buf .u .swapped .half1 ));
276+ memcpy (normal .half2 , buf .u .swapped .half2 , sizeof (buf .u .swapped .half2 ));
277+ memcpy (& buf .u .normal , & normal , sizeof (normal ));
278+ wally_clear (& normal , sizeof (normal ));
258279 }
259280
260281 if (buf .prefix != BIP38_PREFIX ||
@@ -272,23 +293,23 @@ static int to_private_key(const char *bip38,
272293 }
273294
274295 if ((ret = wally_scrypt (pass , pass_len ,
275- (unsigned char * )& buf .hash , sizeof (buf .hash ), 16384 , 8 , 8 ,
296+ (unsigned char * )& buf .u . normal . hash , sizeof (buf . u . normal .hash ), 16384 , 8 , 8 ,
276297 (unsigned char * )& derived , sizeof (derived ))))
277298 goto finish ;
278299
279- aes_dec_impl (buf .half1 , derived .half1_lo , derived .half2 , bytes_out + 0 );
280- aes_dec_impl (buf .half2 , derived .half1_hi , derived .half2 , bytes_out + 16 );
300+ aes_dec_impl (buf .u . normal . half1 , derived .half1_lo , derived .half2 , bytes_out + 0 );
301+ aes_dec_impl (buf .u . normal . half2 , derived .half1_hi , derived .half2 , bytes_out + 16 );
281302
282303 if (flags & BIP38_KEY_RAW_MODE ) {
283- if (buf .hash != base58_get_checksum (bytes_out , len ))
304+ if (buf .u . normal . hash != base58_get_checksum (bytes_out , len ))
284305 ret = WALLY_EINVAL ;
285306 } else {
286307 const unsigned char network = flags & 0xff ;
287308 char * addr58 = NULL ;
288309 ret = address_from_private_key (bytes_out , len , network ,
289310 buf .flags & BIP38_FLAG_COMPRESSED , & addr58 );
290311 if (!ret &&
291- buf .hash != base58_get_checksum ((unsigned char * )addr58 , strlen (addr58 )))
312+ buf .u . normal . hash != base58_get_checksum ((unsigned char * )addr58 , strlen (addr58 )))
292313 ret = WALLY_EINVAL ;
293314 wally_free_string (addr58 );
294315 }
0 commit comments