org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-jdk15to18 Show documentation
Show all versions of bcprov-jdk15to18 Show documentation
The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for JDK 1.5 to JDK 1.8.
package org.bouncycastle.jcajce.provider.asymmetric.util;
import java.math.BigInteger;
import java.security.spec.ECField;
import java.security.spec.ECFieldF2m;
import java.security.spec.ECFieldFp;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ECParametersHolder;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jce.ECGOST3410NamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.field.FiniteField;
import org.bouncycastle.math.field.Polynomial;
import org.bouncycastle.math.field.PolynomialExtensionField;
import org.bouncycastle.util.Arrays;
public class EC5Util
{
private static class CustomCurves
{
private static Map CURVE_MAP = createCurveMap();
private static Map createCurveMap()
{
Map map = new HashMap();
Enumeration e = CustomNamedCurves.getNames();
while (e.hasMoreElements())
{
String name = (String)e.nextElement();
X9ECParametersHolder curveParams = ECNamedCurveTable.getByNameLazy(name);
if (curveParams != null) // there may not be a regular curve, may just be a custom curve.
{
ECCurve curve = curveParams.getCurve();
if (ECAlgorithms.isFpCurve(curve))
{
map.put(curve, CustomNamedCurves.getByNameLazy(name).getCurve());
}
}
}
ECCurve c_25519 = CustomNamedCurves.getByNameLazy("Curve25519").getCurve();
map.put(new ECCurve.Fp(
c_25519.getField().getCharacteristic(),
c_25519.getA().toBigInteger(),
c_25519.getB().toBigInteger(),
c_25519.getOrder(),
c_25519.getCofactor(),
true), c_25519);
return map;
}
static ECCurve substitute(ECCurve c)
{
ECCurve custom = (ECCurve)CURVE_MAP.get(c);
return null != custom ? custom : c;
}
}
public static ECCurve getCurve(
ProviderConfiguration configuration,
X962Parameters params)
{
ECCurve curve;
Set acceptableCurves = configuration.getAcceptableNamedCurves();
if (params.isNamedCurve())
{
ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
if (acceptableCurves.isEmpty() || acceptableCurves.contains(oid))
{
X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
if (ecP == null)
{
ecP = (X9ECParameters)configuration.getAdditionalECParameters().get(oid);
}
curve = ecP.getCurve();
}
else
{
throw new IllegalStateException("named curve not acceptable");
}
}
else if (params.isImplicitlyCA())
{
curve = configuration.getEcImplicitlyCa().getCurve();
}
else
{
ASN1Sequence pSeq = ASN1Sequence.getInstance(params.getParameters());
if (acceptableCurves.isEmpty())
{
if (pSeq.size() > 3)
{
X9ECParameters ecP = X9ECParameters.getInstance(pSeq);
curve = ecP.getCurve();
}
else // GOST parameters
{
ASN1ObjectIdentifier gostCurve = ASN1ObjectIdentifier.getInstance(pSeq.getObjectAt(0));
curve = ECGOST3410NamedCurves.getByOIDX9(gostCurve).getCurve();
}
}
else
{
throw new IllegalStateException("encoded parameters not acceptable");
}
}
return curve;
}
public static ECDomainParameters getDomainParameters(
ProviderConfiguration configuration,
java.security.spec.ECParameterSpec params)
{
ECDomainParameters domainParameters;
if (params == null)
{
org.bouncycastle.jce.spec.ECParameterSpec iSpec = configuration.getEcImplicitlyCa();
domainParameters = new ECDomainParameters(iSpec.getCurve(), iSpec.getG(), iSpec.getN(), iSpec.getH(), iSpec.getSeed());
}
else
{
domainParameters = ECUtil.getDomainParameters(configuration, convertSpec(params));
}
return domainParameters;
}
public static ECParameterSpec convertToSpec(
X962Parameters params, ECCurve curve)
{
ECParameterSpec ecSpec;
EllipticCurve ellipticCurve;
if (params.isNamedCurve())
{
ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
if (ecP == null)
{
Map additionalECParameters = BouncyCastleProvider.CONFIGURATION.getAdditionalECParameters();
if (!additionalECParameters.isEmpty())
{
ecP = (X9ECParameters)additionalECParameters.get(oid);
}
}
ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed());
ecSpec = new ECNamedCurveSpec(
ECUtil.getCurveName(oid),
ellipticCurve,
convertPoint(ecP.getG()),
ecP.getN(),
ecP.getH());
}
else if (params.isImplicitlyCA())
{
ecSpec = null;
}
else
{
ASN1Sequence pSeq = ASN1Sequence.getInstance(params.getParameters());
if (pSeq.size() > 3)
{
X9ECParameters ecP = X9ECParameters.getInstance(pSeq);
ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed());
if (ecP.getH() != null)
{
ecSpec = new ECParameterSpec(
ellipticCurve,
convertPoint(ecP.getG()),
ecP.getN(),
ecP.getH().intValue());
}
else
{
ecSpec = new ECParameterSpec(
ellipticCurve,
convertPoint(ecP.getG()),
ecP.getN(),
1); // TODO: not strictly correct... need to fix the test data...
}
}
else // GOST parameters
{
GOST3410PublicKeyAlgParameters gostParams = GOST3410PublicKeyAlgParameters.getInstance(pSeq);
ECNamedCurveParameterSpec spec = ECGOST3410NamedCurveTable.getParameterSpec(ECGOST3410NamedCurves.getName(
gostParams.getPublicKeyParamSet()));
curve = spec.getCurve();
ellipticCurve = EC5Util.convertCurve(curve, spec.getSeed());
ecSpec = new ECNamedCurveSpec(
ECGOST3410NamedCurves.getName(gostParams.getPublicKeyParamSet()),
ellipticCurve,
EC5Util.convertPoint(spec.getG()),
spec.getN(), spec.getH());
}
}
return ecSpec;
}
public static ECParameterSpec convertToSpec(
X9ECParameters domainParameters)
{
return new ECParameterSpec(
convertCurve(domainParameters.getCurve(), null), // JDK 1.5 has trouble with this if it's not null...
EC5Util.convertPoint(domainParameters.getG()),
domainParameters.getN(),
domainParameters.getH().intValue());
}
public static ECParameterSpec convertToSpec(
ECDomainParameters domainParameters)
{
return new ECParameterSpec(
convertCurve(domainParameters.getCurve(), null), // JDK 1.5 has trouble with this if it's not null...
EC5Util.convertPoint(domainParameters.getG()),
domainParameters.getN(),
domainParameters.getH().intValue());
}
public static EllipticCurve convertCurve(
ECCurve curve,
byte[] seed)
{
ECField field = convertField(curve.getField());
BigInteger a = curve.getA().toBigInteger(), b = curve.getB().toBigInteger();
// TODO: the Sun EC implementation doesn't currently handle the seed properly
// so at the moment it's set to null. Should probably look at making this configurable
return new EllipticCurve(field, a, b, null);
}
public static ECCurve convertCurve(
EllipticCurve ec)
{
ECField field = ec.getField();
BigInteger a = ec.getA();
BigInteger b = ec.getB();
if (field instanceof ECFieldFp)
{
return CustomCurves.substitute(new ECCurve.Fp(((ECFieldFp)field).getP(), a, b, null, null));
}
else
{
ECFieldF2m fieldF2m = (ECFieldF2m)field;
int m = fieldF2m.getM();
int ks[] = ECUtil.convertMidTerms(fieldF2m.getMidTermsOfReductionPolynomial());
return new ECCurve.F2m(m, ks[0], ks[1], ks[2], a, b, null, null);
}
}
public static ECField convertField(FiniteField field)
{
if (ECAlgorithms.isFpField(field))
{
return new ECFieldFp(field.getCharacteristic());
}
else //if (ECAlgorithms.isF2mField(curveField))
{
Polynomial poly = ((PolynomialExtensionField)field).getMinimalPolynomial();
int[] exponents = poly.getExponentsPresent();
int[] ks = Arrays.reverseInPlace(Arrays.copyOfRange(exponents, 1, exponents.length - 1));
return new ECFieldF2m(poly.getDegree(), ks);
}
}
public static ECParameterSpec convertSpec(
EllipticCurve ellipticCurve,
org.bouncycastle.jce.spec.ECParameterSpec spec)
{
ECPoint g = convertPoint(spec.getG());
if (spec instanceof ECNamedCurveParameterSpec)
{
String name = ((ECNamedCurveParameterSpec)spec).getName();
return new ECNamedCurveSpec(name, ellipticCurve, g, spec.getN(), spec.getH());
}
else
{
return new ECParameterSpec(ellipticCurve, g, spec.getN(), spec.getH().intValue());
}
}
public static org.bouncycastle.jce.spec.ECParameterSpec convertSpec(ECParameterSpec ecSpec)
{
ECCurve curve = convertCurve(ecSpec.getCurve());
org.bouncycastle.math.ec.ECPoint g = convertPoint(curve, ecSpec.getGenerator());
BigInteger n = ecSpec.getOrder();
BigInteger h = BigInteger.valueOf(ecSpec.getCofactor());
byte[] seed = ecSpec.getCurve().getSeed();
if (ecSpec instanceof ECNamedCurveSpec)
{
return new org.bouncycastle.jce.spec.ECNamedCurveParameterSpec(((ECNamedCurveSpec)ecSpec).getName(), curve,
g, n, h, seed);
}
else
{
return new org.bouncycastle.jce.spec.ECParameterSpec(curve, g, n, h, seed);
}
}
public static org.bouncycastle.math.ec.ECPoint convertPoint(ECParameterSpec ecSpec, ECPoint point)
{
return convertPoint(convertCurve(ecSpec.getCurve()), point);
}
public static org.bouncycastle.math.ec.ECPoint convertPoint(ECCurve curve, ECPoint point)
{
return curve.createPoint(point.getAffineX(), point.getAffineY());
}
public static ECPoint convertPoint(org.bouncycastle.math.ec.ECPoint point)
{
point = point.normalize();
return new ECPoint(
point.getAffineXCoord().toBigInteger(),
point.getAffineYCoord().toBigInteger());
}
}