def generate(passphrase, trees=['primary']): """Generate a seed for the primary tree of a Gem wallet. You may choose to store the passphrase for a user so the user doesn't have to type it in every time. This is okay (although the security risks should be obvious) but Gem strongly discourages storing even the encrypted private seed, and storing both the passphrase and the private seed is completely insane. Don't do it. Args: passphrase (str): The passphrase that will be used to encrypt the seed before it's send to Gem. Key-stretching is done with PBDKF2 and encryption is done with nacl's SecretBox. trees (list of str): A list of names to generate trees for. For User Wallets this will be ['primary'], for Application Wallets it will be ['primary', 'backup']. Returns: A dict of dicts containing the serialized public master node, and a sub-dict with the encrypted private seed for each tree in `trees`. """ seeds, multi_wallet = MultiWallet.generate(trees, entropy=True) result = {} for tree in trees: result[tree] = dict(private_seed=seeds[tree], public_seed=multi_wallet.public_wif(tree), encrypted_seed=PassphraseBox.encrypt(passphrase, seeds[tree])) return result
def generate(passphrase, trees=['primary']): """Generate a seed for the primary tree of a Gem wallet. You may choose to store the passphrase for a user so the user doesn't have to type it in every time. This is okay (although the security risks should be obvious) but Gem strongly discourages storing even the encrypted private seed, and storing both the passphrase and the private seed is completely insane. Don't do it. Args: passphrase (str): The passphrase that will be used to encrypt the seed before it's send to Gem. Key-stretching is done with PBDKF2 and encryption is done with nacl's SecretBox. trees (list of str): A list of names to generate trees for. For User Wallets this will be ['primary'], for Application Wallets it will be ['primary', 'backup']. Returns: A dict of dicts containing the serialized public master node, and a sub-dict with the encrypted private seed for each tree in `trees`. """ seeds, multi_wallet = MultiWallet.generate(trees, entropy=True) result = {} for tree in trees: result[tree] = dict(private_seed=seeds[tree], public_seed=multi_wallet.public_wif(tree), encrypted_seed=PassphraseBox.encrypt( passphrase, seeds[tree])) return result
def unlock(self, passphrase): """Unlock the Wallet by decrypting the primary_private_seed with the supplied passphrase. Once unlocked, the private seed is accessible in memory and calls to `account.pay` will succeed. This is a necessary step for creating transactions. Args: passphrase (str): The passphrase the User used to encrypt this wallet. Returns: self """ wallet = self.resource try: if wallet.primary_private_seed['nonce']: primary_seed = NaclPassphraseBox.decrypt( passphrase, wallet.primary_private_seed) else: primary_seed = PassphraseBox.decrypt( passphrase, wallet.primary_private_seed) except: raise InvalidPassphraseError() self.multi_wallet = MultiWallet( private_seeds={'primary': primary_seed}, public={'cosigner': wallet.cosigner_public_seed, 'backup': wallet.backup_public_seed}) return self
def unlock(self, passphrase, encrypted_seed=None): """Unlock the Wallet by decrypting the primary_private_seed with the supplied passphrase. Once unlocked, the private seed is accessible in memory and calls to `account.pay` will succeed. This is a necessary step for creating transactions. Args: passphrase (str): The passphrase the User used to encrypt this wallet. encrypted_seed (dict): A dictionary of the form {'ciphertext': longhexvalue, 'iterations': integer of pbkdf2 derivations, 'nonce': 24-byte hex value 'salt': 16-byte hex value} this dict represents an private seed (not a master key) encrypted with the `passphrase` using pbkdf2. You can obtain this value with wallet.generate. If this value is supplied, it overwrites (locally only) the encrypted primary_private_seed value, allowing you to load in a primary key that you didn't store with Gem. Note that the key MUST match the pubkey that this wallet was created with. Returns: self """ wallet = self.resource if not encrypted_seed: encrypted_seed = wallet.primary_private_seed try: if encrypted_seed['nonce']: primary_seed = NaclPassphraseBox.decrypt( passphrase, encrypted_seed) else: primary_seed = PassphraseBox.decrypt(passphrase, encrypted_seed) except: raise InvalidPassphraseError() self.multi_wallet = MultiWallet( private_seeds={'primary': primary_seed}, public={ 'cosigner': wallet.cosigner_public_seed, 'backup': wallet.backup_public_seed }) return self
def unlock(self, passphrase, encrypted_seed=None): """Unlock the Wallet by decrypting the primary_private_seed with the supplied passphrase. Once unlocked, the private seed is accessible in memory and calls to `account.pay` will succeed. This is a necessary step for creating transactions. Args: passphrase (str): The passphrase the User used to encrypt this wallet. encrypted_seed (dict): A dictionary of the form {'ciphertext': longhexvalue, 'iterations': integer of pbkdf2 derivations, 'nonce': 24-byte hex value 'salt': 16-byte hex value} this dict represents an private seed (not a master key) encrypted with the `passphrase` using pbkdf2. You can obtain this value with wallet.generate. If this value is supplied, it overwrites (locally only) the encrypted primary_private_seed value, allowing you to load in a primary key that you didn't store with Gem. Note that the key MUST match the pubkey that this wallet was created with. Returns: self """ wallet = self.resource if not encrypted_seed: encrypted_seed = wallet.primary_private_seed try: if encrypted_seed['nonce']: primary_seed = NaclPassphraseBox.decrypt( passphrase, encrypted_seed) else: primary_seed = PassphraseBox.decrypt( passphrase, encrypted_seed) except: raise InvalidPassphraseError() self.multi_wallet = MultiWallet( private_seeds={'primary': primary_seed}, public={'cosigner': wallet.cosigner_public_seed, 'backup': wallet.backup_public_seed}) return self