You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by mu...@apache.org on 2015/12/22 21:21:34 UTC
svn commit: r1721459 - in /santuario/xml-security-java/trunk/src:
main/java/org/apache/jcp/xml/dsig/internal/dom/DOMKeyValue.java
test/java/javax/xml/crypto/test/dsig/PKSignatureAlgorithmTest.java
Author: mullan
Date: Tue Dec 22 20:21:34 2015
New Revision: 1721459
URL: http://svn.apache.org/viewvc?rev=1721459&view=rev
Log:
Remove dependencies on internal JDK APIs for parsing EC KeyValue elements. Restrict support to standard 256, 384, and 512 bit curves.
Modified:
santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMKeyValue.java
santuario/xml-security-java/trunk/src/test/java/javax/xml/crypto/test/dsig/PKSignatureAlgorithmTest.java
Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMKeyValue.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMKeyValue.java?rev=1721459&r1=1721458&r2=1721459&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMKeyValue.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMKeyValue.java Tue Dec 22 20:21:34 2015
@@ -28,36 +28,31 @@ import javax.xml.crypto.*;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
+import java.io.IOException;
import java.math.BigInteger;
-import java.security.AccessController;
-import java.security.AlgorithmParameters;
import java.security.KeyException;
import java.security.KeyFactory;
-import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
import java.security.PublicKey;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.ECField;
+import java.security.spec.ECFieldFp;
import java.security.spec.ECParameterSpec;
-import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.EllipticCurve;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.RSAPublicKeySpec;
+import java.util.Arrays;
import org.w3c.dom.Element;
import org.apache.xml.security.exceptions.Base64DecodingException;
import org.apache.xml.security.utils.Base64;
-import org.apache.xml.security.utils.ClassLoaderUtils;
/**
* DOM-based implementation of KeyValue.
@@ -317,59 +312,146 @@ public abstract class DOMKeyValue<K exte
static final class EC extends DOMKeyValue<ECPublicKey> {
- private static final String VER = System.getProperty("java.version");
- private static final boolean AT_LEAST_18 = !VER.startsWith("1.5") &&
- !VER.startsWith("1.6") && !VER.startsWith("1.7");
// ECKeyValue CryptoBinaries
private byte[] ecPublicKey;
private KeyFactory eckf;
private ECParameterSpec ecParams;
- private Method encodePoint, decodePoint;
+
+ /* Supported curve, secp256r1 */
+ private static final Curve SECP256R1 = initializeCurve(
+ "secp256r1 [NIST P-256, X9.62 prime256v1]",
+ "1.2.840.10045.3.1.7",
+ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
+ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
+ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ 1
+ );
+
+ /* Supported curve secp384r1 */
+ private static final Curve SECP384R1 = initializeCurve(
+ "secp384r1 [NIST P-384]",
+ "1.3.132.0.34",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+ 1
+ );
+
+ /* Supported curve secp521r1 */
+ private static final Curve SECP521R1 = initializeCurve(
+ "secp521r1 [NIST P-521]",
+ "1.3.132.0.35",
+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
+ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
+ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+ 1
+ );
+
+ private static Curve initializeCurve(String name, String oid,
+ String sfield, String a, String b,
+ String x, String y, String n, int h) {
+ BigInteger p = bigInt(sfield);
+ ECField field = new ECFieldFp(p);
+ EllipticCurve curve = new EllipticCurve(field, bigInt(a),
+ bigInt(b));
+ ECPoint g = new ECPoint(bigInt(x), bigInt(y));
+ return new Curve(name, oid, curve, g, bigInt(n), h);
+ }
EC(ECPublicKey ecKey) throws KeyException {
super(ecKey);
ECPoint ecPoint = ecKey.getW();
ecParams = ecKey.getParams();
- try {
- AccessController.doPrivileged(
- new PrivilegedExceptionAction<Void>() {
- @Override
- public Void run() throws
- ClassNotFoundException, NoSuchMethodException
- {
- getMethods();
- return null;
- }
- }
- );
- } catch (PrivilegedActionException pae) {
- throw new KeyException("ECKeyValue not supported",
- pae.getException());
- }
- Object[] args = new Object[] { ecPoint, ecParams.getCurve() };
- try {
- ecPublicKey = (byte[])encodePoint.invoke(null, args);
- } catch (IllegalAccessException iae) {
- throw new KeyException(iae);
- } catch (InvocationTargetException ite) {
- throw new KeyException(ite);
- }
+ ecPublicKey = encodePoint(ecPoint, ecParams.getCurve());
}
EC(Element dmElem) throws MarshalException {
super(dmElem);
}
- void getMethods() throws ClassNotFoundException, NoSuchMethodException {
- String className = AT_LEAST_18
- ? "sun.security.util.ECUtil"
- : "sun.security.ec.ECParameters";
- Class<?> c = ClassLoaderUtils.loadClass(className, DOMKeyValue.class);
- Class<?>[] params = new Class<?>[] { ECPoint.class, EllipticCurve.class };
- encodePoint = c.getMethod("encodePoint", params);
- params = new Class[] { ECParameterSpec.class };
- params = new Class[] { byte[].class, EllipticCurve.class };
- decodePoint = c.getMethod("decodePoint", params);
+ private static ECPoint decodePoint(byte[] data, EllipticCurve curve)
+ throws IOException {
+ if (data.length == 0 || data[0] != 4) {
+ throw new IOException("Only uncompressed point format " +
+ "supported");
+ }
+ // Per ANSI X9.62, an encoded point is a 1 byte type followed by
+ // ceiling(log base 2 field-size / 8) bytes of x and the same of y.
+ int n = (data.length - 1) / 2;
+ if (n != (curve.getField().getFieldSize() + 7) >> 3) {
+ throw new IOException("Point does not match field size");
+ }
+
+ byte[] xb = Arrays.copyOfRange(data, 1, 1 + n);
+ byte[] yb = Arrays.copyOfRange(data, n + 1, n + 1 + n);
+
+ return new ECPoint(new BigInteger(1, xb), new BigInteger(1, yb));
+ }
+
+ private static byte[] encodePoint(ECPoint point, EllipticCurve curve) {
+ // get field size in bytes (rounding up)
+ int n = (curve.getField().getFieldSize() + 7) >> 3;
+ byte[] xb = trimZeroes(point.getAffineX().toByteArray());
+ byte[] yb = trimZeroes(point.getAffineY().toByteArray());
+ if (xb.length > n || yb.length > n) {
+ throw new RuntimeException("Point coordinates do not " +
+ "match field size");
+ }
+ byte[] b = new byte[1 + (n << 1)];
+ b[0] = 4; // uncompressed
+ System.arraycopy(xb, 0, b, n - xb.length + 1, xb.length);
+ System.arraycopy(yb, 0, b, b.length - yb.length, yb.length);
+ return b;
+ }
+
+ private static byte[] trimZeroes(byte[] b) {
+ int i = 0;
+ while (i < b.length - 1 && b[i] == 0) {
+ i++;
+ }
+ if (i == 0) {
+ return b;
+ }
+ return Arrays.copyOfRange(b, i, b.length);
+ }
+
+ private static String getCurveOid(ECParameterSpec params) {
+ // Check that the params represent one of the supported
+ // curves. If there is a match, return the object identifier
+ // of the curve.
+ Curve match;
+ if (matchCurve(params, SECP256R1)) {
+ match = SECP256R1;
+ } else if (matchCurve(params, SECP384R1)) {
+ match = SECP384R1;
+ } else if (matchCurve(params, SECP521R1)) {
+ match = SECP521R1;
+ } else {
+ return null;
+ }
+ return match.getObjectId();
+ }
+
+ private static boolean matchCurve(ECParameterSpec params, Curve curve) {
+ int fieldSize = params.getCurve().getField().getFieldSize();
+ if (curve.getCurve().getField().getFieldSize() == fieldSize
+ && curve.getCurve().equals(params.getCurve())
+ && curve.getGenerator().equals(params.getGenerator())
+ && curve.getOrder().equals(params.getOrder())
+ && curve.getCofactor() == params.getCofactor()) {
+ return true;
+ } else {
+ return false;
+ }
}
@Override
@@ -382,12 +464,11 @@ public abstract class DOMKeyValue<K exte
xwriter.writeStartElement(prefix, "NamedCurve", XMLDSIG_11_XMLNS);
xwriter.writeNamespace(prefix, XMLDSIG_11_XMLNS);
- try {
- String oid = getCurveName(ecParams);
- xwriter.writeAttribute("", "", "URI", "urn:oid:" + oid);
- } catch (GeneralSecurityException gse) {
- throw new MarshalException(gse);
+ String oid = getCurveOid(ecParams);
+ if (oid == null) {
+ throw new MarshalException("Invalid ECParameterSpec");
}
+ xwriter.writeAttribute("", "", "URI", "urn:oid:" + oid);
xwriter.writeEndElement();
xwriter.writeStartElement(prefix, "PublicKey", XMLDSIG_11_XMLNS);
@@ -397,19 +478,6 @@ public abstract class DOMKeyValue<K exte
xwriter.writeEndElement(); // "ECKeyValue"
}
- private static String getCurveName(ECParameterSpec spec)
- throws GeneralSecurityException
- {
- AlgorithmParameters ap = AlgorithmParameters.getInstance("EC");
- ap.init(spec);
- ECGenParameterSpec nameSpec =
- ap.getParameterSpec(ECGenParameterSpec.class);
- if (nameSpec == null) {
- return null;
- }
- return nameSpec.getName();
- }
-
@Override
ECPublicKey unmarshalKeyValue(Element kvtElem)
throws MarshalException
@@ -422,23 +490,7 @@ public abstract class DOMKeyValue<K exte
("unable to create EC KeyFactory: " + e.getMessage());
}
}
- try {
- AccessController.doPrivileged(
- new PrivilegedExceptionAction<Void>() {
- @Override
- public Void run() throws
- ClassNotFoundException, NoSuchMethodException
- {
- getMethods();
- return null;
- }
- }
- );
- } catch (PrivilegedActionException pae) {
- throw new MarshalException("ECKeyValue not supported",
- pae.getException());
- }
- ECParameterSpec ellipticParams = null;
+ ECParameterSpec ecParams = null;
Element curElem = DOMUtils.getFirstChildElement(kvtElem);
if (curElem == null) {
throw new MarshalException("KeyValue must contain at least one type");
@@ -454,10 +506,9 @@ public abstract class DOMKeyValue<K exte
// strip off "urn:oid"
if (uri.startsWith("urn:oid:")) {
String oid = uri.substring("urn:oid:".length());
- try {
- ellipticParams = getECParameterSpec(oid);
- } catch (GeneralSecurityException gse) {
- throw new MarshalException(gse);
+ ecParams = getECParameterSpec(oid);
+ if (ecParams == null) {
+ throw new MarshalException("Invalid curve OID");
}
} else {
throw new MarshalException("Invalid NamedCurve URI");
@@ -467,32 +518,55 @@ public abstract class DOMKeyValue<K exte
}
curElem = DOMUtils.getNextSiblingElement(curElem, "PublicKey", XMLDSIG_11_XMLNS);
ECPoint ecPoint = null;
+
try {
- Object[] args = new Object[] { Base64.decode(curElem),
- ellipticParams.getCurve() };
- ecPoint = (ECPoint)decodePoint.invoke(null, args);
+ ecPoint = decodePoint(Base64.decode(curElem),
+ ecParams.getCurve());
} catch (Base64DecodingException bde) {
throw new MarshalException("Invalid EC PublicKey", bde);
- } catch (IllegalAccessException iae) {
- throw new MarshalException(iae);
- } catch (InvocationTargetException ite) {
- throw new MarshalException(ite);
- }
-/*
- ecPoint = sun.security.ec.ECParameters.decodePoint(
- Base64.decode(curElem), ellipticParams.getCurve());
-*/
- ECPublicKeySpec spec = new ECPublicKeySpec(ecPoint, ellipticParams);
+ } catch (IOException ioe) {
+ throw new MarshalException("Invalid EC Point", ioe);
+ }
+
+ ECPublicKeySpec spec = new ECPublicKeySpec(ecPoint, ecParams);
return (ECPublicKey) generatePublicKey(eckf, spec);
}
- private static ECParameterSpec getECParameterSpec(String name)
- throws GeneralSecurityException
- {
- AlgorithmParameters ap = AlgorithmParameters.getInstance("EC");
- ap.init(new ECGenParameterSpec(name));
- return ap.getParameterSpec(ECParameterSpec.class);
+ private static ECParameterSpec getECParameterSpec(String oid) {
+ if (oid.equals(SECP256R1.getObjectId())) {
+ return SECP256R1;
+ } else if (oid.equals(SECP384R1.getObjectId())) {
+ return SECP384R1;
+ } else if (oid.equals(SECP521R1.getObjectId())) {
+ return SECP521R1;
+ } else {
+ return null;
+ }
}
+
+ static final class Curve extends ECParameterSpec {
+ private final String name;
+ private final String oid;
+
+ Curve(String name, String oid, EllipticCurve curve,
+ ECPoint g, BigInteger n, int h) {
+ super(curve, g, n, h);
+ this.name = name;
+ this.oid = oid;
+ }
+
+ private String getName() {
+ return name;
+ }
+
+ private String getObjectId() {
+ return oid;
+ }
+ }
+ }
+
+ private static BigInteger bigInt(String s) {
+ return new BigInteger(s, 16);
}
static final class Unknown extends DOMKeyValue<PublicKey> {
Modified: santuario/xml-security-java/trunk/src/test/java/javax/xml/crypto/test/dsig/PKSignatureAlgorithmTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/javax/xml/crypto/test/dsig/PKSignatureAlgorithmTest.java?rev=1721459&r1=1721458&r2=1721459&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/javax/xml/crypto/test/dsig/PKSignatureAlgorithmTest.java (original)
+++ santuario/xml-security-java/trunk/src/test/java/javax/xml/crypto/test/dsig/PKSignatureAlgorithmTest.java Tue Dec 22 20:21:34 2015
@@ -137,7 +137,9 @@ public class PKSignatureAlgorithmTest ex
rsaKpg.initialize(2048);
rsaKeyPair = rsaKpg.genKeyPair();
- ecKeyPair = KeyPairGenerator.getInstance("EC").genKeyPair();
+ KeyPairGenerator ecKpg = KeyPairGenerator.getInstance("EC");
+ ecKpg.initialize(256);
+ ecKeyPair = ecKpg.genKeyPair();
KeyInfoFactory kifac = fac.getKeyInfoFactory();
rsaki = kifac.newKeyInfo(Collections.singletonList