package at.gv.egovernment.moa.id.util; import iaik.ixsil.util.URI; import iaik.security.ecc.ecdsa.ECDSAParameter; import iaik.security.ecc.ecdsa.ECPublicKey; //import iaik.security.ecc.interfaces.ECDSAPublicKey; import iaik.security.ecc.math.ecgroup.ECGroupFactory; import iaik.security.ecc.math.ecgroup.ECPoint; import iaik.security.ecc.math.ecgroup.EllipticCurve; import iaik.security.ecc.math.ecgroup.ProjectiveCoordinate; //import iaik.security.ecc.math.field.BinaryField; //import iaik.security.ecc.math.field.BinaryFieldValue; import iaik.security.ecc.math.field.Field; import iaik.security.ecc.math.field.FieldElement; import iaik.security.ecc.math.field.FieldFactory; import iaik.security.ecc.math.field.Value; import iaik.security.ecc.parameter.ECCParameterFactory; import iaik.security.ecc.spec.ECCParameterSpec; import java.math.BigInteger; import java.security.PublicKey; import java.util.HashMap; import java.util.Iterator; import java.util.Vector; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; //import at.gv.cio.identitylink.init.Constants; import at.gv.egovernment.moa.id.util.ECDSAConstants; public class ECDSAKeyValueConverter { //TODO enhance javadoc /** * converter class which can be used to convert ECDSA keys encoded in XML * to a PublicKey data structure * @param keyValueElem ECDSAKeyValue Element * @return ECPublicKey encoded in PublicKey data structure * @throws Exception * * @author gregor karlinger */ public static PublicKey element2ECDSAPublicKey(Element keyValueElem) throws Exception { String ecdsaNS = ECDSAConstants.NAMESPACE_ECDSAKEYVALUE_; // Domain parameters Element domainParams = getChildElement(keyValueElem, ecdsaNS, "DomainParameters", 1); if (domainParams == null) throw new Exception("Domain parameters must not be implicit."); Element namedCurve = getChildElement(domainParams, ecdsaNS, "NamedCurve", 1); ECCParameterSpec eccParameterSpec; if (namedCurve != null) { // URL curveNameURN = new URL(namedCurve.getAttributeNS(null, "URN")); String curveNameOID = namedCurve.getAttributeNS(null, "URN").substring(8); ECCParameterFactory eccParamFactory = ECCParameterFactory.getInstance(); // eccParameterSpec = eccParamFactory.getParameterByOID(curveNameURN.getPath().substring(4)); eccParameterSpec = eccParamFactory.getParameterByOID(curveNameOID); } else { Element excplicitParams = getChildElement(domainParams, ecdsaNS, "ExplicitParams", 1); Element fieldParams = getChildElement(excplicitParams, ecdsaNS, "FieldParams", 1); Element curveParams = getChildElement(excplicitParams, ecdsaNS, "CurveParams", 1); Element basePointParams = getChildElement(excplicitParams, ecdsaNS, "BasePointParams", 1); // Field parameters String fieldParamsTypeStr = fieldParams.getAttributeNS(ECDSAConstants.NAMESPACE_XSI_, "type"); String ecdsaNSPrefix = getECDSANSPrefix(fieldParams); BigInteger p = null; int fieldParamsType = 0; final int FIELD_TYPE_PRIME = 1; final int FIELD_TYPE_TNB = 2; final int FIELD_TYPE_PNB = 3; int m = -1, k = -1, k1 = -1, k2 = -1, k3 = -1; if (fieldParamsTypeStr.equals(ecdsaNSPrefix + ":PrimeFieldParamsType")) { fieldParamsType = FIELD_TYPE_PRIME; String pStr = getChildElementText(fieldParams, ecdsaNS, "P", 1); p = new BigInteger(pStr, 10); } else if (fieldParamsTypeStr.equals(ecdsaNSPrefix + ":TnBFieldParamsType")) { fieldParamsType = FIELD_TYPE_TNB; String mStr = getChildElementText(fieldParams, ecdsaNS, "M", 1); m = Integer.parseInt(mStr); String kStr = getChildElementText(fieldParams, ecdsaNS, "K", 1); k = Integer.parseInt(kStr); } else if (fieldParamsTypeStr.equals(ecdsaNSPrefix + ":PnBFieldParamsType")) { fieldParamsType = FIELD_TYPE_PNB; String mStr = getChildElementText(fieldParams, ecdsaNS, "M", 1); m = Integer.parseInt(mStr); String k1Str = getChildElementText(fieldParams, ecdsaNS, "K1", 1); k1 = Integer.parseInt(k1Str); String k2Str = getChildElementText(fieldParams, ecdsaNS, "K2", 1); k2 = Integer.parseInt(k2Str); String k3Str = getChildElementText(fieldParams, ecdsaNS, "K3", 1); k3 = Integer.parseInt(k3Str); } else throw new Exception("Unknown field parameters."); // Curve parameters Element aElem = getChildElement(curveParams, ecdsaNS, "A", 1); String aStr = aElem.getAttributeNS(null, "Value"); Element bElem = getChildElement(curveParams, ecdsaNS, "B", 1); String bStr = bElem.getAttributeNS(null, "Value"); String seedStr = getChildElementText(curveParams, ecdsaNS, "Seed", 1); BigInteger seed = (seedStr != null) ? new BigInteger(seedStr, 10) : null; // Base point parameters Element basePoint = getChildElement(basePointParams, ecdsaNS, "BasePoint", 1); Element basePointXElem = getChildElement(basePoint, ecdsaNS, "X", 1); String basePointXStr = basePointXElem.getAttributeNS(null, "Value"); Element basePointYElem = getChildElement(basePoint, ecdsaNS, "Y", 1); String basePointYStr = basePointYElem.getAttributeNS(null, "Value"); String orderStr = getChildElementText(basePointParams, ecdsaNS, "Order", 1); BigInteger order = new BigInteger(orderStr, 10); String cofactorStr = getChildElementText(basePointParams, ecdsaNS, "Cofactor", 1); BigInteger cofactor = (cofactorStr != null) ? new BigInteger(cofactorStr, 10) : null; if (fieldParamsType == FIELD_TYPE_PRIME) { BigInteger a = new BigInteger(aStr, 10); BigInteger b = new BigInteger(bStr, 10); BigInteger basePointX = new BigInteger(basePointXStr, 10); BigInteger basePointY = new BigInteger(basePointYStr, 10); eccParameterSpec = new ECCParameterSpec(p, cofactor, order, seed, null, a, b, basePointX, basePointY, null); } else { int[] irreducible = new int[m/32 + ((m % 32 != 0) ? 1 : 0)]; if (fieldParamsType == FIELD_TYPE_TNB) { irreducible[m/32] = 1 << m % 32; irreducible[k/32] += 1 << k % 32; irreducible[0] += 1; } else { irreducible[m/32] = 1 << m % 32; irreducible[k3/32] += 1 << k3 % 32; irreducible[k2/32] += 1 << k2 % 32; irreducible[k1/32] += 1 << k1 % 32; irreducible[0] += 1; } eccParameterSpec = new ECCParameterSpec(irreducible, cofactor, order, octetString2IntArray(aStr), octetString2IntArray(bStr), octetString2IntArray(basePointXStr), octetString2IntArray(basePointYStr), null); } } // Public key Element publicKeyElem = getChildElement(keyValueElem, ecdsaNS, "PublicKey", 1); Element publicKeyXElem = getChildElement(publicKeyElem, ecdsaNS, "X", 1); String publicKeyXStr = publicKeyXElem.getAttributeNS(null, "Value"); Element publicKeyYElem = getChildElement(publicKeyElem, ecdsaNS, "Y", 1); String publicKeyYStr = publicKeyYElem.getAttributeNS(null, "Value"); ECDSAParameter ecdsaParams = new ECDSAParameter(eccParameterSpec, false); ECGroupFactory ecGroupFactory = ECGroupFactory.getInstance(); EllipticCurve eCurve = ecGroupFactory.getCurveWithProjective(eccParameterSpec.getA(), eccParameterSpec.getB(), eccParameterSpec.getR()); Field field = eCurve.getField(); // Detect type of public key field elements String elementType = publicKeyXElem.getAttributeNS(ECDSAConstants.NAMESPACE_XSI_, "type"); String elementTypeLocalName = elementType.substring(elementType.indexOf(':') + 1); int FIELD_TYPE_PRIME = 1, FIELD_TYPE_CHAR_TWO = 2; int fieldElemType = ("PrimeFieldElemType".equals(elementTypeLocalName)) ? FIELD_TYPE_PRIME : FIELD_TYPE_CHAR_TWO; FieldElement publicKeyPointX, publicKeyPointY; if (fieldElemType == FIELD_TYPE_PRIME) { Value xValue = FieldFactory.getInstance().getPrimeFieldValue(new BigInteger(publicKeyXStr, 10)); publicKeyPointX = field.newElement(xValue); Value yValue = FieldFactory.getInstance().getPrimeFieldValue(new BigInteger(publicKeyYStr, 10)); publicKeyPointY = field.newElement(yValue); } else { publicKeyPointX = field.newElement(octetString2ByteArray(publicKeyXStr)); publicKeyPointY = field.newElement(octetString2ByteArray(publicKeyYStr)); } ProjectiveCoordinate publicKeyPointCoordinate = new ProjectiveCoordinate(publicKeyPointX, publicKeyPointY, field.getONEelement()); ECPoint publicKeyPoint = eCurve.newPoint(publicKeyPointCoordinate); ECPublicKey publicKey = new ECPublicKey(ecdsaParams, publicKeyPoint); return publicKey; } /* ---------------------------------------------------------------------------------------------------- */ /* public static Element publicKey2ECDSAKeyValueElement(boolean implParams, String curveOID, ECDSAPublicKey publicKey, Document factoryDoc) { String ecdsaNS = ECDSAConstants.NAMESPACE_ECDSAKEYVALUE_; String ecdsaNSP = ECDSAConstants.NS_PREFIX_ECDSAKEYVALUE_; String nsNS = ECDSAConstants.NAMESPACE_NAMESPACES_; String xsiNS = ECDSAConstants.NAMESPACE_XSI_; String xsiNSP = ECDSAConstants.NS_PREFIX_XSI_; ECDSAParameter params = (ECDSAParameter)publicKey.getParameter(); EllipticCurve curve = params.getG().getCurve(); Field field = curve.getField(); int fieldId = curve.getField().getFieldId(); Element eCDSAKeyValue = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":ECDSAKeyValue"); eCDSAKeyValue.setAttributeNS(nsNS, "xmlns:" + ecdsaNSP, ecdsaNS); eCDSAKeyValue.setAttributeNS(nsNS, "xmlns:" + xsiNSP, xsiNS); // Detect field type int coeffPositions[] = new int[3]; int fieldType = 0; String fieldElemTypeString = null; final int FT_PRIME = 1, FT_TNB = 2, FT_PNB = 3; if (fieldId == Field.PRIME_FIELD) { fieldType = FT_PRIME; fieldElemTypeString = ecdsaNSP + ":PrimeFieldElemType"; } else { // Get irreducible polynomal BinaryField binaryField = (BinaryField)field; BinaryFieldValue irreducible = binaryField.getIrreducible(); // Get coefficients of irreducible polynomal int order = irreducible.getOrder(); int coeffCount = 2; for (int i = 1; i < order - 1; i++) { if (irreducible.testBit(i)) { coeffPositions[coeffCount - 2] = i; coeffCount++; if (coeffCount == 5) break; } } // Set polynomal type (TNB or fieldType = (coeffCount == 3) ? FT_TNB : FT_PNB; fieldElemTypeString = ecdsaNSP + ":CharTwoFieldElemType"; } if (!implParams) { Element domainParameters = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":DomainParameters"); eCDSAKeyValue.appendChild(factoryDoc.createTextNode("\n ")); eCDSAKeyValue.appendChild(domainParameters); if (curveOID != null) { // Named curve Element namedCurve = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":NamedCurve"); namedCurve.setAttributeNS(null, "URN", "urn:oid:" + curveOID); domainParameters.appendChild(factoryDoc.createTextNode("\n ")); domainParameters.appendChild(namedCurve); domainParameters.appendChild(factoryDoc.createTextNode("\n ")); } else { // Explicit parameters Element explicitParams = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":ExplicitParams"); // Field parameters Element fieldParams = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":FieldParams"); explicitParams.appendChild(factoryDoc.createTextNode("\n ")); explicitParams.appendChild(fieldParams); if (fieldType == FT_PRIME) { fieldParams.setAttributeNS(xsiNS, xsiNSP + ":type", ecdsaNSP + ":PrimeFieldParamsType"); Element p = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":P"); p.appendChild(factoryDoc.createTextNode(curve.getField().getSize().toString(10))); fieldParams.appendChild(factoryDoc.createTextNode("\n ")); fieldParams.appendChild(p); fieldParams.appendChild(factoryDoc.createTextNode("\n ")); } else if (fieldType == FT_TNB) { fieldParams.setAttributeNS(xsiNS, xsiNSP + ":type", ecdsaNSP + ":TnBFieldParamsType"); Element m = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":M"); m.appendChild(factoryDoc.createTextNode(Integer.toString(curve.getField().getOrder()))); fieldParams.appendChild(factoryDoc.createTextNode("\n ")); fieldParams.appendChild(m); Element k = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":K"); k.appendChild(factoryDoc.createTextNode(Integer.toString(coeffPositions[0], 10))); fieldParams.appendChild(factoryDoc.createTextNode("\n ")); fieldParams.appendChild(k); fieldParams.appendChild(factoryDoc.createTextNode("\n ")); } else { fieldParams.setAttributeNS(xsiNS, xsiNSP + ":type", ecdsaNSP + ":PnBFieldParamsType"); Element m = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":M"); m.appendChild(factoryDoc.createTextNode(Integer.toString(curve.getField().getOrder()))); fieldParams.appendChild(factoryDoc.createTextNode("\n ")); fieldParams.appendChild(m); Element k1 = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":K1"); k1.appendChild(factoryDoc.createTextNode(Integer.toString(coeffPositions[0]))); fieldParams.appendChild(factoryDoc.createTextNode("\n ")); fieldParams.appendChild(k1); Element k2 = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":K2"); k2.appendChild(factoryDoc.createTextNode(Integer.toString(coeffPositions[1]))); fieldParams.appendChild(factoryDoc.createTextNode("\n ")); fieldParams.appendChild(k2); Element k3 = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":K3"); k3.appendChild(factoryDoc.createTextNode(Integer.toString(coeffPositions[2]))); fieldParams.appendChild(factoryDoc.createTextNode("\n ")); fieldParams.appendChild(k3); fieldParams.appendChild(factoryDoc.createTextNode("\n ")); } // Curve parameters Element curveParams = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":CurveParams"); explicitParams.appendChild(factoryDoc.createTextNode("\n ")); explicitParams.appendChild(curveParams); Element a = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":A"); a.setAttributeNS(xsiNS, xsiNSP + ":type", fieldElemTypeString); a.setAttributeNS(null, "Value", (fieldId == Field.PRIME_FIELD) ? curve.getA().getValue().toBigInt().toString(10) : evenStringLength(curve.getA().getValue().toBigInt().toString(16))); curveParams.appendChild(factoryDoc.createTextNode("\n ")); curveParams.appendChild(a); Element b = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":B"); b.setAttributeNS(xsiNS, xsiNSP + ":type", fieldElemTypeString); b.setAttributeNS(null, "Value", (fieldId == Field.PRIME_FIELD) ? curve.getB().getValue().toBigInt().toString(10) : evenStringLength(curve.getB().getValue().toBigInt().toString(16))); curveParams.appendChild(factoryDoc.createTextNode("\n ")); curveParams.appendChild(b); if (params.getS() != null) { Element seed = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":Seed"); seed.appendChild(factoryDoc.createTextNode(evenStringLength(params.getS().toString(16)))); curveParams.appendChild(factoryDoc.createTextNode("\n ")); curveParams.appendChild(seed); } curveParams.appendChild(factoryDoc.createTextNode("\n ")); // Base point params Element basePointParams = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":BasePointParams"); explicitParams.appendChild(factoryDoc.createTextNode("\n ")); explicitParams.appendChild(basePointParams); Element basePoint = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":BasePoint"); basePointParams.appendChild(factoryDoc.createTextNode("\n ")); basePointParams.appendChild(basePoint); Element x = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":X"); x.setAttributeNS(xsiNS, xsiNSP + ":type", fieldElemTypeString); x.setAttributeNS(null, "Value", (fieldId == Field.PRIME_FIELD) ? params.getG().getCoordinates().getX().getValue().toBigInt().toString(10) : evenStringLength(params.getG().getCoordinates().getX().getValue().toBigInt().toString(16))); basePoint.appendChild(factoryDoc.createTextNode("\n ")); basePoint.appendChild(x); Element y = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":Y"); y.setAttributeNS(xsiNS, xsiNSP + ":type", fieldElemTypeString); y.setAttributeNS(null, "Value", (fieldId == Field.PRIME_FIELD) ? params.getG().getCoordinates().getY().getValue().toBigInt().toString(10) : evenStringLength(params.getG().getCoordinates().getY().getValue().toBigInt().toString(16))); basePoint.appendChild(factoryDoc.createTextNode("\n ")); basePoint.appendChild(y); basePoint.appendChild(factoryDoc.createTextNode("\n ")); Element order = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":Order"); order.appendChild(factoryDoc.createTextNode(params.getR().toString(10))); basePointParams.appendChild(factoryDoc.createTextNode("\n ")); basePointParams.appendChild(order); if (params.getK() != null) { Element cofactor = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":Cofactor"); cofactor.appendChild(factoryDoc.createTextNode(params.getK().toString(10))); basePointParams.appendChild(factoryDoc.createTextNode("\n ")); basePointParams.appendChild(cofactor); } basePointParams.appendChild(factoryDoc.createTextNode("\n ")); explicitParams.appendChild(factoryDoc.createTextNode("\n ")); domainParameters.appendChild(factoryDoc.createTextNode("\n ")); domainParameters.appendChild(explicitParams); domainParameters.appendChild(factoryDoc.createTextNode("\n ")); } } // Public key point Element publicKeyPoint = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":PublicKey"); Element publicKeyX = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":X"); publicKeyX.setAttributeNS(xsiNS, xsiNSP + ":type", fieldElemTypeString); publicKeyX.setAttributeNS(null, "Value", (fieldId == Field.PRIME_FIELD) ? publicKey.getW().getCoordinates().getX().getValue().toBigInt().toString(10) : evenStringLength(publicKey.getW().getCoordinates().getX().getValue().toBigInt().toString(16))); publicKeyPoint.appendChild(factoryDoc.createTextNode("\n ")); publicKeyPoint.appendChild(publicKeyX); Element publicKeyY = factoryDoc.createElementNS(ecdsaNS, ecdsaNSP + ":Y"); publicKeyY.setAttributeNS(xsiNS, xsiNSP + ":type", fieldElemTypeString); publicKeyY.setAttributeNS(null, "Value", (fieldId == Field.PRIME_FIELD) ? publicKey.getW().getCoordinates().getY().getValue().toBigInt().toString(10) : evenStringLength(publicKey.getW().getCoordinates().getY().getValue().toBigInt().toString(16))); publicKeyPoint.appendChild(factoryDoc.createTextNode("\n ")); publicKeyPoint.appendChild(publicKeyY); publicKeyPoint.appendChild(factoryDoc.createTextNode("\n ")); eCDSAKeyValue.appendChild(factoryDoc.createTextNode("\n ")); eCDSAKeyValue.appendChild(publicKeyPoint); eCDSAKeyValue.appendChild(factoryDoc.createTextNode("\n ")); return eCDSAKeyValue; } */ /* ---------------------------------------------------------------------------------------------------- */ private static String getECDSANSPrefix(Element element) { // FIXXME: Review this function (GK, 11.06.2002) - should return a list of strings, since more than // one NS prefix can be bound to the ECDSA namespace HashMap inScopeNSAttrs = getInScopeNSAttrs(element); Iterator inScopeNSAttrsIt = inScopeNSAttrs.keySet().iterator(); while (inScopeNSAttrsIt.hasNext()) { Attr currentAttr = (Attr)inScopeNSAttrs.get(inScopeNSAttrsIt.next()); if (ECDSAConstants.NAMESPACE_ECDSAKEYVALUE_.equals(currentAttr.getValue())) { return ("xmlns".equals(currentAttr.getNodeName())) ? "" : currentAttr.getNodeName().substring(6); } } return null; } /* ---------------------------------------------------------------------------------------------------- */ // Converts an octet string representation into an int array as needed for the IAIK ECC library // String: rightmost byte is least significant byte // IntArray: rightmost byte is LEAST significant byte private static int[] octetString2IntArray(String octetString) { int byteCount = octetString.length()/2; int[] intArray = new int[byteCount/4 + ((byteCount % 4 != 0) ? 1 : 0)]; for (int i = 0; i < byteCount; i++) { int oSStartPos = octetString.length() - (i + 1) * 2; int currentByte = Integer.parseInt(octetString.substring(oSStartPos, oSStartPos + 2), 16); intArray[i/4] += (currentByte & 0xFF) << ((i % 4) * 8); } return intArray; } /* ---------------------------------------------------------------------------------------------------- */ // Converts an octet string representation into a byte array as needed for the IAIK ECC library // String: rightmost byte is least significant byte // ByteArray: rightmost byte is MOST significant byte private static byte[] octetString2ByteArray(String octetString) { int byteCount = octetString.length()/2; byte[] byteArray = new byte[byteCount]; for (int i = 0; i < byteCount; i++) { int oSStartPos = octetString.length() - (i + 1) * 2; byteArray[byteCount - i - 1] = (byte) Integer.parseInt(octetString.substring( oSStartPos, oSStartPos + 2), 16); } return byteArray; } /* ---------------------------------------------------------------------------------------------------- */ private static String evenStringLength(String hexString) { return (hexString.length() % 2 != 0) ? "0" + hexString : hexString; } /* ---------------------------------------------------------------------------------------------------- */ private static Element getChildElement(Element parent, String namespace, String localName, int instance) { NodeList namedElements = parent.getElementsByTagNameNS(namespace, localName); if (namedElements.getLength() < instance) return null; return (Element)namedElements.item(instance - 1); } /* ---------------------------------------------------------------------------------------------------- */ private static String getChildElementText(Element parent, String namespace, String localName, int instance) { Element child = getChildElement(parent, namespace, localName, instance); if (child == null) return null; NodeList childNodes = child.getChildNodes(); int nodeCount = 0; while (nodeCount < childNodes.getLength()) { Node currentNode = childNodes.item(nodeCount); if (currentNode.getNodeType() == Node.TEXT_NODE) return currentNode.getNodeValue(); nodeCount++; } return null; } /* ---------------------------------------------------------------------------------------------------- */ public static HashMap getInScopeNSAttrs(Element element) { // Get all ancestors of element Vector ancestors = new Vector(); ancestors.add(element); Node currentAncestor = element; while ((currentAncestor = currentAncestor.getParentNode()) != null && currentAncestor.getNodeType() == Node.ELEMENT_NODE) { ancestors.add(currentAncestor); } // Scan all ancestors for NS attributes HashMap inScopeNSAttrs = new HashMap(); for (int i = ancestors.size() - 1; i >= 0; i--) { Element currentAncestorElem = (Element)ancestors.get(i); NamedNodeMap attrs = currentAncestorElem.getAttributes(); for (int j = 0; j < attrs.getLength(); j++) { Attr currentAttr = (Attr)attrs.item(j); String currentAttrName = currentAttr.getNodeName(); if ("xmlns".equals(currentAttrName) || currentAttrName.startsWith("xmlns:")) { inScopeNSAttrs.put(currentAttrName, currentAttr); } } } // Check if default NS attribute is in list; if value is empty remove it from list Attr defaultNSAttr = (Attr)inScopeNSAttrs.get("xmlns"); if (defaultNSAttr != null && "".equals(defaultNSAttr.getValue())) inScopeNSAttrs.remove("xmlns"); return inScopeNSAttrs; } }