Создание закрытого ключа Ethereum, открытого ключа на мобильном устройстве (Android/Java)

Я ищу способ генерировать закрытые и открытые ключи Ethereum внутри приложения для Android. Я порылся в Интернете и в конце концов решил разобрать код на myetherwallet, импортировать те же библиотеки Javascript в Android/Java и запустить их там. Однако это кажется чрезвычайно громоздким.

У кого-нибудь есть фрагмент кода для создания пар закрытый/открытый ключ для Ethereum в Android?

К сожалению, было много несовместимостей, которые сделали это нетривиальным. спасибо, что помогли мне добраться туда, хотя

Ответы (2)

1) Следуйте инструкциям во втором ответе, чтобы реализовать spongycastle на Android. https://stackoverflow.com/questions/6898801/how-to-include-the-spongy-castle-jar-in-android

2) Загрузите и импортируйте банку журнала slfj4 http://www.slf4j.org/android/

3) Загрузите последнюю версию jar ethereumj. Убедитесь, что вы сначала перечислили jar-файлы spongycastle в зависимостях build.gradle, затем slf4j, а затем ethereumj.

4) Вам нужно будет создать новые классы Эфириума, используя губчатый замок вместо надувного замка. Вот класс, который я использовал для создания закрытых ключей, их подписи и т. д. Это просто модифицированная версия ECKey.class ethereumj. Обратите внимание, что я включил 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);

Другой вариант — использовать версию BouncyCastle для .NET и включить ее в проект Xamarin.