All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fisco.bcos.web3j.crypto.ECKeyPair Maven / Gradle / Ivy

package org.fisco.bcos.web3j.crypto;

import java.math.BigInteger;
import java.security.KeyPair;
import java.util.Arrays;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.fisco.bcos.web3j.utils.Numeric;

/** Elliptic Curve SECP-256k1 generated key pair. */
public class ECKeyPair {
  private final BigInteger privateKey;
  private final BigInteger publicKey;

  public ECKeyPair(BigInteger privateKey, BigInteger publicKey) {
    this.privateKey = privateKey;
    this.publicKey = publicKey;
  }

  public BigInteger getPrivateKey() {
    return privateKey;
  }

  public BigInteger getPublicKey() {
    return publicKey;
  }

  /**
   * Sign a hash with the private key of this key pair.
   *
   * @param transactionHash the hash to sign
   * @return An {@link ECDSASignature} of the hash
   */
  public ECDSASignature sign(byte[] transactionHash) {
    ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));

    ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKey, Sign.CURVE);
    signer.init(true, privKey);
    BigInteger[] components = signer.generateSignature(transactionHash);

    return new ECDSASignature(components[0], components[1]).toCanonicalised();
  }

  public static ECKeyPair create(KeyPair keyPair) {
    BCECPrivateKey privateKey = (BCECPrivateKey) keyPair.getPrivate();
    BCECPublicKey publicKey = (BCECPublicKey) keyPair.getPublic();

    BigInteger privateKeyValue = privateKey.getD();

    // Ethereum does not use encoded public keys like bitcoin - see
    // https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm for details
    // Additionally, as the first bit is a constant prefix (0x04) we ignore this value
    byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
    BigInteger publicKeyValue =
        new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length));

    return new ECKeyPair(privateKeyValue, publicKeyValue);
  }

  public static ECKeyPair create(BigInteger privateKey) {
    return new ECKeyPair(privateKey, Sign.publicKeyFromPrivate(privateKey));
  }

  public static ECKeyPair create(byte[] privateKey) {
    return create(Numeric.toBigInt(privateKey));
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    ECKeyPair ecKeyPair = (ECKeyPair) o;

    if (privateKey != null
        ? !privateKey.equals(ecKeyPair.privateKey)
        : ecKeyPair.privateKey != null) {
      return false;
    }

    return publicKey != null ? publicKey.equals(ecKeyPair.publicKey) : ecKeyPair.publicKey == null;
  }

  @Override
  public int hashCode() {
    int result = privateKey != null ? privateKey.hashCode() : 0;
    result = 31 * result + (publicKey != null ? publicKey.hashCode() : 0);
    return result;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy