You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by co...@apache.org on 2019/03/19 12:18:00 UTC

svn commit: r1855815 - in /santuario/xml-security-java/trunk/src: main/java/org/apache/xml/security/keys/content/ main/java/org/apache/xml/security/keys/content/keyvalues/ main/java/org/apache/xml/security/keys/keyresolver/ main/java/org/apache/xml/sec...

Author: coheigea
Date: Tue Mar 19 12:17:59 2019
New Revision: 1855815

URL: http://svn.apache.org/viewvc?rev=1855815&view=rev
Log:
SANTUARIO-404 - Add support for embedding elliptic curve public keys in KeyValue element

Added:
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/content/keyvalues/ECKeyValue.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/ECKeyValueResolver.java
Modified:
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/content/KeyValue.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/keyresolver/KeyResolver.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/resource/config.xml
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/Constants.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/ElementProxy.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/Signature11ElementProxy.java
    santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/signature/ECDSASignatureTest.java

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/content/KeyValue.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/content/KeyValue.java?rev=1855815&r1=1855814&r2=1855815&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/content/KeyValue.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/content/KeyValue.java Tue Mar 19 12:17:59 2019
@@ -22,6 +22,7 @@ import java.security.PublicKey;
 
 import org.apache.xml.security.exceptions.XMLSecurityException;
 import org.apache.xml.security.keys.content.keyvalues.DSAKeyValue;
+import org.apache.xml.security.keys.content.keyvalues.ECKeyValue;
 import org.apache.xml.security.keys.content.keyvalues.RSAKeyValue;
 import org.apache.xml.security.utils.Constants;
 import org.apache.xml.security.utils.SignatureElementProxy;
@@ -103,9 +104,14 @@ public class KeyValue extends SignatureE
 
             appendSelf(rsa);
             addReturnToSelf();
+        } else if (pk instanceof java.security.interfaces.ECPublicKey) {
+            ECKeyValue ec = new ECKeyValue(getDocument(), pk);
+
+            appendSelf(ec);
+            addReturnToSelf();
         } else {
             String error = "The given PublicKey type " + pk + " is not supported. Only DSAPublicKey and "
-                + "RSAPublicKey types are currently supported";
+                + "RSAPublicKey and ECPublicKey types are currently supported";
             throw new IllegalArgumentException(error);
         }
     }

Added: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/content/keyvalues/ECKeyValue.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/content/keyvalues/ECKeyValue.java?rev=1855815&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/content/keyvalues/ECKeyValue.java (added)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/content/keyvalues/ECKeyValue.java Tue Mar 19 12:17:59 2019
@@ -0,0 +1,362 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.xml.security.keys.content.keyvalues;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECField;
+import java.security.spec.ECFieldFp;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.EllipticCurve;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Arrays;
+
+import javax.xml.crypto.MarshalException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.utils.Constants;
+import org.apache.xml.security.utils.I18n;
+import org.apache.xml.security.utils.Signature11ElementProxy;
+import org.apache.xml.security.utils.XMLUtils;
+
+public class ECKeyValue extends Signature11ElementProxy implements KeyValueContent {
+
+    /* 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);
+    }
+
+
+    /**
+     * Constructor DSAKeyValue
+     *
+     * @param element
+     * @param baseURI
+     * @throws XMLSecurityException
+     */
+    public ECKeyValue(Element element, String baseURI) throws XMLSecurityException {
+        super(element, baseURI);
+    }
+
+    /**
+     * Constructor DSAKeyValue
+     *
+     * @param doc
+     * @param key
+     * @throws IllegalArgumentException
+     */
+    public ECKeyValue(Document doc, Key key) throws IllegalArgumentException {
+        super(doc);
+
+        addReturnToSelf();
+
+        if (key instanceof ECPublicKey) {
+            ECParameterSpec ecParams = ((ECPublicKey)key).getParams();
+
+            // NamedCurve
+            String oid = getCurveOid(ecParams);
+            if (oid == null) {
+                throw new IllegalArgumentException("Invalid ECParameterSpec");
+            }
+
+            Element namedCurveElement = XMLUtils.createElementInSignature11Space(getDocument(), "NamedCurve");
+            namedCurveElement.setAttributeNS(null, "URI", "urn:oid:" + oid);
+            appendSelf(namedCurveElement);
+            addReturnToSelf();
+
+            // PublicKey
+            ECPoint ecPoint = ((ECPublicKey)key).getW();
+            byte[] secPublicKey = encodePoint(ecPoint, ecParams.getCurve());
+            String encoded = XMLUtils.encodeToString(secPublicKey);
+            Element publicKeyElement = XMLUtils.createElementInSignature11Space(getDocument(), "PublicKey");
+            Text text = getDocument().createTextNode(encoded);
+
+            publicKeyElement.appendChild(text);
+
+            appendSelf(publicKeyElement);
+            addReturnToSelf();
+
+        } else {
+            Object[] exArgs = { Constants._TAG_ECKEYVALUE, key.getClass().getName() };
+
+            throw new IllegalArgumentException(I18n.translate("KeyValue.IllegalArgument", exArgs));
+        }
+    }
+
+    /** {@inheritDoc} */
+    public PublicKey getPublicKey() throws XMLSecurityException {
+        try {
+            ECParameterSpec ecParams = null;
+            Element curElem = getFirstChildElement(getElement());
+            if (curElem == null) {
+                throw new MarshalException("KeyValue must contain at least one type");
+            }
+
+            if ("ECParameters".equals(curElem.getLocalName())
+                && Constants.SignatureSpec11NS.equals(curElem.getNamespaceURI())) {
+                throw new UnsupportedOperationException
+                    ("ECParameters not supported");
+            } else if ("NamedCurve".equals(curElem.getLocalName())
+                && Constants.SignatureSpec11NS.equals(curElem.getNamespaceURI())) {
+                String uri = null;
+                if (curElem.hasAttributeNS(null, "URI")) {
+                    uri = curElem.getAttributeNS(null, "URI");
+                }
+                // strip off "urn:oid"
+                if (uri.startsWith("urn:oid:")) {
+                    String oid = uri.substring("urn:oid:".length());
+                    ecParams = getECParameterSpec(oid);
+                    if (ecParams == null) {
+                        throw new MarshalException("Invalid curve OID");
+                    }
+                } else {
+                    throw new MarshalException("Invalid NamedCurve URI");
+                }
+            } else {
+                throw new MarshalException("Invalid ECKeyValue");
+            }
+            curElem = getNextSiblingElement(curElem, "PublicKey", Constants.SignatureSpec11NS);
+            ECPoint ecPoint = null;
+
+            try {
+                String content = XMLUtils.getFullTextChildrenFromNode(curElem);
+                ecPoint = decodePoint(XMLUtils.decode(content), ecParams.getCurve());
+            } catch (IOException ioe) {
+                throw new MarshalException("Invalid EC Point", ioe);
+            }
+
+            ECPublicKeySpec spec = new ECPublicKeySpec(ecPoint, ecParams);
+            return KeyFactory.getInstance("EC").generatePublic(spec);
+        } catch (NoSuchAlgorithmException ex) {
+            throw new XMLSecurityException(ex);
+        } catch (InvalidKeySpecException ex) {
+            throw new XMLSecurityException(ex);
+        } catch (MarshalException ex) {
+            throw new XMLSecurityException(ex);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public String getBaseLocalName() {
+        return Constants._TAG_ECKEYVALUE;
+    }
+
+    private static Element getFirstChildElement(Node node) {
+        Node child = node.getFirstChild();
+        while (child != null && child.getNodeType() != Node.ELEMENT_NODE) {
+            child = child.getNextSibling();
+        }
+        return (Element)child;
+    }
+
+    private static Element getNextSiblingElement(Node node, String localName, String namespaceURI)
+        throws MarshalException
+    {
+        return verifyElement(getNextSiblingElement(node), localName, namespaceURI);
+    }
+
+    private static Element getNextSiblingElement(Node node) {
+        Node sibling = node.getNextSibling();
+        while (sibling != null && sibling.getNodeType() != Node.ELEMENT_NODE) {
+            sibling = sibling.getNextSibling();
+        }
+        return (Element)sibling;
+    }
+
+    private static Element verifyElement(Element elem, String localName, String namespaceURI)
+        throws MarshalException
+    {
+        if (elem == null) {
+            throw new MarshalException("Missing " + localName + " element");
+        }
+        String name = elem.getLocalName();
+        String namespace = elem.getNamespaceURI();
+        if (!name.equals(localName) || namespace == null && namespaceURI != null
+            || namespace != null && !namespace.equals(namespaceURI)) {
+            throw new MarshalException("Invalid element name: " +
+                namespace + ":" + name + ", expected " + namespaceURI + ":" + localName);
+        }
+        return elem;
+    }
+
+    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();
+        return curve.getCurve().getField().getFieldSize() == fieldSize
+            && curve.getCurve().equals(params.getCurve())
+            && curve.getGenerator().equals(params.getGenerator())
+            && curve.getOrder().equals(params.getOrder())
+            && curve.getCofactor() == params.getCofactor();
+    }
+
+    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 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);
+    }
+}

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/keyresolver/KeyResolver.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/keyresolver/KeyResolver.java?rev=1855815&r1=1855814&r2=1855815&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/keyresolver/KeyResolver.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/keyresolver/KeyResolver.java Tue Mar 19 12:17:59 2019
@@ -29,6 +29,7 @@ import javax.crypto.SecretKey;
 
 import org.apache.xml.security.keys.keyresolver.implementations.DEREncodedKeyValueResolver;
 import org.apache.xml.security.keys.keyresolver.implementations.DSAKeyValueResolver;
+import org.apache.xml.security.keys.keyresolver.implementations.ECKeyValueResolver;
 import org.apache.xml.security.keys.keyresolver.implementations.KeyInfoReferenceResolver;
 import org.apache.xml.security.keys.keyresolver.implementations.RSAKeyValueResolver;
 import org.apache.xml.security.keys.keyresolver.implementations.RetrievalMethodResolver;
@@ -288,6 +289,7 @@ public class KeyResolver {
         keyResolverList.add(new KeyResolver(new DEREncodedKeyValueResolver()));
         keyResolverList.add(new KeyResolver(new KeyInfoReferenceResolver()));
         keyResolverList.add(new KeyResolver(new X509DigestResolver()));
+        keyResolverList.add(new KeyResolver(new ECKeyValueResolver()));
 
         resolverVector.addAll(keyResolverList);
     }

Added: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/ECKeyValueResolver.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/ECKeyValueResolver.java?rev=1855815&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/ECKeyValueResolver.java (added)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/ECKeyValueResolver.java Tue Mar 19 12:17:59 2019
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.xml.security.keys.keyresolver.implementations;
+
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.content.keyvalues.ECKeyValue;
+import org.apache.xml.security.keys.keyresolver.KeyResolverSpi;
+import org.apache.xml.security.keys.storage.StorageResolver;
+import org.apache.xml.security.utils.Constants;
+import org.apache.xml.security.utils.XMLUtils;
+import org.w3c.dom.Element;
+
+public class ECKeyValueResolver extends KeyResolverSpi {
+
+    private static final org.slf4j.Logger LOG =
+        org.slf4j.LoggerFactory.getLogger(ECKeyValueResolver.class);
+
+
+    /**
+     * Method engineResolvePublicKey
+     *
+     * @param element
+     * @param baseURI
+     * @param storage
+     * @return null if no {@link PublicKey} could be obtained
+     */
+    public PublicKey engineLookupAndResolvePublicKey(
+        Element element, String baseURI, StorageResolver storage
+    ) {
+        if (element == null) {
+            return null;
+        }
+        Element ecKeyElement = null;
+        boolean isKeyValue =
+            XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYVALUE);
+        if (isKeyValue) {
+            ecKeyElement =
+                XMLUtils.selectDs11Node(element.getFirstChild(), Constants._TAG_ECKEYVALUE, 0);
+        } else if (XMLUtils.elementIsInSignature11Space(element, Constants._TAG_ECKEYVALUE)) {
+            // this trick is needed to allow the RetrievalMethodResolver to eat a
+            // ds:ECKeyValue directly (without KeyValue)
+            ecKeyElement = element;
+        }
+
+        if (ecKeyElement == null) {
+            return null;
+        }
+
+        try {
+            ECKeyValue ecKeyValue = new ECKeyValue(ecKeyElement, baseURI);
+            return ecKeyValue.getPublicKey();
+        } catch (XMLSecurityException ex) {
+            LOG.debug(ex.getMessage(), ex);
+            //do nothing
+        }
+
+        return null;
+    }
+
+
+    /** {@inheritDoc} */
+    public X509Certificate engineLookupResolveX509Certificate(
+        Element element, String baseURI, StorageResolver storage
+    ) {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public javax.crypto.SecretKey engineLookupAndResolveSecretKey(
+        Element element, String baseURI, StorageResolver storage
+    ) {
+        return null;
+    }
+}

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/resource/config.xml
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/resource/config.xml?rev=1855815&r1=1855814&r2=1855815&view=diff
==============================================================================
Binary files - no diff available.

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/Constants.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/Constants.java?rev=1855815&r1=1855814&r2=1855815&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/Constants.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/Constants.java Tue Mar 19 12:17:59 2019
@@ -206,6 +206,9 @@ public final class Constants {
     /** Tag of Element J **/
     public static final String _TAG_J = "J";
 
+    /** Tag of Element ECKeyValue **/
+    public static final String _TAG_ECKEYVALUE = "ECKeyValue";
+
     /** Tag of Element Seed **/
     public static final String _TAG_SEED = "Seed";
 

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/ElementProxy.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/ElementProxy.java?rev=1855815&r1=1855814&r2=1855815&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/ElementProxy.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/ElementProxy.java Tue Mar 19 12:17:59 2019
@@ -493,8 +493,9 @@ public abstract class ElementProxy {
 
         if (Constants.SignatureSpecNS.equals(namespace)) {
             XMLUtils.setDsPrefix(prefix);
-        }
-        if (EncryptionConstants.EncryptionSpecNS.equals(namespace)) {
+        } else if (Constants.SignatureSpec11NS.equals(namespace)) {
+            XMLUtils.setDs11Prefix(prefix);
+        } else if (EncryptionConstants.EncryptionSpecNS.equals(namespace)) {
             XMLUtils.setXencPrefix(prefix);
         }
         prefixMappings.put(namespace, prefix);
@@ -514,6 +515,7 @@ public abstract class ElementProxy {
         setNamespacePrefix(
             "http://www.nue.et-inf.uni-siegen.de/~geuer-pollmann/#xpathFilter", "xx"
         );
+        setNamespacePrefix("http://www.w3.org/2009/xmldsig11#", "dsig11");
     }
 
     /**

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/Signature11ElementProxy.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/Signature11ElementProxy.java?rev=1855815&r1=1855814&r2=1855815&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/Signature11ElementProxy.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/Signature11ElementProxy.java Tue Mar 19 12:17:59 2019
@@ -43,6 +43,13 @@ public abstract class Signature11Element
 
         setDocument(doc);
         setElement(XMLUtils.createElementInSignature11Space(doc, this.getBaseLocalName()));
+
+        String prefix = ElementProxy.getDefaultPrefix(getBaseNamespace());
+        if (prefix == null || prefix.length() == 0) {
+            getElement().setAttributeNS(Constants.NamespaceSpecNS, "xmlns", getBaseNamespace());
+        } else {
+            getElement().setAttributeNS(Constants.NamespaceSpecNS, "xmlns:" + prefix, getBaseNamespace());
+        }
     }
 
     /**

Modified: santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/signature/ECDSASignatureTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/signature/ECDSASignatureTest.java?rev=1855815&r1=1855814&r2=1855815&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/signature/ECDSASignatureTest.java (original)
+++ santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/signature/ECDSASignatureTest.java Tue Mar 19 12:17:59 2019
@@ -23,8 +23,11 @@ import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStream;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
 import java.security.KeyStore;
 import java.security.PrivateKey;
+import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 
 import javax.xml.xpath.XPath;
@@ -56,8 +59,6 @@ public class ECDSASignatureTest {
         "src/test/resources/org/apache/xml/security/samples/input/ecdsa.jks";
     private static final String ECDSA_JKS_PASSWORD = "security";
 
-    private KeyStore keyStore;
-
     public ECDSASignatureTest() throws Exception {
 
         //String id = "http://apache.org/xml/properties/dom/document-class-name";
@@ -75,11 +76,14 @@ public class ECDSASignatureTest {
             return;
         }
 
-        keyStore = KeyStore.getInstance("JKS");
+        KeyStore keyStore = KeyStore.getInstance("JKS");
         keyStore.load(new FileInputStream(ECDSA_JKS), ECDSA_JKS_PASSWORD.toCharArray());
 
-        doVerify(doSign());
-        doVerify(doSign());
+        PrivateKey privateKey =
+            (PrivateKey)keyStore.getKey("ECDSA", ECDSA_JKS_PASSWORD.toCharArray());
+
+        doVerify(doSign(privateKey, (X509Certificate)keyStore.getCertificate("ECDSA"), null));
+        doVerify(doSign(privateKey, (X509Certificate)keyStore.getCertificate("ECDSA"), null));
     }
 
     // Failing with more recent BouncyCastle libraries
@@ -102,9 +106,23 @@ public class ECDSASignatureTest {
         }
     }
 
-    private byte[] doSign() throws Exception {
-        PrivateKey privateKey =
-            (PrivateKey)keyStore.getKey("ECDSA", ECDSA_JKS_PASSWORD.toCharArray());
+    @org.junit.Test
+    public void testKeyValue() throws Exception {
+        //
+        // This test fails with the IBM JDK
+        //
+        if ("IBM Corporation".equals(System.getProperty("java.vendor"))) {
+            return;
+        }
+
+        KeyPairGenerator ecKpg = KeyPairGenerator.getInstance("EC");
+        ecKpg.initialize(256);
+        KeyPair ecKeyPair = ecKpg.genKeyPair();
+
+        doVerify(doSign(ecKeyPair.getPrivate(), null, ecKeyPair.getPublic()));
+    }
+
+    private byte[] doSign(PrivateKey privateKey, X509Certificate x509, PublicKey publicKey) throws Exception {
         org.w3c.dom.Document doc = XMLUtils.newDocument();
         doc.appendChild(doc.createComment(" Comment before "));
         Element root = doc.createElementNS("", "RootElement");
@@ -130,8 +148,11 @@ public class ECDSASignatureTest {
         transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);
         sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
 
-        X509Certificate x509 = (X509Certificate)keyStore.getCertificate("ECDSA");
-        sig.addKeyInfo(x509);
+        if (x509 != null) {
+            sig.addKeyInfo(x509);
+        } else {
+            sig.addKeyInfo(publicKey);
+        }
         sig.sign(privateKey);
 
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
@@ -165,11 +186,11 @@ public class ECDSASignatureTest {
             throw new RuntimeException("No keyinfo");
         }
         X509Certificate cert = signature.getKeyInfo().getX509Certificate();
-
-        if (cert == null) {
-            throw new RuntimeException("No certificate");
+        if (cert != null) {
+            assertTrue(signature.checkSignatureValue(cert));
+        } else {
+            assertTrue(signature.checkSignatureValue(signature.getKeyInfo().getPublicKey()));
         }
-        assertTrue(signature.checkSignatureValue(cert) );
     }
 
     private File makeDataFile(String relPath) {
@@ -253,6 +274,6 @@ public class ECDSASignatureTest {
         );
 
     }
-    */
+     */
 
 }
\ No newline at end of file