-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Comments:BIP 0038
Designed for single-key "paper wallets", which are not a good idea in general. --Luke Dashjr, 2016-12-23
I assume this is not meant as a general recommendation against "paper wallets", but rather paper wallets that consist of a single key? If so, is there an equivalent BIP (or discussion) on passphrase-protected HD paper wallets? --Jonathan Cross, 2017-01-17
The design may have been intended for paper wallets, although there is nothing inherently bad about either a paper wallet or encryption of a single key. I would agree that a "single-key" wallet is a bad idea from a privacy perspective, but there are other perfectly "good" scenarios for encryption of a single secret. The are however significant security problems with one aspect of BIP38. The issue is documented in detail here. --Eric Voskuil, 2017-01-21
Thank you Eric. It seems the security issues only relate to the Confirmation Code section, correct? Are there security issues with owner-created, single-use, BIP-38 encrypted key pair when create and printed on a secure platform? --Jonathan Cross, 2017-02-04
That is correct. In implementing all aspects of BIP38 (and BIP39) in the libbitcoin library, and providing a command line interface via bx, we had a chance to thoroughly review the scenarios. The confirmation code scenario is inherently flawed and the entire section should be struck. The other scenarios appear to be secure to the extent one trusts the platform and the cryptographic assumptions. The former is up to the user and I'm not qualified to asses the latter.
In response to your initial query, backing up an HD wallet consists of securing the master private key, which this BIP accomplishes. It is useful in the case where one must secure any existing private key. If one intends to create a new HD wallet BIP39 may be a better option. It accomplishes the objective of securing a private key (which it generates) but cannot secure an existing key.
--Eric Voskuil, 2017-02-11
This BIP has an unfortunate accidental history. Due to a process screw up it was never published for public review and has a number of shortcomings that would have been otherwise fixed. No strong replacement has been tendered because the general application of a single key paper wallet is strongly disfavored for security and usability reasons. I recommend against implementing this proposal. --Greg Maxwell, 2017-03-14
Can someone go into detail, or link a resource, on the problem with single key paper wallets? --Nick Johnson, 2017-04-01
`
BIP: 119 Layer: Consensus (soft fork) Title: CHECKTEMPLATEVERIFY Author: Jeremy Rubin [email protected] Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0119 Status: Draft Type: Standards Track Created: 2020-01-06 License: BSD-3-Clause
==Abstract==
This BIP proposes a new opcode, OP_CHECKTEMPLATEVERIFY, to be activated as a change to the semantics of OP_NOP4.
==Summary==
OP_CHECKTEMPLATEVERIFY uses opcode OP_NOP4 (0xb3) as a soft fork upgrade.
OP_CHECKTEMPLATEVERIFY does the following:
- There is at least one element on the stack, fail otherwise
- The element on the stack is 32 bytes long, NOP otherwise
- The DefaultCheckTemplateVerifyHash of the transaction at the current input index is equal to the element on the stack, fail otherwise
The DefaultCheckTemplateVerifyHash commits to the serialized version, locktime, scriptSigs hash (if any non-null scriptSigs), number of inputs, sequences hash, number of outputs, outputs hash, and currently executing input index.
The recommended standardness rules additionally:
- Reject non-32 byte as SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS.
==Motivation==
This BIP introduces a transaction template, a simple spending restriction that pattern matches a transaction against a hashed transaction specification. OP_CHECKTEMPLATEVERIFY reduces many of the trust, interactivity, and storage requirements inherent with the use of pre-signing in applications. For more details on applications, please see the references.
==Detailed Specification==
The below code is the main logic for verifying CHECKTEMPLATEVERIFY, described in pythonic pseudocode. The canonical specification for the semantics of OP_CHECKTEMPLATEVERIFY as implemented in C++ in the context of Bitcoin Core can be seen in the reference implementation.
The execution of the opcode is as follows:
# CTV always requires at least one stack argument
if len(self.stack) < 1:
return self.errors_with(errors.script_err_invalid_stack_operation)
# CTV only verifies the hash against a 32 byte argument
if len(self.stack[-1]) == 32:
# Ensure the precomputed data required for anti-DoS is available,
# or cache it on first use
if self.context.precomputed_ctv_data == None:
self.context.precomputed_ctv_data = self.context.tx.get_default_check_template_precomputed_data()
# If the hashes do not match, return error
if stack[-1] != self.context.tx.get_default_check_template_hash(self.context.nIn, self.context.precomputed_ctv_data):
return self.errors_with(errors.script_err_template_mismatch)
return self.return_as_nop()
# future upgrade can add semantics for this opcode with different length args
# so discourage use when applicable
if self.flags.script_verify_discourage_upgradable_nops:
return self.errors_with(errors.script_err_discourage_upgradable_nops)
else:
return self.return_as_nop()
The computation of this hash can be implemented as specified below (where self is the transaction type). Care must be taken that in any validation context, the precomputed data must be initialized to prevent Denial-of-Service attacks. Any implementation must cache these parts of the hash computation to avoid quadratic hashing DoS. All variable length computations must be precomputed including hashes of the scriptsigs, sequences, and outputs. See the section "Denial of Service and Validation Costs" below. This is not a performance optimization.
def ser_compact_size(l): r = b"" if l < 253: # Serialize as unsigned char r = struct.pack("B", l) elif l < 0x10000: # Serialize as unsigned char 253 followed by unsigned 2 byte integer (little endian) r = struct.pack("<BH", 253, l) elif l < 0x100000000: # Serialize as unsigned char 254 followed by unsigned 4 byte integer (little endian) r = struct.pack("<BI", 254, l) else: # Serialize as unsigned char 255 followed by unsigned 8 byte integer (little endian) r = struct.pack("<BQ", 255, l) return r
def ser_string(s): return ser_compact_size(len(s)) + s
class CTxOut: def serialize(self): r = b"" # serialize as signed 8 byte integer (little endian) r += struct.pack("<q", self.nValue) r += ser_string(self.scriptPubKey) return r
def get_default_check_template_precomputed_data(self): result = {} # If there are no s`**