Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.bouncycastle.crypto.tls;
  
 
 
 public class TlsECCUtils
 {
     public static final Integer EXT_elliptic_curves = Integers.valueOf(.);
     public static final Integer EXT_ec_point_formats = Integers.valueOf(.);
 
     private static final String[] CURVE_NAMES = new String[] { "sect163k1""sect163r1""sect163r2""sect193r1",
         "sect193r2""sect233k1""sect233r1""sect239k1""sect283k1""sect283r1""sect409k1""sect409r1",
         "sect571k1""sect571r1""secp160k1""secp160r1""secp160r2""secp192k1""secp192r1""secp224k1",
         "secp224r1""secp256k1""secp256r1""secp384r1""secp521r1",
         "brainpoolP256r1""brainpoolP384r1""brainpoolP512r1"};
 
     public static void addSupportedEllipticCurvesExtension(Hashtable extensionsint[] namedCurvesthrows IOException
     {
         extensions.put(createSupportedEllipticCurvesExtension(namedCurves));
     }
 
     public static void addSupportedPointFormatsExtension(Hashtable extensionsshort[] ecPointFormats)
         throws IOException
     {
         extensions.put(createSupportedPointFormatsExtension(ecPointFormats));
     }
 
     public static int[] getSupportedEllipticCurvesExtension(Hashtable extensionsthrows IOException
     {
         byte[] extensionData = TlsUtils.getExtensionData(extensions);
         return extensionData == null ? null : readSupportedEllipticCurvesExtension(extensionData);
     }
 
     public static short[] getSupportedPointFormatsExtension(Hashtable extensionsthrows IOException
     {
         byte[] extensionData = TlsUtils.getExtensionData(extensions);
         return extensionData == null ? null : readSupportedPointFormatsExtension(extensionData);
     }
 
     public static byte[] createSupportedEllipticCurvesExtension(int[] namedCurvesthrows IOException
     {
         if (namedCurves == null || namedCurves.length < 1)
         {
             throw new TlsFatalAlert(.);
         }
 
         return TlsUtils.encodeUint16ArrayWithUint16Length(namedCurves);
     }
 
     public static byte[] createSupportedPointFormatsExtension(short[] ecPointFormatsthrows IOException
     {
         if (ecPointFormats == null || !Arrays.contains(ecPointFormats.))
         {
             /*
              * RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST
              * contain the value 0 (uncompressed) as one of the items in the list of point formats.
              */
 
             // NOTE: We add it at the end (lowest preference)
             ecPointFormats = Arrays.append(ecPointFormats.);
         }
 
         return TlsUtils.encodeUint8ArrayWithUint8Length(ecPointFormats);
     }
 
     public static int[] readSupportedEllipticCurvesExtension(byte[] extensionDatathrows IOException
     {
         if (extensionData == null)
         {
             throw new IllegalArgumentException("'extensionData' cannot be null");
         }
 
         ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
 
         int length = TlsUtils.readUint16(buf);
        if (length < 2 || (length & 1) != 0)
        {
            throw new TlsFatalAlert(.);
        }
        int[] namedCurves = TlsUtils.readUint16Array(length / 2, buf);
        TlsProtocol.assertEmpty(buf);
        return namedCurves;
    }
    public static short[] readSupportedPointFormatsExtension(byte[] extensionDatathrows IOException
    {
        if (extensionData == null)
        {
            throw new IllegalArgumentException("'extensionData' cannot be null");
        }
        ByteArrayInputStream buf = new ByteArrayInputStream(extensionData);
        short length = TlsUtils.readUint8(buf);
        if (length < 1)
        {
            throw new TlsFatalAlert(.);
        }
        short[] ecPointFormats = TlsUtils.readUint8Array(lengthbuf);
        TlsProtocol.assertEmpty(buf);
        if (!Arrays.contains(ecPointFormats.))
        {
            /*
             * RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST
             * contain the value 0 (uncompressed) as one of the items in the list of point formats.
             */
            throw new TlsFatalAlert(.);
        }
        return ecPointFormats;
    }
    public static String getNameOfNamedCurve(int namedCurve)
    {
        return isSupportedNamedCurve(namedCurve) ? [namedCurve - 1] : null;
    }
    public static ECDomainParameters getParametersForNamedCurve(int namedCurve)
    {
        String curveName = getNameOfNamedCurve(namedCurve);
        if (curveName == null)
        {
            return null;
        }
        // Parameters are lazily created the first time a particular curve is accessed
        X9ECParameters ecP = CustomNamedCurves.getByName(curveName);
        if (ecP == null)
        {
            ecP = ECNamedCurveTable.getByName(curveName);
            if (ecP == null)
            {
                return null;
            }
        }
        // It's a bit inefficient to do this conversion every time
        return new ECDomainParameters(ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed());
    }
    public static boolean hasAnySupportedNamedCurves()
    {
        return . > 0;
    }
    public static boolean containsECCCipherSuites(int[] cipherSuites)
    {
        for (int i = 0; i < cipherSuites.length; ++i)
        {
            if (isECCCipherSuite(cipherSuites[i]))
            {
                return true;
            }
        }
        return false;
    }
    public static boolean isECCCipherSuite(int cipherSuite)
    {
        switch (cipherSuite)
        {
        /*
         * RFC 4492
         */
        /*
         * RFC 5289
         */
        /*
         * RFC 5489
         */
        /*
         * RFC 6367
         */
        /*
         * RFC 7251
         */
        /*
         * draft-agl-tls-chacha20poly1305-04
         */
        /*
         * draft-josefsson-salsa20-tls-04 
         */
            return true;
        default:
            return false;
        }
    }
    public static boolean areOnSameCurve(ECDomainParameters aECDomainParameters b)
    {
        // TODO Move to ECDomainParameters.equals() or other utility method?
        return a.getCurve().equals(b.getCurve()) && a.getG().equals(b.getG()) && a.getN().equals(b.getN())
            && a.getH().equals(b.getH());
    }
    public static boolean isSupportedNamedCurve(int namedCurve)
    {
        return (namedCurve > 0 && namedCurve <= .);
    }
    public static boolean isCompressionPreferred(short[] ecPointFormatsshort compressionFormat)
    {
        if (ecPointFormats == null)
        {
            return false;
        }
        for (int i = 0; i < ecPointFormats.length; ++i)
        {
            short ecPointFormat = ecPointFormats[i];
            if (ecPointFormat == .)
            {
                return false;
            }
            if (ecPointFormat == compressionFormat)
            {
                return true;
            }
        }
        return false;
    }
    public static byte[] serializeECFieldElement(int fieldSizeBigInteger xthrows IOException
    {
        return BigIntegers.asUnsignedByteArray((fieldSize + 7) / 8, x);
    }
    public static byte[] serializeECPoint(short[] ecPointFormatsECPoint pointthrows IOException
    {
        ECCurve curve = point.getCurve();
        /*
         * RFC 4492 5.7. ...an elliptic curve point in uncompressed or compressed format. Here, the
         * format MUST conform to what the server has requested through a Supported Point Formats
         * Extension if this extension was used, and MUST be uncompressed if this extension was not
         * used.
         */
        boolean compressed = false;
        if (ECAlgorithms.isFpCurve(curve))
        {
            compressed = isCompressionPreferred(ecPointFormats.);
        }
        else if (ECAlgorithms.isF2mCurve(curve))
        {
            compressed = isCompressionPreferred(ecPointFormats.);
        }
        return point.getEncoded(compressed);
    }
    public static byte[] serializeECPublicKey(short[] ecPointFormatsECPublicKeyParameters keyParameters)
        throws IOException
    {
        return serializeECPoint(ecPointFormatskeyParameters.getQ());
    }
    public static BigInteger deserializeECFieldElement(int fieldSizebyte[] encodingthrows IOException
    {
        int requiredLength = (fieldSize + 7) / 8;
        if (encoding.length != requiredLength)
        {
            throw new TlsFatalAlert(.);
        }
        return new BigInteger(1, encoding);
    }
    public static ECPoint deserializeECPoint(short[] ecPointFormatsECCurve curvebyte[] encodingthrows IOException
    {
        if (encoding == null || encoding.length < 1)
        {
            throw new TlsFatalAlert(.);
        }
        short actualFormat;
        switch (encoding[0])
        {
        case 0x02: // compressed
        case 0x03: // compressed
        {
            if (ECAlgorithms.isF2mCurve(curve))
            {
                actualFormat = .;
            }
            else if (ECAlgorithms.isFpCurve(curve))
            {
                actualFormat = .;
            }
            else
            {
                throw new TlsFatalAlert(.);
            }
            break;
        }
        case 0x04: // uncompressed
        {
            actualFormat = .;
            break;
        }
        case 0x00: // infinity
        case 0x06: // hybrid
        case 0x07: // hybrid
        default:
            throw new TlsFatalAlert(.);
        }
        if (actualFormat != .
            && (ecPointFormats == null || !Arrays.contains(ecPointFormatsactualFormat)))
        {
            throw new TlsFatalAlert(.);
        }
        return curve.decodePoint(encoding);
    }
    public static ECPublicKeyParameters deserializeECPublicKey(short[] ecPointFormatsECDomainParameters curve_params,
        byte[] encodingthrows IOException
    {
        try
        {
            ECPoint Y = deserializeECPoint(ecPointFormatscurve_params.getCurve(), encoding);
            return new ECPublicKeyParameters(Ycurve_params);
        }
        catch (RuntimeException e)
        {
            throw new TlsFatalAlert(.e);
        }
    }
    public static byte[] calculateECDHBasicAgreement(ECPublicKeyParameters publicKeyECPrivateKeyParameters privateKey)
    {
        ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();
        basicAgreement.init(privateKey);
        BigInteger agreementValue = basicAgreement.calculateAgreement(publicKey);
        /*
         * RFC 4492 5.10. Note that this octet string (Z in IEEE 1363 terminology) as output by
         * FE2OSP, the Field Element to Octet String Conversion Primitive, has constant length for
         * any given field; leading zeros found in this octet string MUST NOT be truncated.
         */
        return BigIntegers.asUnsignedByteArray(basicAgreement.getFieldSize(), agreementValue);
    }
    public static AsymmetricCipherKeyPair generateECKeyPair(SecureRandom randomECDomainParameters ecParams)
    {
        ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
        keyPairGenerator.init(new ECKeyGenerationParameters(ecParamsrandom));
        return keyPairGenerator.generateKeyPair();
    }
    public static ECPrivateKeyParameters generateEphemeralClientKeyExchange(SecureRandom randomshort[] ecPointFormats,
        ECDomainParameters ecParamsOutputStream outputthrows IOException
    {
        AsymmetricCipherKeyPair kp = generateECKeyPair(randomecParams);
        ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameterskp.getPublic();
        writeECPoint(ecPointFormatsecPublicKey.getQ(), output);
        return (ECPrivateKeyParameterskp.getPrivate();
    }
    // TODO Refactor around ServerECDHParams before making this public
    static ECPrivateKeyParameters generateEphemeralServerKeyExchange(SecureRandom randomint[] namedCurves,
        short[] ecPointFormatsOutputStream outputthrows IOException
    {
        /* First we try to find a supported named curve from the client's list. */
        int namedCurve = -1;
        if (namedCurves == null)
        {
            // TODO Let the peer choose the default named curve
            namedCurve = .;
        }
        else
        {
            for (int i = 0; i < namedCurves.length; ++i)
            {
                int entry = namedCurves[i];
                if (NamedCurve.isValid(entry) && isSupportedNamedCurve(entry))
                {
                    namedCurve = entry;
                    break;
                }
            }
        }
        ECDomainParameters ecParams = null;
        if (namedCurve >= 0)
        {
            ecParams = getParametersForNamedCurve(namedCurve);
        }
        else
        {
            /* If no named curves are suitable, check if the client supports explicit curves. */
            if (Arrays.contains(namedCurves.))
            {
                ecParams = getParametersForNamedCurve(.);
            }
            else if (Arrays.contains(namedCurves.))
            {
                ecParams = getParametersForNamedCurve(.);
            }
        }
        if (ecParams == null)
        {
            /*
             * NOTE: We shouldn't have negotiated ECDHE key exchange since we apparently can't find
             * a suitable curve.
             */
            throw new TlsFatalAlert(.);
        }
        if (namedCurve < 0)
        {
            writeExplicitECParameters(ecPointFormatsecParamsoutput);
        }
        else
        {
            writeNamedECParameters(namedCurveoutput);
        }
        return generateEphemeralClientKeyExchange(randomecPointFormatsecParamsoutput);
    }
    {
        // TODO Check RFC 4492 for validation
        return key;
    }
    public static int readECExponent(int fieldSizeInputStream inputthrows IOException
    {
        BigInteger K = readECParameter(input);
        if (K.bitLength() < 32)
        {
            int k = K.intValue();
            if (k > 0 && k < fieldSize)
            {
                return k;
            }
        }
    }
    public static BigInteger readECFieldElement(int fieldSizeInputStream inputthrows IOException
    {
        return deserializeECFieldElement(fieldSize, TlsUtils.readOpaque8(input));
    }
    public static BigInteger readECParameter(InputStream inputthrows IOException
    {
        // TODO Are leading zeroes okay here?
        return new BigInteger(1, TlsUtils.readOpaque8(input));
    }
    public static ECDomainParameters readECParameters(int[] namedCurvesshort[] ecPointFormatsInputStream input)
        throws IOException
    {
        try
        {
            short curveType = TlsUtils.readUint8(input);
            switch (curveType)
            {
            case .:
            {
                checkNamedCurve(namedCurves.);
                BigInteger prime_p = readECParameter(input);
                BigInteger a = readECFieldElement(prime_p.bitLength(), input);
                BigInteger b = readECFieldElement(prime_p.bitLength(), input);
                byte[] baseEncoding = TlsUtils.readOpaque8(input);
                BigInteger order = readECParameter(input);
                BigInteger cofactor = readECParameter(input);
                ECCurve curve = new ECCurve.Fp(prime_pabordercofactor);
                ECPoint base = deserializeECPoint(ecPointFormatscurvebaseEncoding);
                return new ECDomainParameters(curvebaseordercofactor);
            }
            case .:
            {
                checkNamedCurve(namedCurves.);
                int m = TlsUtils.readUint16(input);
                short basis = TlsUtils.readUint8(input);
                if (!ECBasisType.isValid(basis))
                {
                    throw new TlsFatalAlert(.);
                }
                int k1 = readECExponent(minput), k2 = -1, k3 = -1;
                if (basis == .)
                {
                    k2 = readECExponent(minput);
                    k3 = readECExponent(minput);
                }
                BigInteger a = readECFieldElement(minput);
                BigInteger b = readECFieldElement(minput);
                byte[] baseEncoding = TlsUtils.readOpaque8(input);
                BigInteger order = readECParameter(input);
                BigInteger cofactor = readECParameter(input);
                ECCurve curve = (basis == .)
                    ? new ECCurve.F2m(mk1k2k3abordercofactor)
                    : new ECCurve.F2m(mk1abordercofactor);
                ECPoint base = deserializeECPoint(ecPointFormatscurvebaseEncoding);
                return new ECDomainParameters(curvebaseordercofactor);
            }
            case .:
            {
                int namedCurve = TlsUtils.readUint16(input);
                if (!NamedCurve.refersToASpecificNamedCurve(namedCurve))
                {
                    /*
                     * RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a
                     * specific curve. Values of NamedCurve that indicate support for a class of
                     * explicitly defined curves are not allowed here [...].
                     */
                    throw new TlsFatalAlert(.);
                }
                checkNamedCurve(namedCurvesnamedCurve);
                return getParametersForNamedCurve(namedCurve);
            }
            default:
                throw new TlsFatalAlert(.);
            }
        }
        catch (RuntimeException e)
        {
            throw new TlsFatalAlert(.e);
        }
    }
    private static void checkNamedCurve(int[] namedCurvesint namedCurvethrows IOException
    {
        if (namedCurves != null && !Arrays.contains(namedCurvesnamedCurve))
        {
            /*
             * RFC 4492 4. [...] servers MUST NOT negotiate the use of an ECC cipher suite
             * unless they can complete the handshake while respecting the choice of curves
             * and compression techniques specified by the client.
             */
            throw new TlsFatalAlert(.);
        }
    }
    public static void writeECExponent(int kOutputStream outputthrows IOException
    {
        BigInteger K = BigInteger.valueOf(k);
        writeECParameter(Koutput);
    }
    public static void writeECFieldElement(ECFieldElement xOutputStream outputthrows IOException
    {
        TlsUtils.writeOpaque8(x.getEncoded(), output);
    }
    public static void writeECFieldElement(int fieldSizeBigInteger xOutputStream outputthrows IOException
    {
        TlsUtils.writeOpaque8(serializeECFieldElement(fieldSizex), output);
    }
    public static void writeECParameter(BigInteger xOutputStream outputthrows IOException
    {
        TlsUtils.writeOpaque8(BigIntegers.asUnsignedByteArray(x), output);
    }
    public static void writeExplicitECParameters(short[] ecPointFormatsECDomainParameters ecParameters,
        OutputStream outputthrows IOException
    {
        ECCurve curve = ecParameters.getCurve();
        if (ECAlgorithms.isFpCurve(curve))
        {
            TlsUtils.writeUint8(.output);
            writeECParameter(curve.getField().getCharacteristic(), output);
        }
        else if (ECAlgorithms.isF2mCurve(curve))
        {
            PolynomialExtensionField field = (PolynomialExtensionField)curve.getField();
            int[] exponents = field.getMinimalPolynomial().getExponentsPresent();
            TlsUtils.writeUint8(.output);
            int m = exponents[exponents.length - 1];
            TlsUtils.checkUint16(m);
            TlsUtils.writeUint16(moutput);
            if (exponents.length == 3)
            {
                TlsUtils.writeUint8(.output);
                writeECExponent(exponents[1], output);
            }
            else if (exponents.length == 5)
            {
                TlsUtils.writeUint8(.output);
                writeECExponent(exponents[1], output);
                writeECExponent(exponents[2], output);
                writeECExponent(exponents[3], output);
            }
            else
            {
                throw new IllegalArgumentException("Only trinomial and pentomial curves are supported");
            }
        }
        else
        {
            throw new IllegalArgumentException("'ecParameters' not a known curve type");
        }
        writeECFieldElement(curve.getA(), output);
        writeECFieldElement(curve.getB(), output);
        TlsUtils.writeOpaque8(serializeECPoint(ecPointFormatsecParameters.getG()), output);
        writeECParameter(ecParameters.getN(), output);
        writeECParameter(ecParameters.getH(), output);
    }
    public static void writeECPoint(short[] ecPointFormatsECPoint pointOutputStream outputthrows IOException
    {
        TlsUtils.writeOpaque8(serializeECPoint(ecPointFormatspoint), output);
    }
    public static void writeNamedECParameters(int namedCurveOutputStream outputthrows IOException
    {
        if (!NamedCurve.refersToASpecificNamedCurve(namedCurve))
        {
            /*
             * RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a specific
             * curve. Values of NamedCurve that indicate support for a class of explicitly defined
             * curves are not allowed here [...].
             */
            throw new TlsFatalAlert(.);
        }
        TlsUtils.writeUint8(.output);
        TlsUtils.checkUint16(namedCurve);
        TlsUtils.writeUint16(namedCurveoutput);
    }
New to GrepCode? Check out our FAQ X