Package com.bitsofproof.supernode.wallet

Source Code of com.bitsofproof.supernode.wallet.SimpleFileWallet$NCExtendedKeyAccountManager

/*
* Copyright 2013 bits of proof zrt.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bitsofproof.supernode.wallet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.bitsofproof.supernode.api.BCSAPI;
import com.bitsofproof.supernode.api.BCSAPIException;
import com.bitsofproof.supernode.common.ExtendedKey;
import com.bitsofproof.supernode.common.ValidationException;
import com.google.protobuf.ByteString;

public class SimpleFileWallet implements Wallet
{
  private static final SecureRandom random = new SecureRandom ();
  private transient ExtendedKey master;
  private byte[] encrypted;
  private byte[] signature;
  private String fileName;
  private long since;

  private static class NCExtendedKeyAccountManager extends ExtendedKeyAccountManager
  {
    private final String name;

    public NCExtendedKeyAccountManager (String name, long created)
    {
      super ();
      this.name = name;
      setCreated (created);
    }

    public String getName ()
    {
      return name;
    }
  }

  private final Map<String, NCExtendedKeyAccountManager> accounts = new HashMap<String, NCExtendedKeyAccountManager> ();

  public SimpleFileWallet (String fileName)
  {
    this.fileName = fileName;
    this.since = System.currentTimeMillis ();
  }

  public boolean exists ()
  {
    return new File (fileName).exists ();
  }

  public void init (String passphrase)
  {
    master = null;
    encrypted = new byte[32];
    random.nextBytes (encrypted);
    try
    {
      signature = ExtendedKey.createFromPassphrase (passphrase, encrypted).getMaster ().sign (encrypted);
    }
    catch ( ValidationException e )
    {
    }
  }

  public void init (String passphrase, ExtendedKey master, boolean production, long since)
  {
    this.master = master;
    this.since = since;
    try
    {
      encrypted = master.encrypt (passphrase, production);
      signature = ExtendedKey.createFromPassphrase (passphrase, encrypted).getMaster ().sign (encrypted);
    }
    catch ( ValidationException e )
    {
    }
  }

  public ExtendedKey getMaster ()
  {
    return master;
  }

  public void unlock (String passphrase) throws ValidationException
  {
    master = ExtendedKey.createFromPassphrase (passphrase, encrypted);
    if ( !master.getMaster ().verify (encrypted, signature) )
    {
      throw new ValidationException ("incorrect passphrase");
    }
    for ( NCExtendedKeyAccountManager account : accounts.values () )
    {
      account.setMaster (master.getChild (account.getMaster ().getSequence ()));
    }
  }

  public void lock ()
  {
    master = null;
    for ( ExtendedKeyAccountManager account : accounts.values () )
    {
      account.setMaster (account.getMaster ().getReadOnly ());
    }
  }

  public List<String> getAccountNames ()
  {
    List<String> names = new ArrayList<String> ();
    for ( NCExtendedKeyAccountManager account : accounts.values () )
    {
      names.add (account.getName ());
    }
    return names;
  }

  public void setFileName (String fileName)
  {
    this.fileName = fileName;
  }

  public static SimpleFileWallet read (String fileName) throws IOException, ValidationException
  {
    SimpleFileWallet wallet = new SimpleFileWallet (fileName);
    File f = new File (fileName);
    InputStream in = new FileInputStream (f);
    try
    {
      WalletFormat.SimpleWallet walletMessage = WalletFormat.SimpleWallet.parseFrom (in);
      wallet.encrypted = walletMessage.getEncryptedSeed ().toByteArray ();
      wallet.signature = walletMessage.getSignature ().toByteArray ();
      for ( WalletFormat.SimpleWallet.Account account : walletMessage.getAccountsList () )
      {
        ExtendedKey pub = ExtendedKey.parse (account.getPublicKey ());
        NCExtendedKeyAccountManager am = new NCExtendedKeyAccountManager (account.getName (), account.getCreated () * 1000);
        am.setFirstIndex (account.getFirstIndex ());
        wallet.accounts.put (account.getName (), am);
        am.setMaster (pub);
      }
    }
    finally
    {
      in.close ();
    }
    return wallet;
  }

  public void sync (BCSAPI api) throws BCSAPIException, ValidationException
  {
    for ( NCExtendedKeyAccountManager account : accounts.values () )
    {
      account.syncHistory (api);
    }
  }

  @Override
  public synchronized AccountManager getAccountManager (String name)
  {
    return accounts.get (name);
  }

  @Override
  public synchronized AccountManager createAccountManager (String name) throws ValidationException
  {
    if ( accounts.containsKey (name) )
    {
      return accounts.get (name);
    }
    else
    {
      if ( master == null )
      {
        throw new ValidationException ("The wallet is locked");
      }
      NCExtendedKeyAccountManager account = new NCExtendedKeyAccountManager (name, Math.min (System.currentTimeMillis (), since));
      account.setMaster (master.getChild (accounts.size () | 0x80000000));
      accounts.put (name, account);
      return account;
    }
  }

  public void persist () throws IOException
  {
    FileOutputStream out = new FileOutputStream (fileName);
    try
    {
      WalletFormat.SimpleWallet.Builder builder = WalletFormat.SimpleWallet.newBuilder ();
      builder.setBcsapiversion (1);
      builder.setEncryptedSeed (ByteString.copyFrom (encrypted));
      builder.setSignature (ByteString.copyFrom (signature));
      for ( NCExtendedKeyAccountManager am : accounts.values () )
      {
        WalletFormat.SimpleWallet.Account.Builder ab = WalletFormat.SimpleWallet.Account.newBuilder ();
        ab.setName (am.getName ());
        ab.setCreated (am.getCreated () / 1000);
        ab.setFirstIndex (am.getFirstIndex ());
        ab.setPublicKey (am.getMaster ().getReadOnly ().serialize (true));
        builder.addAccounts (ab.build ());
      }
      builder.build ().writeTo (out);
    }
    finally
    {
      out.close ();
    }
  }
}
TOP

Related Classes of com.bitsofproof.supernode.wallet.SimpleFileWallet$NCExtendedKeyAccountManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.