Private-Key

在移動端生成乙太坊私鑰、公鑰(Android/Java)

  • January 10, 2018

我正在尋找一種在 Android 應用程序中生成乙太坊私鑰和公鑰的方法。我搜尋了網路並最終決定將程式碼拆分到 myetherwallet 並將相同的 Javascript 庫導入 Android/Java 並在那裡執行它們。但是,這感覺非常麻煩。

有沒有人有用於在 Android 中為乙太坊生成私鑰/公鑰對的程式碼片段?

1)按照第二個答案中的說明在Android上實現spongycastle。https://stackoverflow.com/questions/6898801/how-to-include-the-spongy-castle-jar-in-android

2)下載並導入slfj4 logger jar http://www.slf4j.org/android/

3)下載最新的ethereumj jar。確保首先在 build.gradle 依賴項中列出 spongycastle jar,然後是 slf4j,然後是 ethereumj

  1. 你需要使用海綿城堡而不是 bouncycastle 創建新的乙太坊類。這是我用來創建私鑰、簽名等的類。它只是 ethereumj 的 ECKey.class 的修改版本。請注意,我在這裡包含了 spongycastle 作為安全提供者,所以不要讓自己成為一個包含它的新類(這在步驟 1 中提到過)
package com.your.package;
import android.support.annotation.Nullable;

import org.ethereum.config.Constants;
import org.ethereum.crypto.HashUtil;
import org.ethereum.crypto.jce.ECKeyAgreement;
import org.ethereum.crypto.jce.ECKeyFactory;
import org.ethereum.crypto.jce.ECKeyPairGenerator;
import org.ethereum.crypto.jce.ECSignatureFactory;
import org.ethereum.util.BIUtil;
import org.ethereum.util.ByteUtil;
import org.spongycastle.asn1.ASN1InputStream;
import org.spongycastle.asn1.ASN1Integer;
import org.spongycastle.asn1.DLSequence;
import org.spongycastle.asn1.sec.SECNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;
import org.spongycastle.asn1.x9.X9IntegerConverter;
import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
import org.spongycastle.crypto.digests.SHA256Digest;
import org.spongycastle.crypto.engines.AESFastEngine;
import org.spongycastle.crypto.modes.SICBlockCipher;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import org.spongycastle.crypto.signers.ECDSASigner;
import org.spongycastle.crypto.signers.HMacDSAKCalculator;
import org.spongycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.spongycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.spongycastle.jce.spec.ECParameterSpec;
import org.spongycastle.jce.spec.ECPrivateKeySpec;
import org.spongycastle.jce.spec.ECPublicKeySpec;
import org.spongycastle.math.ec.ECAlgorithms;
import org.spongycastle.math.ec.ECCurve.Fp;
import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.util.BigIntegers;
import org.spongycastle.util.encoders.Base64;
import org.spongycastle.util.encoders.Hex;

import java.io.IOException;
import java.io.Serializable;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;

import javax.crypto.KeyAgreement;
public class ECKey implements Serializable {
   static {
       Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
   }
   public static final ECDomainParameters CURVE;
   public static final ECParameterSpec CURVE_SPEC;
   public static final BigInteger HALF_CURVE_ORDER;
   private static final SecureRandom secureRandom;
   private static final long serialVersionUID = -728224901792295832L;
   private final PrivateKey privKey;
   protected final ECPoint pub;
   private final Provider provider;
   private transient byte[] pubKeyHash;
   private transient byte[] nodeId;

   public ECKey() {
       this(secureRandom);
   }

   private static ECPoint extractPublicKey(ECPublicKey ecPublicKey) {
       java.security.spec.ECPoint publicPointW = ecPublicKey.getW();
       BigInteger xCoord = publicPointW.getAffineX();
       BigInteger yCoord = publicPointW.getAffineY();
       return CURVE.getCurve().createPoint(xCoord, yCoord);
   }

   public ECKey(Provider provider, SecureRandom secureRandom) {
       this.provider = provider;
       KeyPairGenerator keyPairGen = ECKeyPairGenerator.getInstance(provider, secureRandom);
       KeyPair keyPair = keyPairGen.generateKeyPair();
       this.privKey = keyPair.getPrivate();
       PublicKey pubKey = keyPair.getPublic();
       if(pubKey instanceof BCECPublicKey) {
           this.pub = ((BCECPublicKey)pubKey).getQ();
       } else {
           if(!(pubKey instanceof ECPublicKey)) {
               throw new AssertionError("Expected Provider " + provider.getName() + " to produce a subtype of ECPublicKey, found " + pubKey.getClass());
           }

           this.pub = extractPublicKey((ECPublicKey)pubKey);
       }

   }

   public ECKey(SecureRandom secureRandom) {
       this(new org.spongycastle.jce.provider.BouncyCastleProvider(), secureRandom);
   }

   private static boolean isECPrivateKey(PrivateKey privKey) {
       return privKey instanceof ECPrivateKey || privKey.getAlgorithm().equals("EC");
   }

   public ECKey(Provider provider,  PrivateKey privKey, ECPoint pub) {
       this.provider = provider;
       if(privKey != null && !isECPrivateKey(privKey)) {
           throw new IllegalArgumentException("Expected EC private key, given a private key object with class " + privKey.getClass().toString() + " and algorithm " + privKey.getAlgorithm());
       } else {
           this.privKey = privKey;
           if(pub == null) {
               throw new IllegalArgumentException("Public key may not be null");
           } else {
               this.pub = pub;
           }
       }
   }

   private static PrivateKey privateKeyFromBigInteger(BigInteger priv) {
       if(priv == null) {
           return null;
       } else {
           try {
               return ECKeyFactory.getInstance(new org.spongycastle.jce.provider.BouncyCastleProvider()).generatePrivate(new ECPrivateKeySpec(priv, CURVE_SPEC));
           } catch (InvalidKeySpecException var2) {
               throw new AssertionError("Assumed correct key spec statically");
           }
       }
   }

   public ECKey(@Nullable BigInteger priv, ECPoint pub) {
       this(new org.spongycastle.jce.provider.BouncyCastleProvider(), privateKeyFromBigInteger(priv), pub);
   }

   /** @deprecated */
   public static ECPoint compressPoint(ECPoint uncompressed) {
       return CURVE.getCurve().decodePoint(uncompressed.getEncoded(true));
   }

   /** @deprecated */
   public static ECPoint decompressPoint(ECPoint compressed) {
       return CURVE.getCurve().decodePoint(compressed.getEncoded(false));
   }

   public static ECKey fromPrivate(BigInteger privKey) {
       return new ECKey(privKey, CURVE.getG().multiply(privKey));
   }

   public static ECKey fromPrivate(byte[] privKeyBytes) {
       return fromPrivate(new BigInteger(1, privKeyBytes));
   }

   public static ECKey fromPrivateAndPrecalculatedPublic(BigInteger priv, ECPoint pub) {
       return new ECKey(priv, pub);
   }

   public static ECKey fromPrivateAndPrecalculatedPublic(byte[] priv, byte[] pub) {
       check(priv != null, "Private key must not be null");
       check(pub != null, "Public key must not be null");
       return new ECKey(new BigInteger(1, priv), CURVE.getCurve().decodePoint(pub));
   }

   public static ECKey fromPublicOnly(ECPoint pub) {
       return new ECKey((BigInteger)null, pub);
   }

   public static ECKey fromPublicOnly(byte[] pub) {
       return new ECKey((BigInteger)null, CURVE.getCurve().decodePoint(pub));
   }

   /** @deprecated */
   public ECKey decompress() {
       return !this.pub.isCompressed()?this:new ECKey(this.provider, this.privKey, decompressPoint(this.pub));
   }

   /** @deprecated */
   public ECKey compress() {
       return this.pub.isCompressed()?this:new ECKey(this.provider, this.privKey, compressPoint(this.pub));
   }

   public boolean isPubKeyOnly() {
       return this.privKey == null;
   }

   public boolean hasPrivKey() {
       return this.privKey != null;
   }

   public static byte[] publicKeyFromPrivate(BigInteger privKey, boolean compressed) {
       ECPoint point = CURVE.getG().multiply(privKey);
       return point.getEncoded(compressed);
   }

   public static byte[] computeAddress(byte[] pubBytes) {
       return HashUtil.sha3omit12(Arrays.copyOfRange(pubBytes, 1, pubBytes.length));
   }

   public static byte[] computeAddress(ECPoint pubPoint) {
       return computeAddress(pubPoint.getEncoded(false));
   }

   public byte[] getAddress() {
       if(this.pubKeyHash == null) {
           this.pubKeyHash = computeAddress(this.pub);
       }

       return this.pubKeyHash;
   }

   public static byte[] pubBytesWithoutFormat(ECPoint pubPoint) {
       byte[] pubBytes = pubPoint.getEncoded(false);
       return Arrays.copyOfRange(pubBytes, 1, pubBytes.length);
   }

   public byte[] getNodeId() {
       if(this.nodeId == null) {
           this.nodeId = pubBytesWithoutFormat(this.pub);
       }

       return this.nodeId;
   }

   public static ECKey fromNodeId(byte[] nodeId) {
       check(nodeId.length == 64, "Expected a 64 byte node id");
       byte[] pubBytes = new byte[65];
       System.arraycopy(nodeId, 0, pubBytes, 1, nodeId.length);
       pubBytes[0] = 4;
       return fromPublicOnly(pubBytes);
   }

   public byte[] getPubKey() {
       return this.pub.getEncoded(false);
   }

   public ECPoint getPubKeyPoint() {
       return this.pub;
   }

   public BigInteger getPrivKey() {
       if(this.privKey == null) {
           throw new ECKey.MissingPrivateKeyException();
       } else if(this.privKey instanceof BCECPrivateKey) {
           return ((BCECPrivateKey)this.privKey).getD();
       } else {
           throw new ECKey.MissingPrivateKeyException();
       }
   }

   public boolean isCompressed() {
       return this.pub.isCompressed();
   }

   public String toString() {
       StringBuilder b = new StringBuilder();
       b.append("pub:").append(Hex.toHexString(this.pub.getEncoded(false)));
       return b.toString();
   }

   public String toStringWithPrivate() {
       StringBuilder b = new StringBuilder();
       b.append(this.toString());
       if(this.privKey != null && this.privKey instanceof BCECPrivateKey) {
           b.append(" priv:").append(Hex.toHexString(((BCECPrivateKey)this.privKey).getD().toByteArray()));
       }

       return b.toString();
   }

   public ECKey.ECDSASignature doSign(byte[] input) {
       if(input.length != 32) {
           throw new IllegalArgumentException("Expected 32 byte input to ECDSA signature, not " + input.length);
       } else if(this.privKey == null) {
           throw new ECKey.MissingPrivateKeyException();
       } else if(this.privKey instanceof BCECPrivateKey) {
           ECDSASigner ex1 = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
           ECPrivateKeyParameters derSignature1 = new ECPrivateKeyParameters(((BCECPrivateKey)this.privKey).getD(), CURVE);
           ex1.init(true, derSignature1);
           BigInteger[] components = ex1.generateSignature(input);
           return (new ECKey.ECDSASignature(components[0], components[1])).toCanonicalised();
       } else {
           try {
               Signature ex = ECSignatureFactory.getRawInstance(this.provider);
               ex.initSign(this.privKey);
               ex.update(input);
               byte[] derSignature = ex.sign();
               return ECKey.ECDSASignature.decodeFromDER(derSignature).toCanonicalised();
           } catch (InvalidKeyException | SignatureException var5) {
               throw new RuntimeException("ECKey signing error", var5);
           }
       }
   }

   public ECKey.ECDSASignature sign(byte[] messageHash) {
       ECKey.ECDSASignature sig = this.doSign(messageHash);
       int recId = -1;
       byte[] thisKey = this.pub.getEncoded(false);

       for(int i = 0; i < 4; ++i) {
           byte[] k = recoverPubBytesFromSignature(i, sig, messageHash);
           if(k != null && Arrays.equals(k, thisKey)) {
               recId = i;
               break;
           }
       }

       if(recId == -1) {
           throw new RuntimeException("Could not construct a recoverable key. This should never happen.");
       } else {
           sig.v = (byte)(recId + 27);
           return sig;
       }
   }

   public static byte[] signatureToKeyBytes(byte[] messageHash, String signatureBase64) throws SignatureException {
       byte[] signatureEncoded;
       try {
           signatureEncoded = Base64.decode(signatureBase64);
       } catch (RuntimeException var4) {
           throw new SignatureException("Could not decode base64", var4);
       }

       if(signatureEncoded.length < 65) {
           throw new SignatureException("Signature truncated, expected 65 bytes and got " + signatureEncoded.length);
       } else {
           return signatureToKeyBytes(messageHash, ECKey.ECDSASignature.fromComponents(Arrays.copyOfRange(signatureEncoded, 1, 33), Arrays.copyOfRange(signatureEncoded, 33, 65), (byte)(signatureEncoded[0] & 255)));
       }
   }

   public static byte[] signatureToKeyBytes(byte[] messageHash, ECKey.ECDSASignature sig) throws SignatureException {
       check(messageHash.length == 32, "messageHash argument has length " + messageHash.length);
       int header = sig.v;
       if(header >= 27 && header <= 34) {
           if(header >= 31) {
               header -= 4;
           }

           int recId = header - 27;
           byte[] key = recoverPubBytesFromSignature(recId, sig, messageHash);
           if(key == null) {
               throw new SignatureException("Could not recover public key from signature");
           } else {
               return key;
           }
       } else {
           throw new SignatureException("Header byte out of range: " + header);
       }
   }

   public static byte[] signatureToAddress(byte[] messageHash, String signatureBase64) throws SignatureException {
       return computeAddress(signatureToKeyBytes(messageHash, signatureBase64));
   }

   public static byte[] signatureToAddress(byte[] messageHash, ECKey.ECDSASignature sig) throws SignatureException {
       return computeAddress(signatureToKeyBytes(messageHash, sig));
   }

   public static ECKey signatureToKey(byte[] messageHash, String signatureBase64) throws SignatureException {
       byte[] keyBytes = signatureToKeyBytes(messageHash, signatureBase64);
       return fromPublicOnly(keyBytes);
   }

   public static ECKey signatureToKey(byte[] messageHash, ECKey.ECDSASignature sig) throws SignatureException {
       byte[] keyBytes = signatureToKeyBytes(messageHash, sig);
       return fromPublicOnly(keyBytes);
   }

   public BigInteger keyAgreement(ECPoint otherParty) {
       if(this.privKey == null) {
           throw new ECKey.MissingPrivateKeyException();
       } else if(this.privKey instanceof BCECPrivateKey) {
           ECDHBasicAgreement ex1 = new ECDHBasicAgreement();
           ex1.init(new ECPrivateKeyParameters(((BCECPrivateKey)this.privKey).getD(), CURVE));
           return ex1.calculateAgreement(new ECPublicKeyParameters(otherParty, CURVE));
       } else {
           try {
               KeyAgreement ex = ECKeyAgreement.getInstance(this.provider);
               ex.init(this.privKey);
               ex.doPhase(ECKeyFactory.getInstance(this.provider).generatePublic(new ECPublicKeySpec(otherParty, CURVE_SPEC)), true);
               return new BigInteger(1, ex.generateSecret());
           } catch (InvalidKeyException | InvalidKeySpecException | IllegalStateException var3) {
               throw new RuntimeException("ECDH key agreement failure", var3);
           }
       }
   }

   /** @deprecated */
   public byte[] decryptAES(byte[] cipher) {
       if(this.privKey == null) {
           throw new ECKey.MissingPrivateKeyException();
       } else if(!(this.privKey instanceof BCECPrivateKey)) {
           throw new UnsupportedOperationException("Cannot use the private key as an AES key");
       } else {
           AESFastEngine engine = new AESFastEngine();
           SICBlockCipher ctrEngine = new SICBlockCipher(engine);
           KeyParameter key = new KeyParameter(BigIntegers.asUnsignedByteArray(((BCECPrivateKey)this.privKey).getD()));
           ParametersWithIV params = new ParametersWithIV(key, new byte[16]);
           ctrEngine.init(false, params);
           int i = 0;
           byte[] out = new byte[cipher.length];

           while(i < cipher.length) {
               ctrEngine.processBlock(cipher, i, out, i);
               i += engine.getBlockSize();
               if(cipher.length - i < engine.getBlockSize()) {
                   break;
               }
           }

           if(cipher.length - i > 0) {
               byte[] tmpBlock = new byte[16];
               System.arraycopy(cipher, i, tmpBlock, 0, cipher.length - i);
               ctrEngine.processBlock(tmpBlock, 0, tmpBlock, 0);
               System.arraycopy(tmpBlock, 0, out, i, cipher.length - i);
           }

           return out;
       }
   }

   public static boolean verify(byte[] data, ECKey.ECDSASignature signature, byte[] pub) {
       ECDSASigner signer = new ECDSASigner();
       ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub), CURVE);
       signer.init(false, params);

       try {
           return signer.verifySignature(data, signature.r, signature.s);
       } catch (NullPointerException var6) {
           return false;
       }
   }

   public static boolean verify(byte[] data, byte[] signature, byte[] pub) {
       return verify(data, ECKey.ECDSASignature.decodeFromDER(signature), pub);
   }

   public boolean verify(byte[] data, byte[] signature) {
       return verify(data, signature, this.getPubKey());
   }

   public boolean verify(byte[] sigHash, ECKey.ECDSASignature signature) {
       return verify(sigHash, signature, this.getPubKey());
   }

   public boolean isPubKeyCanonical() {
       return isPubKeyCanonical(this.pub.getEncoded(false));
   }

   public static boolean isPubKeyCanonical(byte[] pubkey) {
       if(pubkey[0] == 4) {
           if(pubkey.length != 65) {
               return false;
           }
       } else {
           if(pubkey[0] != 2 && pubkey[0] != 3) {
               return false;
           }

           if(pubkey.length != 33) {
               return false;
           }
       }

       return true;
   }

   @Nullable
   public static byte[] recoverPubBytesFromSignature(int recId, ECKey.ECDSASignature sig, byte[] messageHash) {
       check(recId >= 0, "recId must be positive");
       check(sig.r.signum() >= 0, "r must be positive");
       check(sig.s.signum() >= 0, "s must be positive");
       check(messageHash != null, "messageHash must not be null");
       BigInteger n = CURVE.getN();
       BigInteger i = BigInteger.valueOf((long)recId / 2L);
       BigInteger x = sig.r.add(i.multiply(n));
       Fp curve = (Fp)CURVE.getCurve();
       BigInteger prime = curve.getQ();
       if(x.compareTo(prime) >= 0) {
           return null;
       } else {
           ECPoint R = decompressKey(x, (recId & 1) == 1);
           if(!R.multiply(n).isInfinity()) {
               return null;
           } else {
               BigInteger e = new BigInteger(1, messageHash);
               BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n);
               BigInteger rInv = sig.r.modInverse(n);
               BigInteger srInv = rInv.multiply(sig.s).mod(n);
               BigInteger eInvrInv = rInv.multiply(eInv).mod(n);
               org.spongycastle.math.ec.ECPoint.Fp q = (org.spongycastle.math.ec.ECPoint.Fp)ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, R, srInv);
               return q.getEncoded(false);
           }
       }
   }

   @Nullable
   public static byte[] recoverAddressFromSignature(int recId, ECKey.ECDSASignature sig, byte[] messageHash) {
       byte[] pubBytes = recoverPubBytesFromSignature(recId, sig, messageHash);
       return pubBytes == null?null:computeAddress(pubBytes);
   }

   @Nullable
   public static ECKey recoverFromSignature(int recId, ECKey.ECDSASignature sig, byte[] messageHash) {
       byte[] pubBytes = recoverPubBytesFromSignature(recId, sig, messageHash);
       return pubBytes == null?null:fromPublicOnly(pubBytes);
   }

   private static ECPoint decompressKey(BigInteger xBN, boolean yBit) {
       X9IntegerConverter x9 = new X9IntegerConverter();
       byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE.getCurve()));
       compEnc[0] = (byte)(yBit?3:2);
       return CURVE.getCurve().decodePoint(compEnc);
   }

   @Nullable
   public byte[] getPrivKeyBytes() {
       return this.privKey == null?null:(this.privKey instanceof BCECPrivateKey?ByteUtil.bigIntegerToBytes(((BCECPrivateKey)this.privKey).getD(), 32):null);
   }

   public boolean equals(Object o) {
       if(this == o) {
           return true;
       } else if(o != null && o instanceof ECKey) {
           ECKey ecKey = (ECKey)o;
           return this.privKey != null && !this.privKey.equals(ecKey.privKey)?false:this.pub == null || this.pub.equals(ecKey.pub);
       } else {
           return false;
       }
   }

   public int hashCode() {
       return Arrays.hashCode(this.getPubKey());
   }

   private static void check(boolean test, String message) {
       if(!test) {
           throw new IllegalArgumentException(message);
       }
   }

   static {
       X9ECParameters params = SECNamedCurves.getByName("secp256k1");
       CURVE = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH());
       CURVE_SPEC = new ECParameterSpec(params.getCurve(), params.getG(), params.getN(), params.getH());
       HALF_CURVE_ORDER = params.getN().shiftRight(1);
       secureRandom = new SecureRandom();
   }

   public static class MissingPrivateKeyException extends RuntimeException {
       public MissingPrivateKeyException() {
       }
   }

   public static class ECDSASignature {
       public final BigInteger r;
       public final BigInteger s;
       public byte v;

       public ECDSASignature(BigInteger r, BigInteger s) {
           this.r = r;
           this.s = s;
       }

       private static ECKey.ECDSASignature fromComponents(byte[] r, byte[] s) {
           return new ECKey.ECDSASignature(new BigInteger(1, r), new BigInteger(1, s));
       }

       public static ECKey.ECDSASignature fromComponents(byte[] r, byte[] s, byte v) {
           ECKey.ECDSASignature signature = fromComponents(r, s);
           signature.v = v;
           return signature;
       }

       public boolean validateComponents() {
           return validateComponents(this.r, this.s, this.v);
       }

       public static boolean validateComponents(BigInteger r, BigInteger s, byte v) {
           return v != 27 && v != 28?false:(BIUtil.isLessThan(r, BigInteger.ONE)?false:(BIUtil.isLessThan(s, BigInteger.ONE)?false:(!BIUtil.isLessThan(r, Constants.getSECP256K1N())?false:BIUtil.isLessThan(s, Constants.getSECP256K1N()))));
       }

       public static ECKey.ECDSASignature decodeFromDER(byte[] bytes) {
           ASN1InputStream decoder = null;

           ECKey.ECDSASignature e1;
           try {
               decoder = new ASN1InputStream(bytes);
               DLSequence e = (DLSequence)decoder.readObject();
               if(e == null) {
                   throw new RuntimeException("Reached past end of ASN.1 stream.");
               }

               ASN1Integer r;
               ASN1Integer s;
               try {
                   r = (ASN1Integer)e.getObjectAt(0);
                   s = (ASN1Integer)e.getObjectAt(1);
               } catch (ClassCastException var15) {
                   throw new IllegalArgumentException(var15);
               }

               e1 = new ECKey.ECDSASignature(r.getPositiveValue(), s.getPositiveValue());
           } catch (IOException var16) {
               throw new RuntimeException(var16);
           } finally {
               if(decoder != null) {
                   try {
                       decoder.close();
                   } catch (IOException var14) {
                       ;
                   }
               }

           }

           return e1;
       }

       public ECKey.ECDSASignature toCanonicalised() {
           return this.s.compareTo(ECKey.HALF_CURVE_ORDER) > 0?new ECKey.ECDSASignature(this.r, ECKey.CURVE.getN().subtract(this.s)):this;
       }

       public String toBase64() {
           byte[] sigData = new byte[65];
           sigData[0] = this.v;
           System.arraycopy(ByteUtil.bigIntegerToBytes(this.r, 32), 0, sigData, 1, 32);
           System.arraycopy(ByteUtil.bigIntegerToBytes(this.s, 32), 0, sigData, 33, 32);
           return new String(Base64.encode(sigData), Charset.forName("UTF-8"));
       }

       public boolean equals(Object o) {
           if(this == o) {
               return true;
           } else if(o != null && this.getClass() == o.getClass()) {
               ECKey.ECDSASignature signature = (ECKey.ECDSASignature)o;
               return !this.r.equals(signature.r)?false:this.s.equals(signature.s);
           } else {
               return false;
           }
       }

       public int hashCode() {
           int result = this.r.hashCode();
           result = 31 * result + this.s.hashCode();
           return result;
       }
   }
}

要在您的應用程序中真正實現這一點,請嘗試以下操作:

       ECKey key = new com.your.package.ECKey();
       byte[] addr = key.getAddress();
       byte[] priv = key.getPrivKeyBytes();
       String addrBase16 = Hex.toHexString(addr);
       String privBase16 = Hex.toHexString(priv);
       Log.d("address",addrBase16);
       Log.d("priv",privBase16);

引用自:https://ethereum.stackexchange.com/questions/6673