Coverage Summary for Class: ECKey (org.ethereum.crypto)

Class Method, % Line, %
ECKey 42.9% (15/35) 42.5% (51/120)
ECKey$ECDSASignature 22.2% (2/9) 24.1% (7/29)
ECKey$MissingPrivateKeyException 0% (0/1) 0% (0/1)
Total 37.8% (17/45) 38.7% (58/150)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2017 RSK Labs Ltd. 4  * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>) 5  * 6  * This program is free software: you can redistribute it and/or modify 7  * it under the terms of the GNU Lesser General Public License as published by 8  * the Free Software Foundation, either version 3 of the License, or 9  * (at your option) any later version. 10  * 11  * This program is distributed in the hope that it will be useful, 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14  * GNU Lesser General Public License for more details. 15  * 16  * You should have received a copy of the GNU Lesser General Public License 17  * along with this program. If not, see <http://www.gnu.org/licenses/>. 18  */ 19  20 package org.ethereum.crypto; 21 /** 22  * Copyright 2011 Google Inc. 23  * 24  * Licensed under the Apache License, Version 2.0 (the "License"); 25  * you may not use this file except in compliance with the License. 26  * You may obtain a copy of the License at 27  * 28  * http://www.apache.org/licenses/LICENSE-2.0 29  * 30  * Unless required by applicable law or agreed to in writing, software 31  * distributed under the License is distributed on an "AS IS" BASIS, 32  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 33  * See the License for the specific language governing permissions and 34  * limitations under the License. 35  */ 36  37 import org.bouncycastle.asn1.sec.SECNamedCurves; 38 import org.bouncycastle.asn1.x9.X9ECParameters; 39 import org.bouncycastle.crypto.AsymmetricCipherKeyPair; 40 import org.bouncycastle.crypto.digests.SHA256Digest; 41 import org.bouncycastle.crypto.engines.AESEngine; 42 import org.bouncycastle.crypto.generators.ECKeyPairGenerator; 43 import org.bouncycastle.crypto.modes.SICBlockCipher; 44 import org.bouncycastle.crypto.params.*; 45 import org.bouncycastle.crypto.signers.ECDSASigner; 46 import org.bouncycastle.crypto.signers.HMacDSAKCalculator; 47 import org.bouncycastle.math.ec.ECPoint; 48 import org.bouncycastle.util.BigIntegers; 49 import org.ethereum.crypto.signature.Secp256k1; 50 import org.ethereum.util.ByteUtil; 51  52 import javax.annotation.Nullable; 53 import java.math.BigInteger; 54 import java.security.SecureRandom; 55 import java.security.SignatureException; 56 import java.util.Arrays; 57  58 import static org.ethereum.util.ByteUtil.bigIntegerToBytes; 59  60 /** 61  * <p>Represents an elliptic curve public and (optionally) private key, usable for digital signatures but not encryption. 62  * Creating a new ECKey with the empty constructor will generate a new random keypair. Other static methods can be used 63  * when you already have the public or private parts. If you create a key with only the public part, you can check 64  * signatures but not create them.</p> 65  * 66  * <p>The ECDSA algorithm supports <i>key recovery</i> in which a signature plus a couple of discriminator bits can 67  * be reversed to find the public key used to calculate it. This can be convenient when you have a message and a 68  * signature and want to find out who signed it, rather than requiring the user to provide the expected identity.</p> 69  * 70  * <p>A key can be <i>compressed</i> or <i>uncompressed</i>. This refers to whether the public key is represented 71  * when encoded into bytes as an (x, y) coordinate on the elliptic curve, or whether it's represented as just an X 72  * co-ordinate and an extra byte that carries a sign bit. With the latter form the Y coordinate can be calculated 73  * dynamically, however, <b>because the binary serialization is different the address of a key changes if its 74  * compression status is changed</b>. If you deviate from the defaults it's important to understand this: money sent 75  * to a compressed version of the key will have a different address to the same key in uncompressed form. Whether 76  * a public key is compressed or not is recorded in the SEC binary serialisation format, and preserved in a flag in 77  * this class so round-tripping preserves state. Unless you're working with old software or doing unusual things, you 78  * can usually ignore the compressed/uncompressed distinction.</p> 79  * 80  * This code is borrowed from the bitcoinj project and altered to fit Ethereum.<br> 81  * See <a href="https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/com/google/bitcoin/core/ECKey.java"> 82  * bitcoinj on GitHub</a>. 83  */ 84 public class ECKey { 85  86  /** 87  * The parameters of the secp256k1 curve that Ethereum uses. 88  */ 89  public static final ECDomainParameters CURVE; 90  91  /** 92  * Equal to CURVE.getN().shiftRight(1), used for canonicalising the S value of a signature. If you aren't 93  * sure what this is about, you can ignore it. 94  */ 95  public static final BigInteger HALF_CURVE_ORDER; 96  97  private static final SecureRandom secureRandom; 98  99  static { 100  // All clients must agree on the curve to use by agreement. Ethereum uses secp256k1. 101  X9ECParameters params = SECNamedCurves.getByName("secp256k1"); 102  CURVE = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); 103  HALF_CURVE_ORDER = params.getN().shiftRight(1); 104  secureRandom = new SecureRandom(); 105  } 106  107  // The two parts of the key. If "priv" is set, "pub" can always be calculated. If "pub" is set but not "priv", we 108  // can only verify signatures not make them. 109  // TODO: Redesign this class to use consistent internals and more efficient serialization. 110  private final BigInteger priv; 111  private final ECPoint pub; 112  113  // Transient because it's calculated on demand. 114  private byte[] pubKeyHash; 115  private byte[] nodeId; 116  117  /** 118  * Generates an entirely new keypair. Point compression is used so the resulting public key will be 33 bytes 119  * (32 for the co-ordinate and 1 byte to represent the y bit). 120  */ 121  public ECKey() { 122  this(secureRandom); 123  } 124  125  /** 126  * Generates an entirely new keypair with the given {@link SecureRandom} object. Point compression is used so the 127  * resulting public key will be 33 bytes (32 for the co-ordinate and 1 byte to represent the y bit). 128  * 129  * @param secureRandom - 130  */ 131  public ECKey(SecureRandom secureRandom) { 132  ECKeyPairGenerator generator = new ECKeyPairGenerator(); 133  ECKeyGenerationParameters keygenParams = new ECKeyGenerationParameters(CURVE, secureRandom); 134  generator.init(keygenParams); 135  AsymmetricCipherKeyPair keypair = generator.generateKeyPair(); 136  ECPrivateKeyParameters privParams = (ECPrivateKeyParameters) keypair.getPrivate(); 137  ECPublicKeyParameters pubParams = (ECPublicKeyParameters) keypair.getPublic(); 138  priv = privParams.getD(); 139  pub = CURVE.getCurve().decodePoint(pubParams.getQ().getEncoded(true)); 140  } 141  142  public ECKey(@Nullable BigInteger priv, ECPoint pub) { 143  this.priv = priv; 144  if (pub == null) { 145  throw new IllegalArgumentException("Public key may not be null"); 146  } 147  this.pub = pub; 148  } 149  150  /** 151  * Utility for compressing an elliptic curve point. Returns the same point if it's already compressed. 152  * See the ECKey class docs for a discussion of point compression. 153  * 154  * @param uncompressed - 155  * 156  * @return - 157  */ 158  public static ECPoint compressPoint(ECPoint uncompressed) { 159  return CURVE.getCurve().decodePoint(uncompressed.getEncoded(true)); 160  } 161  162  /** 163  * Utility for decompressing an elliptic curve point. Returns the same point if it's already compressed. 164  * See the ECKey class docs for a discussion of point compression. 165  * 166  * @param compressed - 167  * 168  * @return - 169  */ 170  public static ECPoint decompressPoint(ECPoint compressed) { 171  return CURVE.getCurve().decodePoint(compressed.getEncoded(false)); 172  } 173  174  /** 175  * Creates an ECKey given the private key only. The public key is calculated from it (this is slow). Note that 176  * the resulting public key is compressed. 177  * 178  * @param privKey - 179  * 180  * 181  * @return - 182  */ 183  public static ECKey fromPrivate(BigInteger privKey) { 184  return new ECKey(privKey, compressPoint(CURVE.getG().multiply(privKey))); 185  } 186  187  /** 188  * Creates an ECKey given the private key only. The public key is calculated from it (this is slow). The resulting 189  * public key is compressed. 190  * 191  * @param privKeyBytes - 192  * 193  * @return - 194  */ 195  public static ECKey fromPrivate(byte[] privKeyBytes) { 196  return fromPrivate(new BigInteger(1, privKeyBytes)); 197  } 198  199  /** 200  * Creates an ECKey that cannot be used for signing, only verifying signatures, from the given point. The 201  * compression state of pub will be preserved. 202  * 203  * @param pub - 204  * @return - 205  */ 206  public static ECKey fromPublicOnly(ECPoint pub) { 207  return new ECKey(null, pub); 208  } 209  210  /** 211  * Creates an ECKey that cannot be used for signing, only verifying signatures, from the given encoded point. 212  * The compression state of pub will be preserved. 213  * 214  * @param pub - 215  * @return - 216  */ 217  public static ECKey fromPublicOnly(byte[] pub) { 218  return new ECKey(null, CURVE.getCurve().decodePoint(pub)); 219  } 220  221  /** 222  * Returns a copy of this key, but with the public point represented in uncompressed form. Normally you would 223  * never need this: it's for specialised scenarios or when backwards compatibility in encoded form is necessary. 224  * 225  * @return - 226  */ 227  228  public ECKey decompress() { 229  return new ECKey(priv, decompressPoint(pub)); 230  } 231  232  /** 233  * Returns true if this key doesn't have access to private key bytes. This may be because it was never 234  * given any private key bytes to begin with (a watching key). 235  * 236  * @return - 237  */ 238  public boolean isPubKeyOnly() { 239  return priv == null; 240  } 241  242  /** 243  * Returns true if this key has access to private key bytes. Does the opposite of 244  * {@link #isPubKeyOnly()}. 245  * 246  * @return - 247  */ 248  public boolean hasPrivKey() { 249  return priv != null; 250  } 251  252  /** 253  * Returns public key bytes from the given private key. To convert a byte array into a BigInteger, use <tt> 254  * new BigInteger(1, bytes);</tt> 255  * 256  * @param privKey - 257  * @param compressed - 258  * @return - 259  */ 260  public static byte[] publicKeyFromPrivate(BigInteger privKey, boolean compressed) { 261  ECPoint point = CURVE.getG().multiply(privKey); 262  return point.getEncoded(compressed); 263  } 264  265  /** 266  * Gets the hash160 form of the public key (as seen in addresses). 267  * 268  * When we hash the PK to get the address -> Keccak256(PK), 269  * Some things are important: 270  * - 12 bytes are omitted, to get 20bytes for the address. 271  * - first byte of the public key is omitted (generally that byte is the format of the PK - 2/3/4) 272  * - In case of PoI when PK = [0], as the first byte is omitted, we hash an empty byte array. 273  * 274  * @return - 275  */ 276  public byte[] getAddress() { 277  if (pubKeyHash == null) { 278  byte[] pubBytes = this.pub.getEncoded(false); 279  pubKeyHash = HashUtil.keccak256Omit12(Arrays.copyOfRange(pubBytes, 1, pubBytes.length)); 280  } 281  return pubKeyHash; 282  } 283  284  /** 285  * Generates the NodeID based on this key, that is the public key without first format byte 286  */ 287  public byte[] getNodeId() { 288  if (nodeId == null) { 289  byte[] nodeIdWithFormat = getPubKey(); 290  nodeId = new byte[nodeIdWithFormat.length - 1]; 291  System.arraycopy(nodeIdWithFormat, 1, nodeId, 0, nodeId.length); 292  } 293  return nodeId; 294  } 295  296  /** 297  * Gets the raw public key value. This appears in transaction scriptSigs. Note that this is <b>not</b> the same 298  * as the pubKeyHash/address. 299  * 300  * @return - 301  */ 302  public byte[] getPubKey() { 303  return pub.getEncoded(false); 304  } 305  306  public byte[] getPubKey(boolean compressed) { 307  return pub.getEncoded(compressed); 308  } 309  310  /** 311  * Gets the public key in the form of an elliptic curve point object from Bouncy Castle. 312  * 313  * @return - 314  */ 315  public ECPoint getPubKeyPoint() { 316  return pub; 317  } 318  319  public boolean equalsPub(ECKey other) { 320  return this.pub.equals(other.pub); 321  } 322  323  /** 324  * Gets the private key in the form of an integer field element. The public key is derived by performing EC 325  * point addition this number of times (i.e. point multiplying). 326  * 327  * 328  * @return - 329  * 330  * @throws java.lang.IllegalStateException if the private key bytes are not available. 331  */ 332  public BigInteger getPrivKey() { 333  if (priv == null) { 334  throw new MissingPrivateKeyException(); 335  } 336  return priv; 337  } 338  339  public String toString() { 340  StringBuilder b = new StringBuilder(); 341  b.append("pub:").append(ByteUtil.toHexString(pub.getEncoded(false))); 342  return b.toString(); 343  } 344  345  /** 346  * Groups the two components that make up a signature, and provides a way to encode to Base64 form, which is 347  * how ECDSA signatures are represented when embedded in other data structures in the Ethereum protocol. The raw 348  * components can be useful for doing further EC maths on them. 349  * 350  * @deprecated( in favor of {@link org.ethereum.crypto.signature.ECDSASignature}) 351  */ 352  @Deprecated 353  public static class ECDSASignature { 354  /** 355  * The two components of the signature. 356  */ 357  public final BigInteger r; 358  public final BigInteger s; 359  public byte v; 360  361  /** 362  * Constructs a signature with the given components. Does NOT automatically canonicalise the signature. 363  * 364  * @param r - 365  * @param s - 366  */ 367  public ECDSASignature(BigInteger r, BigInteger s) { 368  this.r = r; 369  this.s = s; 370  } 371  372  /** 373  *t 374  * @param r 375  * @param s 376  * @return - 377  */ 378  private static ECDSASignature fromComponents(byte[] r, byte[] s) { 379  return new ECDSASignature(new BigInteger(1, r), new BigInteger(1, s)); 380  } 381  382  /** 383  * 384  * @param r - 385  * @param s - 386  * @param v - 387  * @return - 388  */ 389  public static ECDSASignature fromComponents(byte[] r, byte[] s, byte v) { 390  ECDSASignature signature = fromComponents(r, s); 391  signature.v = v; 392  return signature; 393  } 394  395  /** 396  * 397  * @param r - 398  * @param s - 399  * @param hash - the hash used to compute this signature 400  * @param pub - public key bytes, used to calculate the recovery byte 'v' 401  * @return - 402  */ 403  public static ECDSASignature fromComponentsWithRecoveryCalculation(byte[] r, byte[] s, byte[] hash, byte[] pub) { 404  return ECDSASignature.fromSignature(org.ethereum.crypto.signature.ECDSASignature.fromComponentsWithRecoveryCalculation(r, s, hash, pub)); 405  } 406  407  /** 408  * Only for compatibility should be removed with the entire deprecated class. 409  * @param sig 410  * @return 411  */ 412  private static ECDSASignature fromSignature(org.ethereum.crypto.signature.ECDSASignature sig) { 413  ECDSASignature result = new ECDSASignature(sig.getR(), sig.getS()); 414  result.v = sig.getV(); 415  return result; 416  } 417  418  public boolean validateComponents() { 419  return org.ethereum.crypto.signature.ECDSASignature.validateComponents(r, s, v); 420  } 421  422  /** 423  * Will automatically adjust the S component to be less than or equal to half the curve order, if necessary. 424  * This is required because for every signature (r,s) the signature (r, -s (mod N)) is a valid signature of 425  * the same message. However, we dislike the ability to modify the bits of a Ethereum transaction after it's 426  * been signed, as that violates various assumed invariants. Thus in future only one of those forms will be 427  * considered legal and the other will be banned. 428  * 429  * @return - 430  */ 431  public ECDSASignature toCanonicalised() { 432  if (s.compareTo(HALF_CURVE_ORDER) > 0) { 433  // The order of the curve is the number of valid points that exist on that curve. If S is in the upper 434  // half of the number of valid points, then bring it back to the lower half. Otherwise, imagine that 435  // N = 10 436  // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are valid solutions. 437  // 10 - 8 == 2, giving us always the latter solution, which is canonical. 438  return new ECDSASignature(r, CURVE.getN().subtract(s)); 439  } else { 440  return this; 441  } 442  } 443  444  @Override 445  public boolean equals(Object o) { 446  if (this == o) { 447  return true; 448  } 449  450  if (o == null || getClass() != o.getClass()) { 451  return false; 452  } 453  454  ECDSASignature signature = (ECDSASignature) o; 455  456  if (!r.equals(signature.r)) { 457  return false; 458  } 459  460  if (!s.equals(signature.s)) { 461  return false; 462  } 463  464  return true; 465  } 466  467  @Override 468  public int hashCode() { 469  int result = r.hashCode(); 470  result = 31 * result + s.hashCode(); 471  return result; 472  } 473  } 474  475  /** 476  * Signs the given hash and returns the R and S components as BigIntegers 477  * and put them in ECDSASignature 478  * 479  * @param input to sign 480  * @return ECDSASignature signature that contains the R and S components 481  */ 482  public ECDSASignature doSign(byte[] input) { 483  // No decryption of private key required. 484  if (priv == null) { 485  throw new MissingPrivateKeyException(); 486  } 487  ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())); 488  ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(priv, CURVE); 489  signer.init(true, privKey); 490  BigInteger[] components = signer.generateSignature(input); 491  return new ECDSASignature(components[0], components[1]).toCanonicalised(); 492  } 493  494  495  /** 496  * Takes the sha3 hash (32 bytes) of data and returns the ECDSA signature 497  * 498  * @param messageHash - 499  * @return - 500  * @throws IllegalStateException if this ECKey does not have the private part. 501  */ 502  public ECDSASignature sign(byte[] messageHash) { 503  if (priv == null) { 504  throw new MissingPrivateKeyException(); 505  } 506  ECDSASignature sig = doSign(messageHash); 507  // Now we have to work backwards to figure out the recId needed to recover the signature. 508  int recId = -1; 509  for (int i = 0; i < 4; i++) { 510  ECKey k = Secp256k1.getInstance().recoverFromSignature(i, org.ethereum.crypto.signature.ECDSASignature.fromSignature(sig), messageHash, false); 511  if (k != null && k.pub.equals(pub)) { 512  recId = i; 513  break; 514  } 515  } 516  if (recId == -1) { 517  throw new RuntimeException("Could not construct a recoverable key. This should never happen."); 518  } 519  sig.v = (byte) (recId + 27); 520  return sig; 521  } 522  523  524  /** 525  * Given a piece of text and a message signature encoded in base64, returns an ECKey 526  * containing the public key that was used to sign it. This can then be compared to the expected public key to 527  * determine if the signature was correct. 528  * 529  * @deprecated( in favor of {@link org.ethereum.crypto.signature.Secp256k1Service#signatureToKey(byte[], org.ethereum.crypto.signature.ECDSASignature)} ) 530  * 531  * @param messageHash a piece of human readable text that was signed 532  * @param signature The message signature 533  * 534  * @return - 535  * @throws java.security.SignatureException If the public key could not be recovered or if there was a signature format error. 536  */ 537  @Deprecated 538  public static ECKey signatureToKey(byte[] messageHash, ECDSASignature signature) throws SignatureException { 539  return Secp256k1.getInstance().signatureToKey(messageHash, org.ethereum.crypto.signature.ECDSASignature.fromSignature(signature)); 540  } 541  542  /** 543  * Decrypt cipher by AES in SIC(also know as CTR) mode 544  * 545  * @param cipher -proper cipher 546  * @return decrypted cipher, equal length to the cipher. 547  */ 548  public byte[] decryptAES(byte[] cipher){ 549  550  if (priv == null) { 551  throw new MissingPrivateKeyException(); 552  } 553  554  AESEngine engine = new AESEngine(); 555  SICBlockCipher ctrEngine = new SICBlockCipher(engine); 556  557  KeyParameter key = new KeyParameter(BigIntegers.asUnsignedByteArray(priv)); 558  ParametersWithIV params = new ParametersWithIV(key, new byte[16]); 559  560  ctrEngine.init(false, params); 561  562  int i = 0; 563  byte[] out = new byte[cipher.length]; 564  while(i < cipher.length){ 565  ctrEngine.processBlock(cipher, i, out, i); 566  i += engine.getBlockSize(); 567  if (cipher.length - i < engine.getBlockSize()) { 568  break; 569  } 570  } 571  572  // process left bytes 573  if (cipher.length - i > 0){ 574  byte[] tmpBlock = new byte[16]; 575  System.arraycopy(cipher, i, tmpBlock, 0, cipher.length - i); 576  ctrEngine.processBlock(tmpBlock, 0, tmpBlock, 0); 577  System.arraycopy(tmpBlock, 0, out, i, cipher.length - i); 578  } 579  580  return out; 581  } 582  583  584  585  /** 586  * <p>Verifies the given ECDSA signature against the message bytes using the public key bytes.</p> 587  * 588  * <p>When using native ECDSA verification, data must be 32 bytes, and no element may be 589  * larger than 520 bytes.</p> 590  * @deprecated( in favor of {@link org.ethereum.crypto.signature.Secp256k1Service#verify(byte[], org.ethereum.crypto.signature.ECDSASignature, byte[])}) 591  * 592  * @param data Hash of the data to verify. 593  * @param signature signature. 594  * @param pub The public key bytes to use. 595  * 596  * @return - 597  */ 598  @Deprecated 599  public static boolean verify(byte[] data, ECDSASignature signature, byte[] pub) { 600  return Secp256k1.getInstance().verify(data, org.ethereum.crypto.signature.ECDSASignature.fromSignature(signature), pub); 601  } 602  603  /** 604  * Verifies the given R/S pair (signature) against a hash using the public key. 605  * 606  * @deprecated( in favor of {@link #verify(byte[], org.ethereum.crypto.signature.ECDSASignature)}) 607  * 608  * @param sigHash - 609  * @param signature - 610  * @return - 611  */ 612  @Deprecated 613  public boolean verify(byte[] sigHash, ECDSASignature signature) { 614  return Secp256k1.getInstance().verify(sigHash, org.ethereum.crypto.signature.ECDSASignature.fromSignature(signature), getPubKey()); 615  } 616  617  /** 618  * Verifies the given R/S pair (signature) against a hash using the public key. 619  * 620  * @param sigHash - 621  * @param signature - 622  * @return - 623  */ 624  public boolean verify(byte[] sigHash, org.ethereum.crypto.signature.ECDSASignature signature) { 625  return Secp256k1.getInstance().verify(sigHash, signature, getPubKey()); 626  } 627  628  629  /** 630  * Returns true if this pubkey is canonical, i.e. the correct length taking into account compression. 631  * 632  * @return - 633  */ 634  public boolean isPubKeyCanonical() { 635  return isPubKeyCanonical(pub.getEncoded(false)); 636  } 637  638  639  /** 640  * Returns true if the given pubkey is canonical, i.e. the correct length taking into account compression. 641  * @param pubkey - 642  * @return - 643  */ 644  public static boolean isPubKeyCanonical(byte[] pubkey) { 645  if (pubkey[0] == 0x04) { 646  // Uncompressed pubkey 647  if (pubkey.length != 65) { 648  return false; 649  } 650  } else if (pubkey[0] == 0x02 || pubkey[0] == 0x03) { 651  // Compressed pubkey 652  if (pubkey.length != 33) { 653  return false; 654  } 655  } else { 656  return false; 657  } 658  return true; 659  } 660  661  /** 662  * <p>Given the components of a signature and a selector value, recover and return the public key 663  * that generated the signature according to the algorithm in SEC1v2 section 4.1.6.</p> 664  * 665  * <p>The recId is an index from 0 to 3 which indicates which of the 4 possible keys is the correct one. Because 666  * the key recovery operation yields multiple potential keys, the correct key must either be stored alongside the 667  * signature, or you must be willing to try each recId in turn until you find one that outputs the key you are 668  * expecting.</p> 669  * 670  * <p>If this method returns null it means recovery was not possible and recId should be iterated.</p> 671  * 672  * <p>Given the above two points, a correct usage of this method is inside a for loop from 0 to 3, and if the 673  * output is null OR a key that is not the one you expect, you try again with the next recId.</p> 674  * 675  * @deprecated (in favor of {@link org.ethereum.crypto.signature.Secp256k1Service#recoverFromSignature(int, org.ethereum.crypto.signature.ECDSASignature, byte[], boolean)} 676  * 677  * @param recId Which possible key to recover. 678  * @param sig the R and S components of the signature, wrapped. 679  * @param messageHash Hash of the data that was signed. 680  * @param compressed Whether or not the original pubkey was compressed. 681  * @return An ECKey containing only the public part, or null if recovery wasn't possible. 682  */ 683  @Deprecated 684  @Nullable 685  public static ECKey recoverFromSignature(int recId, ECDSASignature sig, byte[] messageHash, boolean compressed) { 686  return Secp256k1.getInstance().recoverFromSignature(recId, org.ethereum.crypto.signature.ECDSASignature.fromSignature(sig), messageHash, compressed); 687  } 688  689  /** 690  * Returns a 32 byte array containing the private key, or null if the key is encrypted or public only 691  * 692  * @return - 693  */ 694  @Nullable 695  public byte[] getPrivKeyBytes() { 696  return bigIntegerToBytes(priv, 32); 697  } 698  699  @Override 700  public boolean equals(Object o) { 701  if (this == o) { 702  return true; 703  } 704  705  if (o == null || !(o instanceof ECKey)) { 706  return false; 707  } 708  709  ECKey ecKey = (ECKey) o; 710  711  if (priv != null && !priv.equals(ecKey.priv)) { 712  return false; 713  } 714  715  if (pub != null && !pub.equals(ecKey.pub)) { 716  return false; 717  } 718  719  return true; 720  } 721  722  @Override 723  public int hashCode() { 724  // Public keys are random already so we can just use a part of them as the hashcode. Read from the start to 725  // avoid picking up the type code (compressed vs uncompressed) which is tacked on the end. 726  byte[] bits = getPubKey(true); 727  return (bits[0] & 0xFF) | ((bits[1] & 0xFF) << 8) | ((bits[2] & 0xFF) << 16) | ((bits[3] & 0xFF) << 24); 728  } 729  730  @SuppressWarnings("serial") 731  public static class MissingPrivateKeyException extends RuntimeException { 732  } 733  734 }