Package com.bitsofproof.supernode.wallet

Source Code of com.bitsofproof.supernode.wallet.ShamirsSecretSharing$SecretShare

/*
* 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.math.BigInteger;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

import org.bouncycastle.util.Arrays;

import com.bitsofproof.supernode.common.ValidationException;

public class ShamirsSecretSharing
{
  public static class SecretShare
  {
    public byte x;
    public byte dl;
    public byte yl;
    public byte[] y;
  }

  private final static SecureRandom random = new SecureRandom ();

  public static List<String> issueMnemonicShares (byte[] data, int pieces, int needed, String passphrase) throws ValidationException
  {
    List<String> m = new ArrayList<> ();
    for ( SecretShare share : cut (data, pieces, needed) )
    {
      int l = share.y.length + 3;
      if ( l % 8 != 0 )
      {
        l += 8 - l % 8;
      }
      byte[] e = new byte[l];
      e[0] = share.x;
      e[1] = share.dl;
      e[2] = (byte) share.y.length;
      System.arraycopy (share.y, 0, e, 3, share.y.length);
      m.add (BIP39.encode (e, passphrase));
    }
    return m;
  }

  public static byte[] reconstructFromMnemonicShares (List<String> shareList, String passphrase) throws ValidationException
  {
    SecretShare[] shares = new SecretShare[shareList.size ()];
    int i = 0;
    for ( String m : shareList )
    {
      byte[] e = BIP39.decode (m, passphrase);
      shares[i] = new SecretShare ();
      shares[i].x = e[0];
      shares[i].dl = e[1];
      shares[i].yl = e[2];
      shares[i].y = Arrays.copyOfRange (e, 3, shares[i].yl + 3);
      ++i;
    }
    return reconstruct (shares);
  }

  public static SecretShare[] cut (byte[] secret, int pieces, int needed) throws ValidationException
  {
    if ( secret.length > 127 )
    {
      throw new ValidationException ("secret too long");
    }
    BigInteger[] coeff = new BigInteger[needed - 1];
    for ( int i = 0; i < coeff.length; ++i )
    {
      byte[] r = new byte[secret.length];
      random.nextBytes (r);
      coeff[i] = new BigInteger (r);
    }

    SecretShare[] shares = new SecretShare[pieces];
    for ( int x = 1; x <= pieces; ++x )
    {
      int pow = x;
      BigInteger poly = new BigInteger (1, secret);
      for ( int i = 0; i < needed - 1; ++i )
      {
        poly = poly.add (BigInteger.valueOf (pow).multiply (coeff[i]));
        pow *= x;
      }
      shares[x - 1] = new SecretShare ();
      shares[x - 1].x = (byte) x;
      shares[x - 1].dl = (byte) secret.length;
      shares[x - 1].y = poly.toByteArray ();
      shares[x - 1].yl = (byte) poly.toByteArray ().length;
    }

    return shares;
  }

  public static byte[] reconstruct (SecretShare[] shares) throws ValidationException
  {
    for ( int i = 0; i < shares.length - 1; ++i )
    {
      for ( int j = 0; j < shares.length; ++j )
      {
        if ( i != j && shares[i].x == shares[j].x )
        {
          throw new ValidationException ("Shares are not unique");
        }
      }
    }
    BigInteger[] y = new BigInteger[shares.length];
    for ( int i = 0; i < shares.length; ++i )
    {
      y[i] = new BigInteger (shares[i].y);
    }
    int d, i;
    for ( d = 1; d < shares.length; d++ )
    {
      for ( i = 0; i < shares.length - d; i++ )
      {
        int j = i + d;
        BigInteger num =
            BigInteger.valueOf (shares[j].x).multiply (y[i]).subtract (BigInteger.valueOf (shares[i].x).multiply (y[i + 1]));
        BigInteger den = BigInteger.valueOf (shares[j].x).subtract (BigInteger.valueOf (shares[i].x));
        y[i] = num.divide (den);
      }
    }
    byte[] result = y[0].toByteArray ();
    if ( result.length > shares[0].dl )
    {
      result = Arrays.copyOfRange (result, result.length - shares[0].dl, result.length);
    }
    if ( result.length < shares[0].dl )
    {
      byte[] tmp = new byte[shares[0].dl];
      System.arraycopy (result, 0, tmp, shares[0].dl - result.length, result.length);
      result = tmp;
    }
    return result;
  }
}
TOP

Related Classes of com.bitsofproof.supernode.wallet.ShamirsSecretSharing$SecretShare

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.