Ejemplo n.º 1
0
  /**
   * return a parameter spec representing the passed in named curve. The routine returns null if the
   * curve is not present.
   *
   * @param name the name of the curve requested
   * @return a parameter spec for the curve, null if it is not available.
   */
  public static ECNamedCurveParameterSpec getParameterSpec(String name) {
    X9ECParameters ecP = org.spongycastle.crypto.ec.CustomNamedCurves.getByName(name);
    if (ecP == null) {
      try {
        ecP = org.spongycastle.crypto.ec.CustomNamedCurves.getByOID(new ASN1ObjectIdentifier(name));
      } catch (IllegalArgumentException e) {
        // ignore - not an oid
      }

      if (ecP == null) {
        ecP = org.spongycastle.asn1.x9.ECNamedCurveTable.getByName(name);
        if (ecP == null) {
          try {
            ecP =
                org.spongycastle.asn1.x9.ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(name));
          } catch (IllegalArgumentException e) {
            // ignore - not an oid
          }
        }
      }
    }

    if (ecP == null) {
      return null;
    }

    return new ECNamedCurveParameterSpec(
        name, ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed());
  }
Ejemplo n.º 2
0
/** Source code copied from Mike Hearn's BitcoinJ. */
public class ECKey {
  private static final Logger log = LoggerFactory.getLogger(ECKey.class);

  /**
   * Verifies the given ECDSA signature against the message bytes using the public key bytes.
   *
   * <p>When using native ECDSA verification, data must be 32 bytes, and no element may be larger
   * than 520 bytes.
   *
   * @param data Hash of the data to verify.
   * @param signature ASN.1 encoded signature.
   * @param pub The public key bytes to use.
   */
  public static boolean verify(byte[] data, 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 e) {
      // Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures. Those
      // signatures
      // are inherently invalid/attack sigs so we just fail them here rather than crash the thread.
      log.error("Caught NPE inside bouncy castle");
      e.printStackTrace();
      return false;
    }
  }

  // The parameters of the secp256k1 curve that Bitcoin uses.
  private static final X9ECParameters CURVE_PARAMS = CustomNamedCurves.getByName("secp256k1");

  /** The parameters of the secp256k1 curve that Bitcoin uses. */
  public static final ECDomainParameters CURVE;
  /**
   * Equal to CURVE.getN().shiftRight(1), used for canonicalising the S value of a signature. If you
   * aren't sure what this is about, you can ignore it.
   */
  public static final BigInteger HALF_CURVE_ORDER;

  static {
    // Tell Bouncy Castle to precompute data that's needed during secp256k1 calculations. Increasing
    // the width
    // number makes calculations faster, but at a cost of extra memory usage and with decreasing
    // returns. 12 was
    // picked after consulting with the BC team.
    FixedPointUtil.precompute(CURVE_PARAMS.getG(), 12);
    CURVE =
        new ECDomainParameters(
            CURVE_PARAMS.getCurve(), CURVE_PARAMS.getG(), CURVE_PARAMS.getN(), CURVE_PARAMS.getH());
    HALF_CURVE_ORDER = CURVE_PARAMS.getN().shiftRight(1);
  }

  /**
   * Groups the two components that make up a signature, and provides a way to encode to DER form,
   * which is how ECDSA signatures are represented when embedded in other data structures in the
   * Bitcoin protocol. The raw components can be useful for doing further EC maths on them.
   */
  public static class ECDSASignature {
    /** The two components of the signature. */
    public final BigInteger r, s;

    /**
     * Constructs a signature with the given components. Does NOT automatically canonicalise the
     * signature.
     */
    public ECDSASignature(BigInteger r, BigInteger s) {
      this.r = r;
      this.s = s;
    }

    /**
     * Returns true if the S component is "low", that means it is below {@link
     * ECKey#HALF_CURVE_ORDER}. See <a
     * href="https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#Low_S_values_in_signatures">BIP62</a>.
     */
    public boolean isCanonical() {
      return s.compareTo(HALF_CURVE_ORDER) <= 0;
    }

    /**
     * Will automatically adjust the S component to be less than or equal to half the curve order,
     * if necessary. This is required because for every signature (r,s) the signature (r, -s (mod
     * N)) is a valid signature of the same message. However, we dislike the ability to modify the
     * bits of a Bitcoin transaction after it's been signed, as that violates various assumed
     * invariants. Thus in future only one of those forms will be considered legal and the other
     * will be banned.
     */
    public ECDSASignature toCanonicalised() {
      if (!isCanonical()) {
        // The order of the curve is the number of valid points that exist on that curve. If S is in
        // the upper
        // half of the number of valid points, then bring it back to the lower half. Otherwise,
        // imagine that
        //    N = 10
        //    s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are valid solutions.
        //    10 - 8 == 2, giving us always the latter solution, which is canonical.
        return new ECDSASignature(r, CURVE.getN().subtract(s));
      } else {
        return this;
      }
    }

    /**
     * DER is an international standard for serializing data structures which is widely used in
     * cryptography. It's somewhat like protocol buffers but less convenient. This method returns a
     * standard DER encoding of the signature, as recognized by OpenSSL and other libraries.
     */
    public byte[] encodeToDER() {
      try {
        return derByteStream().toByteArray();
      } catch (IOException e) {
        throw new RuntimeException(e); // Cannot happen.
      }
    }

    public static ECDSASignature decodeFromDER(byte[] bytes) {
      ASN1InputStream decoder = null;
      try {
        decoder = new ASN1InputStream(bytes);
        DLSequence seq = (DLSequence) decoder.readObject();
        if (seq == null) throw new RuntimeException("Reached past end of ASN.1 stream.");
        ASN1Integer r, s;
        try {
          r = (ASN1Integer) seq.getObjectAt(0);
          s = (ASN1Integer) seq.getObjectAt(1);
        } catch (ClassCastException e) {
          throw new IllegalArgumentException(e);
        }
        // OpenSSL deviates from the DER spec by interpreting these values as unsigned, though they
        // should not be
        // Thus, we always use the positive versions. See: http://r6.ca/blog/20111119T211504Z.html
        return new ECDSASignature(r.getPositiveValue(), s.getPositiveValue());
      } catch (IOException e) {
        throw new RuntimeException(e);
      } finally {
        if (decoder != null)
          try {
            decoder.close();
          } catch (IOException x) {
          }
      }
    }

    protected ByteArrayOutputStream derByteStream() throws IOException {
      // Usually 70-72 bytes.
      ByteArrayOutputStream bos = new ByteArrayOutputStream(72);
      DERSequenceGenerator seq = new DERSequenceGenerator(bos);
      seq.addObject(new ASN1Integer(r));
      seq.addObject(new ASN1Integer(s));
      seq.close();
      return bos;
    }

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

    @Override
    public int hashCode() {
      return Objects.hash(r, s);
    }

    public static boolean isEncodingCanonical(byte[] signature) {
      // See reference client's IsCanonicalSignature,
      // https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
      // A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S>
      // <hashtype>
      // Where R and S are not negative (their first byte has its highest bit not set), and not
      // excessively padded (do not start with a 0 byte, unless an otherwise negative number
      // follows,
      // in which case a single 0 byte is necessary and even required).
      if (signature.length < 9 || signature.length > 73) return false;

      // BUGBUG : ANYONECANPAY was byte type, but changed it to int. Make sure it is OK.
      int hashType =
          signature[signature.length - 1] & ~TransactionSigHash$.MODULE$.HASH_TYPE_MASK();
      if (hashType < (TransactionSigHash$.MODULE$.ALL())
          || hashType > (TransactionSigHash$.MODULE$.SINGLE())) return false;

      //                   "wrong type"                  "wrong length marker"
      if ((signature[0] & 0xff) != 0x30 || (signature[1] & 0xff) != signature.length - 3)
        return false;

      int lenR = signature[3] & 0xff;
      if (5 + lenR >= signature.length || lenR == 0) return false;
      int lenS = signature[5 + lenR] & 0xff;
      if (lenR + lenS + 7 != signature.length || lenS == 0) return false;

      //    R value type mismatch          R value negative
      if (signature[4 - 2] != 0x02 || (signature[4] & 0x80) == 0x80) return false;
      if (lenR > 1 && signature[4] == 0x00 && (signature[4 + 1] & 0x80) != 0x80)
        return false; // R value excessively padded

      //       S value type mismatch                    S value negative
      if (signature[6 + lenR - 2] != 0x02 || (signature[6 + lenR] & 0x80) == 0x80) return false;
      if (lenS > 1 && signature[6 + lenR] == 0x00 && (signature[6 + lenR + 1] & 0x80) != 0x80)
        return false; // S value excessively padded
      return true;
    }
  }
}