Bitcoin Forum
December 08, 2016, 11:58:00 AM *
News: To be able to use the next phase of the beta forum software, please ensure that your email address is correct/functional.
 
   Home   Help Search Donate Login Register  
Pages: [1]
  Print  
Author Topic: Pbwhatkey -- deterministic private key generator (PBKDF2 & pywallet.py based)  (Read 5520 times)
Ukigo
Hero Member
*****
Offline Offline

Activity: 924


View Profile
July 15, 2011, 01:50:13 PM
 #1

Hi all !

It's there :

UPD : see next post for new version (probably more secure ).

Pbwhatkey takes 3 parameters :

 ./pbwhatkey your_passphrase your_salt number_of_iterations

From that input script generates private key and then shows  it and
 corresponding bitcoin address.
 
Installation :
1) Install pbwhatkey ( see post below )
2) Download pywallet from
 https://github.com/joric/pywallet  version 1.1 (will not work with v 1.0 )
Place pywallet.py in the same directory

Run it : ./pb4 Korsaar over9000 66666
          or : python pb4 Korsaar over9000 66666
Output must be :  

Private key for import :  5JPX6aZBM9NpVdRza6eYnJ1ofB76YL6bennLcZpBq6rB5mbvEYa
 
Bitcoin address :  1PQKsnY7N4jQhfRTgKx4j3xLkscYkm4fLS

3rd parameter must be BIG enough maybe above 1000000 iterations.
( tested up to 2200000 )

Password and salt can be in UTF-8 ( not tested yet though )

Tested with Python 2.6 , pbkdf2_rmd v 0.1 (python module), pywallet v 1.1

Any thoughts or suggestions ?






"...Enemies are everywhere ! Angka is all rage ! Be a good soldiers, blow everything... " <-- Pol Pot (C)
1481198280
Hero Member
*
Offline Offline

Posts: 1481198280

View Profile Personal Message (Offline)

Ignore
1481198280
Reply with quote  #2

1481198280
Report to moderator
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction. Advertise here.
Ukigo
Hero Member
*****
Offline Offline

Activity: 924


View Profile
July 16, 2011, 09:44:45 AM
 #2

Well, here comes version 3 Wink

UPD : replaced by version 4. See post below.


  



 
  
  
    

"...Enemies are everywhere ! Angka is all rage ! Be a good soldiers, blow everything... " <-- Pol Pot (C)
Ukigo
Hero Member
*****
Offline Offline

Activity: 924


View Profile
July 16, 2011, 09:51:41 AM
 #3

You will need a slightly altered by me PBKDF2 Python module.
Save code below as "pbkdf2_rmd.py" in the same directory with posted above
"pb3" script.
Code:
#!/usr/bin/python
# -*- coding: ascii -*-
###########################################################################
# pbkdf2 - PKCS#5 v2.0 Password-Based Key Derivation
#
# Copyright (C) 2007-2011 Dwayne C. Litzenberger <dlitz@dlitz.net>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Country of origin: Canada
#
###########################################################################
# Sample PBKDF2 usage:
#   from Crypto.Cipher import AES
#   from pbkdf2 import PBKDF2
#   import os
#
#   salt = os.urandom(8)    # 64-bit salt
#   key = PBKDF2("This passphrase is a secret.", salt).read(32) # 256-bit key
#   iv = os.urandom(16)     # 128-bit IV
#   cipher = AES.new(key, AES.MODE_CBC, iv)
#     ...
#
# Sample crypt() usage:
#   from pbkdf2 import crypt
#   pwhash = crypt("secret")
#   alleged_pw = raw_input("Enter password: ")
#   if pwhash == crypt(alleged_pw, pwhash):
#       print "Password good"
#   else:
#       print "Invalid password"
#
###########################################################################

__version__ = "0.1"
__all__ = ['PBKDF2_RMD', 'crypt']

from struct import pack
from random import randint
import string
import sys

try:
    # Use PyCrypto (if available).
    from Crypto.Hash import HMAC, SHA as SHA1, RIPEMD as RMD
except ImportError:
    print "Import Error : PyCrypto not installed !"
    exit (0)
    # PyCrypto not available.  Use the Python standard library.
#    import hmac as HMAC
#    try:
#        from hashlib import sha1 as SHA1
#    except ImportError:
        # hashlib not available.  Use the old sha module.
#        import sha as SHA1

#
# Python 2.1 thru 3.2 compatibility
#

if sys.version_info[0] == 2:
    _0xffffffffL = long(1) << 32
    def isunicode(s):
        return isinstance(s, unicode)
    def isbytes(s):
        return isinstance(s, str)
    def isinteger(n):
        return isinstance(n, (int, long))
    def b(s):
        return s
    def binxor(a, b):
        return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)])
    def b64encode(data, chars="+/"):
        tt = string.maketrans("+/", chars)
        return data.encode('base64').replace("\n", "").translate(tt)
    from binascii import b2a_hex
else:
    _0xffffffffL = 0xffffffff
    def isunicode(s):
        return isinstance(s, str)
    def isbytes(s):
        return isinstance(s, bytes)
    def isinteger(n):
        return isinstance(n, int)
    def callable(obj):
        return hasattr(obj, '__call__')
    def b(s):
       return s.encode("latin-1")
    def binxor(a, b):
        return bytes([x ^ y for (x, y) in zip(a, b)])
    from base64 import b64encode as _b64encode
    def b64encode(data, chars="+/"):
        if isunicode(chars):
            return _b64encode(data, chars.encode('utf-8')).decode('utf-8')
        else:
            return _b64encode(data, chars)
    from binascii import b2a_hex as _b2a_hex
    def b2a_hex(s):
        return _b2a_hex(s).decode('us-ascii')
    xrange = range

class PBKDF2_RMD(object):
    """PBKDF2.py : PKCS#5 v2.0 Password-Based Key Derivation

    This implementation takes a passphrase and a salt (and optionally an
    iteration count, a digest module, and a MAC module) and provides a
    file-like object from which an arbitrarily-sized key can be read.

    If the passphrase and/or salt are unicode objects, they are encoded as
    UTF-8 before they are processed.

    The idea behind PBKDF2 is to derive a cryptographic key from a
    passphrase and a salt.

    PBKDF2 may also be used as a strong salted password hash.  The
    'crypt' function is provided for that purpose.

    Remember: Keys generated using PBKDF2 are only as strong as the
    passphrases they are derived from.
    """

    def __init__(self, passphrase, salt, iterations=1000,
                 digestmodule=RMD, macmodule=HMAC):
        self.__macmodule = macmodule
        self.__digestmodule = digestmodule
        self._setup(passphrase, salt, iterations, self._pseudorandom)

    def _pseudorandom(self, key, msg):
        """Pseudorandom function.  e.g. HMAC-SHA1"""
        return self.__macmodule.new(key=key, msg=msg,
            digestmod=self.__digestmodule).digest()

    def read(self, bytes):
        """Read the specified number of key bytes."""
        if self.closed:
            raise ValueError("file-like object is closed")

        size = len(self.__buf)
        blocks = [self.__buf]
        i = self.__blockNum
        while size < bytes:
            i += 1
            if i > _0xffffffffL or i < 1:
                # We could return "" here, but
                raise OverflowError("derived key too long")
            block = self.__f(i)
            blocks.append(block)
            size += len(block)
        buf = b("").join(blocks)
        retval = buf[:bytes]
        self.__buf = buf[bytes:]
        self.__blockNum = i
        return retval

    def __f(self, i):
        # i must fit within 32 bits
        assert 1 <= i <= _0xffffffffL
        U = self.__prf(self.__passphrase, self.__salt + pack("!L", i))
        result = U
        for j in xrange(2, 1+self.__iterations):
            U = self.__prf(self.__passphrase, U)
            result = binxor(result, U)
        return result

    def hexread(self, octets):
        """Read the specified number of octets. Return them as hexadecimal.

        Note that len(obj.hexread(n)) == 2*n.
        """
        return b2a_hex(self.read(octets))

    def _setup(self, passphrase, salt, iterations, prf):
        # Sanity checks:

        # passphrase and salt must be str or unicode (in the latter
        # case, we convert to UTF-8)
        if isunicode(passphrase):
            passphrase = passphrase.encode("UTF-8")
        elif not isbytes(passphrase):
            raise TypeError("passphrase must be str or unicode")
        if isunicode(salt):
            salt = salt.encode("UTF-8")
        elif not isbytes(salt):
            raise TypeError("salt must be str or unicode")

        # iterations must be an integer >= 1
        if not isinteger(iterations):
            raise TypeError("iterations must be an integer")
        if iterations < 1:
            raise ValueError("iterations must be at least 1")

        # prf must be callable
        if not callable(prf):
            raise TypeError("prf must be callable")

        self.__passphrase = passphrase
        self.__salt = salt
        self.__iterations = iterations
        self.__prf = prf
        self.__blockNum = 0
        self.__buf = b("")
        self.closed = False

    def close(self):
        """Close the stream."""
        if not self.closed:
            del self.__passphrase
            del self.__salt
            del self.__iterations
            del self.__prf
            del self.__blockNum
            del self.__buf
            self.closed = True

def crypt(word, salt=None, iterations=None):
    """PBKDF2-based unix crypt(3) replacement.

    The number of iterations specified in the salt overrides the 'iterations'
    parameter.

    The effective hash length is 192 bits.
    """

    # Generate a (pseudo-)random salt if the user hasn't provided one.
    if salt is None:
        salt = _makesalt()

    # salt must be a string or the us-ascii subset of unicode
    if isunicode(salt):
        salt = salt.encode('us-ascii').decode('us-ascii')
    elif isbytes(salt):
        salt = salt.decode('us-ascii')
    else:
        raise TypeError("salt must be a string")

    # word must be a string or unicode (in the latter case, we convert to UTF-8)
    if isunicode(word):
        word = word.encode("UTF-8")
    elif not isbytes(word):
        raise TypeError("word must be a string or unicode")

    # Try to extract the real salt and iteration count from the salt
    if salt.startswith("$p5k2$"):
        (iterations, salt, dummy) = salt.split("$")[2:5]
        if iterations == "":
            iterations = 400
        else:
            converted = int(iterations, 16)
            if iterations != "%x" % converted:  # lowercase hex, minimum digits
                raise ValueError("Invalid salt")
            iterations = converted
            if not (iterations >= 1):
                raise ValueError("Invalid salt")

    # Make sure the salt matches the allowed character set
    allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"
    for ch in salt:
        if ch not in allowed:
            raise ValueError("Illegal character %r in salt" % (ch,))

    if iterations is None or iterations == 400:
        iterations = 400
        salt = "$p5k2$$" + salt
    else:
        salt = "$p5k2$%x$%s" % (iterations, salt)
    rawhash = PBKDF2_RMD(word, salt, iterations).read(24)
    return salt + "$" + b64encode(rawhash, "./")

# Add crypt as a static method of the PBKDF2 class
# This makes it easier to do "from PBKDF2 import PBKDF2" and still use
# crypt.
PBKDF2_RMD.crypt = staticmethod(crypt)

def _makesalt():
    """Return a 48-bit pseudorandom salt for crypt().

    This function is not suitable for generating cryptographic secrets.
    """
    binarysalt = b("").join([pack("@H", randint(0, 0xffff)) for i in range(3)])
    return b64encode(binarysalt, "./")

# vim:set ts=4 sw=4 sts=4 expandtab:
#

This module implements HMAC-RIPEMD160 algorithm.
Probably safer than HMAC-SHA1 in the very good pbkdf2
module by Dwayne Litzenberger.

"...Enemies are everywhere ! Angka is all rage ! Be a good soldiers, blow everything... " <-- Pol Pot (C)
Ukigo
Hero Member
*****
Offline Offline

Activity: 924


View Profile
July 16, 2011, 10:26:13 AM
 #4

With "pb4" you can easily regenerate your lost with broken backup private key
in the future.
Just keep TOP secret your 3 params. Good for savings.

Also you  can tweak "pb4" script and as result you will have your

personal unique key generator. No one else will be able to create your keys.

It's like 3-factor authentification. The attacker need to know ALL of your params
 to recreate your key and then spend your money.

Add. if number of iterations is BIG enough the bad guy will spend a LOT of resources
trying to brute-force. Quite expansive for him.

"...Enemies are everywhere ! Angka is all rage ! Be a good soldiers, blow everything... " <-- Pol Pot (C)
samr7
Full Member
***
Offline Offline

Activity: 140

Firstbits: 1samr7


View Profile
July 19, 2011, 12:10:05 PM
 #5

This program would appear to work exactly as advertised.  It produces good, repeatable public/private key pairs out of passwords using a standard, well-regarded algorithm.  Kudos on moving to Python, it's so easy to read the code, and the base58 functions are elegant and understandable!

In any case, memorizing a 51-character private key is unwieldy, but I'll argue that a strong password of comparable security can be a little over half as long and much easier to memorize.  Which, besides backup, would be really great in low-tech situations where wallet files and all physical representations of keys can't be retained.
Ukigo
Hero Member
*****
Offline Offline

Activity: 924


View Profile
July 19, 2011, 02:24:48 PM
 #6

2 samr7 :
 Thanks again for your idea and suggestions about PBKDF2 !
  Me too very happy that whole task now done in one language
 without pipes and tricks of previous solution (ukbx).
 Base58 routines are not mine. I take them from someone else project.
 So it's truly collective work )
 
 For me most important result is that now i can move my savings
 to my new repairable addresses. Broken backups are not a threat more.


 

"...Enemies are everywhere ! Angka is all rage ! Be a good soldiers, blow everything... " <-- Pol Pot (C)
samr7
Full Member
***
Offline Offline

Activity: 140

Firstbits: 1samr7


View Profile
July 19, 2011, 03:53:27 PM
 #7

On second thought, there is one detail about this program that worries me.

It sets up the PBKDF2 function and reads out 16 bytes as a hexadecimal-encoded string.

Code:
    topsec = PBKDF2_RMD(hashlib.sha512(sys.argv[1]).hexdigest(), salt, int(sys.argv[3])).hexread(16)

Then it passes the string to the pywallet integer converter.  I think what you meant to do with this is read 32 bytes of unencoded data from the PBKDF2 function:

Code:
    topsec = PBKDF2_RMD(hashlib.sha512(sys.argv[1]).hexdigest(), salt, int(sys.argv[3])).read(32)

and while the next line will no longer be able to print the raw private key without a str.encode('hex'), the str_to_long will at least get the full key data.  As it stands now, it looks like it's using the ASCII hexadecimal string as the raw private key, which would provide about half the expected level of security.
Ukigo
Hero Member
*****
Offline Offline

Activity: 924


View Profile
July 20, 2011, 04:12:47 AM
 #8

As i understand this :
"topsec" is NOT a private key itself, but a "secret multiplier" using to construct  private key.
 See pywallet source code.
 
 Previous unpublished version of "pb" (working with pywallet v1.0 that have diffrent API)
 simply creates 32-digit hexadecimal and then uses it as private key.

 With pywallet v 1.1 it can not be done, so i decide to create secret multiplier from input params.
 But maybe you are right and your proposed changes will enlarge keyspace a lot.

I'm not sure how many digits secret multiplier must have ?!
 

"...Enemies are everywhere ! Angka is all rage ! Be a good soldiers, blow everything... " <-- Pol Pot (C)
Ukigo
Hero Member
*****
Offline Offline

Activity: 924


View Profile
July 20, 2011, 04:24:17 AM
 #9

version 4 available for testing :
Code:
#!/usr/bin/python

# Copyright (c) 2011, Ukigo

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


usage = """             Usage : ./pb4 your_passphrase your_salt number_of_iterations

                        Example :  ./pb4 +WindFall-Money*. Candy+] 777777 """


from pbkdf2_rmd import PBKDF2_RMD
import os, sys, hashlib
from hashlib import sha256
import pywallet as pyw
#from optparse import OptionParser

b58_digits = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def base58_encode (n):
    l = []
    while n > 0:
        n, r = divmod (n, 58)
        l.insert (0, (b58_digits[r]))
    return ''.join (l)

def base58_decode (s):
    n = 0
    for ch in s:
        n *= 58
        digit = b58_digits.index (ch)
        n += digit
    return n

def dhash (s):
    return sha256(sha256(s).digest()).digest()

def convert_privkey_to_base58 (s):
    checksum = dhash ('\x80' + s)[:4]
    return base58_encode (
        int ('0x80' + (s + checksum).encode ('hex_codec'), 16)
        )

def main():

    try:
        if sys.argv[1] in ("help", "-h", "-help","--help"):
            print " "
            print usage
            exit(0)
        if int(sys.argv[3]) < 60001:
            print " "
            print "Number of iterations must be > 60000 ( better use > 1'000'000 )"
            exit(0)

    except IndexError:
        print " "
        print usage
        exit(0)

    print " "
    print "    Please wait. Generating keypair ..."
    salt = hashlib.sha512(sys.argv[2]).hexdigest()
    print " "
    print "Password was : ", sys.argv[1]

    topsec = PBKDF2_RMD(hashlib.sha512(sys.argv[1]).hexdigest(), salt, int(sys.argv[3])).read(32)
    #print "                .............................................................."
    print "Secret  multiplier : ", topsec.encode("hex")

    
    
    print " "
    

    secret = pyw.str_to_long(topsec)
    eckey = pyw.EC_KEY(secret)
    pub = pyw.GetPubKey(eckey)
    priv = pyw.GetPrivKey(eckey)
    priv_base58 = pyw.SecretToASecret(pyw.PrivKeyToSecret(priv))


    print "Private key for import : ", priv_base58
    

    print " "
    print "Bitcoin address :  "+pyw.public_key_to_bc_address(pub)
    print " "
    exit(0)

if __name__ == '__main__':
    main()

"...Enemies are everywhere ! Angka is all rage ! Be a good soldiers, blow everything... " <-- Pol Pot (C)
samr7
Full Member
***
Offline Offline

Activity: 140

Firstbits: 1samr7


View Profile
July 20, 2011, 04:48:59 AM
 #10

As i understand this :
"topsec" is NOT a private key itself, but a "secret multiplier" using to construct  private key.
 See pywallet source code.

It's true that the topsec isn't the same thing as a pywallet Private_key.  However, an EC private key is just a large integer between 0 and the group order, and one would assume your intention is to use topsec as this value.

Indeed the secret and secret_multiplier from the pywallet code is exactly the EC private key.  The act of multiplying the generator (point) by secret (integer) produces the EC public key (point).

Quote
I'm not sure how many digits secret multiplier must have ?!

It's 32 bytes long.  The largest useful value is one less than: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

BTW, new version looks a lot better!
Ukigo
Hero Member
*****
Offline Offline

Activity: 924


View Profile
July 20, 2011, 06:16:38 AM
 #11

My bad ! You are right !
 Those elliptic curves create chaos in my tired head )




"...Enemies are everywhere ! Angka is all rage ! Be a good soldiers, blow everything... " <-- Pol Pot (C)
etotheipi
Legendary
*
expert
Offline Offline

Activity: 1428


Core Armory Developer


View Profile WWW
August 25, 2011, 11:21:55 PM
 #12

So I'm reviving an old thread here, but I'm interested in a slightly different application of deterministic key generation.  It seems like something that could integrated with pywallet very easily.  I'm sure I'm not the first person to suggest this, but I'm not finding other threads about it.

Rather than using passwords to deterministically generate your key, I'd like to use a random number generator to create a 256-bit Private-Key-Generator once.  This generator would be the first private key, GenKey, and then you get a semi-infinite sequence of new keys by simply following:

Code:
PrivKey[i+1] = hash256( GenKey XOR PrivKey[i] );

You wouldn't need the key stretching (at least that's what I'm assuming the iterations are for in the PBKDF2 module), because you're using full entropy in your original key.  Using this technique, you only need to backup your wallet once.  Sure, it links all your addresses together, but 99% of the time with the current wallet, if the attacker gets one key, he gets all of them, anyway.  And by using GenKey in each iteration, even if attacker gets PrivKey(i), he cannot determine any of the other keys.  My primary motivation is that I want to be able to put my GenKey into a QR code and store it in a safe-deposit box, and then I never have to worry about losing my private keys.  

With the current wallet, I only get a pool of 100 keys, and have to re-backup my wallet every time I run out.

Founder and CEO of Armory Technologies, Inc.
Armory Bitcoin Wallet: Bringing cold storage to the average user!
Only use Armory software signed by the Armory Offline Signing Key (0x98832223)

Please donate to the Armory project by clicking here!    (or donate directly via 1QBDLYTDFHHZAABYSKGKPWKLSXZWCCJQBX -- yes, it's a real address!)
Ukigo
Hero Member
*****
Offline Offline

Activity: 924


View Profile
August 26, 2011, 04:35:14 AM
 #13

So I'm reviving an old thread here, but I'm interested in a slightly different application of deterministic key generation.  It seems like something that could integrated with pywallet very easily.  I'm sure I'm not the first person to suggest this, but I'm not finding other threads about it.

Rather than using passwords to deterministically generate your key, I'd like to use a random number generator to create a 256-bit Private-Key-Generator once.  This generator would be the first private key, GenKey, and then you get a semi-infinite sequence of new keys by simply following:

Code:
PrivKey[i+1] = hash256( GenKey XOR PrivKey[i] );

You wouldn't need the key stretching (at least that's what I'm assuming the iterations are for in the PBKDF2 module), because you're using full entropy in your original key.  Using this technique, you only need to backup your wallet once.  Sure, it links all your addresses together, but 99% of the time with the current wallet, if the attacker gets one key, he gets all of them, anyway.  And by using GenKey in each iteration, even if attacker gets PrivKey(i), he cannot determine any of the other keys.  My primary motivation is that I want to be able to put my GenKey into a QR code and store it in a safe-deposit box, and then I never have to worry about losing my private keys.  

With the current wallet, I only get a pool of 100 keys, and have to re-backup my wallet every time I run out.

Your idea in my view is closer to deterministic wallets.
Go ahead, be the first to produce some REAL code that way.
Show it.People will criticize your approach.
Maybe something interesting will be born.

Also i am sure that safe-deposit boxes are not really so SAFE nowadays.
Keeping your secrets there you simply exchange one risk to another.

"...Enemies are everywhere ! Angka is all rage ! Be a good soldiers, blow everything... " <-- Pol Pot (C)
etotheipi
Legendary
*
expert
Offline Offline

Activity: 1428


Core Armory Developer


View Profile WWW
August 26, 2011, 04:51:57 AM
 #14

Yes, it is a deterministic wallet.  In hindsight I realize is not precisely the purpose of this original post, but it is related.  Pywallet is the perfect tool for enabling this technique.  The command line interface would look like:

   
Code:
./pywallet.py --create-deterministic-wallet --generator-key=random256bit.bin --numkeys 10000 -o wallet.dat

This would calculate the first 10,000 keys based on the generator, and add them to key pool in wallet.dat.  If you run out of keys, you can re-run with a higher number, and it will add the new keys to it.  Perhaps it could eventually be included in the client so you never have to run anything:  just create your generator-key once, back it up, and the client will create endless keys from it.

You don't have to be snarky about the idea... it's simply a suggestion and you guys are a very short way from having this enabled using pywallet.py.  If you don't like it, let's have a discussion about what problems it might have and how they could be resolved.

Also, I don't know why you would question the security of safe-deposit boxes, but that wasn't the point at all.  People want to be able to backup their wallet once and know that they always have a backup somewhere they consider safe in case their hard-drive fails.  With the current wallets, they have to backup every 100 transactions.  Additionally, there is no warning when their key pool is exhausted, so there's a risk of using non-backed-up keys without realizing it.  This deterministic wallet solves a lot of problems, and I don't see where the reduced security is.




Founder and CEO of Armory Technologies, Inc.
Armory Bitcoin Wallet: Bringing cold storage to the average user!
Only use Armory software signed by the Armory Offline Signing Key (0x98832223)

Please donate to the Armory project by clicking here!    (or donate directly via 1QBDLYTDFHHZAABYSKGKPWKLSXZWCCJQBX -- yes, it's a real address!)
Ukigo
Hero Member
*****
Offline Offline

Activity: 924


View Profile
August 26, 2011, 06:02:03 AM
 #15


You don't have to be snarky about the idea... it's simply a suggestion and you guys are a very short way from having this enabled using pywallet.py.  If you don't like it, let's have a discussion about what problems it might have and how they could be resolved.
I like your idea, but personally have no time to try to implement it right now.
Devil always in the details. Only after we will have reference implementation we will see HIM's ears.
Or not will see Smiley
Quote
Also, I don't know why you would question the security of safe-deposit boxes, but that wasn't the point at all.
 
I only mean that if you loose somehow (bank went bankrupt or get robbed,riots or some other event)your backup placed in safe box you will be in huge trouble.

"...Enemies are everywhere ! Angka is all rage ! Be a good soldiers, blow everything... " <-- Pol Pot (C)
Pages: [1]
  Print  
 
Jump to:  

Sponsored by , a Bitcoin-accepting VPN.
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!