1/* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5/** 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 */ 23/* 24 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 25 */ 26/* 27 * $Id: DOMKeyValue.java 1333415 2012-05-03 12:03:51Z coheigea $ 28 */ 29package org.jcp.xml.dsig.internal.dom; 30 31import javax.xml.crypto.*; 32import javax.xml.crypto.dom.DOMCryptoContext; 33import javax.xml.crypto.dsig.*; 34import javax.xml.crypto.dsig.keyinfo.KeyValue; 35 36import java.io.IOException; 37import java.math.BigInteger; 38import java.security.KeyException; 39import java.security.KeyFactory; 40import java.security.NoSuchAlgorithmException; 41import java.security.PublicKey; 42import java.security.interfaces.DSAParams; 43import java.security.interfaces.DSAPublicKey; 44import java.security.interfaces.ECPublicKey; 45import java.security.interfaces.RSAPublicKey; 46import java.security.spec.DSAPublicKeySpec; 47import java.security.spec.ECField; 48import java.security.spec.ECFieldFp; 49import java.security.spec.ECParameterSpec; 50import java.security.spec.ECPoint; 51import java.security.spec.ECPublicKeySpec; 52import java.security.spec.EllipticCurve; 53import java.security.spec.InvalidKeySpecException; 54import java.security.spec.KeySpec; 55import java.security.spec.RSAPublicKeySpec; 56import java.util.Arrays; 57import org.w3c.dom.Document; 58import org.w3c.dom.Element; 59import org.w3c.dom.Node; 60 61import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; 62import com.sun.org.apache.xml.internal.security.utils.Base64; 63 64/** 65 * DOM-based implementation of KeyValue. 66 * 67 * @author Sean Mullan 68 */ 69public abstract class DOMKeyValue extends DOMStructure implements KeyValue { 70 71 private static final String XMLDSIG_11_XMLNS 72 = "http://www.w3.org/2009/xmldsig11#"; 73 private final PublicKey publicKey; 74 75 public DOMKeyValue(PublicKey key) throws KeyException { 76 if (key == null) { 77 throw new NullPointerException("key cannot be null"); 78 } 79 this.publicKey = key; 80 } 81 82 /** 83 * Creates a <code>DOMKeyValue</code> from an element. 84 * 85 * @param kvtElem a KeyValue child element 86 */ 87 public DOMKeyValue(Element kvtElem) throws MarshalException { 88 this.publicKey = unmarshalKeyValue(kvtElem); 89 } 90 91 static KeyValue unmarshal(Element kvElem) throws MarshalException { 92 Element kvtElem = DOMUtils.getFirstChildElement(kvElem); 93 if (kvtElem.getLocalName().equals("DSAKeyValue")) { 94 return new DSA(kvtElem); 95 } else if (kvtElem.getLocalName().equals("RSAKeyValue")) { 96 return new RSA(kvtElem); 97 } else if (kvtElem.getLocalName().equals("ECKeyValue")) { 98 return new EC(kvtElem); 99 } else { 100 return new Unknown(kvtElem); 101 } 102 } 103 104 public PublicKey getPublicKey() throws KeyException { 105 if (publicKey == null) { 106 throw new KeyException("can't convert KeyValue to PublicKey"); 107 } else { 108 return publicKey; 109 } 110 } 111 112 public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) 113 throws MarshalException 114 { 115 Document ownerDoc = DOMUtils.getOwnerDocument(parent); 116 117 // create KeyValue element 118 Element kvElem = DOMUtils.createElement(ownerDoc, "KeyValue", 119 XMLSignature.XMLNS, dsPrefix); 120 marshalPublicKey(kvElem, ownerDoc, dsPrefix, context); 121 122 parent.appendChild(kvElem); 123 } 124 125 abstract void marshalPublicKey(Node parent, Document doc, String dsPrefix, 126 DOMCryptoContext context) throws MarshalException; 127 128 abstract PublicKey unmarshalKeyValue(Element kvtElem) 129 throws MarshalException; 130 131 private static PublicKey generatePublicKey(KeyFactory kf, KeySpec keyspec) { 132 try { 133 return kf.generatePublic(keyspec); 134 } catch (InvalidKeySpecException e) { 135 //@@@ should dump exception to log 136 return null; 137 } 138 } 139 140 @Override 141 public boolean equals(Object obj) { 142 if (this == obj) { 143 return true; 144 } 145 if (!(obj instanceof KeyValue)) { 146 return false; 147 } 148 try { 149 KeyValue kv = (KeyValue)obj; 150 if (publicKey == null ) { 151 if (kv.getPublicKey() != null) { 152 return false; 153 } 154 } else if (!publicKey.equals(kv.getPublicKey())) { 155 return false; 156 } 157 } catch (KeyException ke) { 158 // no practical way to determine if the keys are equal 159 return false; 160 } 161 162 return true; 163 } 164 165 @Override 166 public int hashCode() { 167 int result = 17; 168 if (publicKey != null) { 169 result = 31 * result + publicKey.hashCode(); 170 } 171 172 return result; 173 } 174 175 static final class RSA extends DOMKeyValue { 176 // RSAKeyValue CryptoBinaries 177 private DOMCryptoBinary modulus, exponent; 178 private KeyFactory rsakf; 179 180 RSA(PublicKey key) throws KeyException { 181 super(key); 182 RSAPublicKey rkey = (RSAPublicKey)key; 183 exponent = new DOMCryptoBinary(rkey.getPublicExponent()); 184 modulus = new DOMCryptoBinary(rkey.getModulus()); 185 } 186 187 RSA(Element elem) throws MarshalException { 188 super(elem); 189 } 190 191 void marshalPublicKey(Node parent, Document doc, String dsPrefix, 192 DOMCryptoContext context) throws MarshalException { 193 Element rsaElem = DOMUtils.createElement(doc, "RSAKeyValue", 194 XMLSignature.XMLNS, 195 dsPrefix); 196 Element modulusElem = DOMUtils.createElement(doc, "Modulus", 197 XMLSignature.XMLNS, 198 dsPrefix); 199 Element exponentElem = DOMUtils.createElement(doc, "Exponent", 200 XMLSignature.XMLNS, 201 dsPrefix); 202 modulus.marshal(modulusElem, dsPrefix, context); 203 exponent.marshal(exponentElem, dsPrefix, context); 204 rsaElem.appendChild(modulusElem); 205 rsaElem.appendChild(exponentElem); 206 parent.appendChild(rsaElem); 207 } 208 209 PublicKey unmarshalKeyValue(Element kvtElem) 210 throws MarshalException 211 { 212 if (rsakf == null) { 213 try { 214 rsakf = KeyFactory.getInstance("RSA"); 215 } catch (NoSuchAlgorithmException e) { 216 throw new RuntimeException 217 ("unable to create RSA KeyFactory: " + e.getMessage()); 218 } 219 } 220 Element modulusElem = DOMUtils.getFirstChildElement(kvtElem, 221 "Modulus"); 222 modulus = new DOMCryptoBinary(modulusElem.getFirstChild()); 223 Element exponentElem = DOMUtils.getNextSiblingElement(modulusElem, 224 "Exponent"); 225 exponent = new DOMCryptoBinary(exponentElem.getFirstChild()); 226 RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus.getBigNum(), 227 exponent.getBigNum()); 228 return generatePublicKey(rsakf, spec); 229 } 230 } 231 232 static final class DSA extends DOMKeyValue { 233 // DSAKeyValue CryptoBinaries 234 private DOMCryptoBinary p, q, g, y, j; //, seed, pgen; 235 private KeyFactory dsakf; 236 237 DSA(PublicKey key) throws KeyException { 238 super(key); 239 DSAPublicKey dkey = (DSAPublicKey) key; 240 DSAParams params = dkey.getParams(); 241 p = new DOMCryptoBinary(params.getP()); 242 q = new DOMCryptoBinary(params.getQ()); 243 g = new DOMCryptoBinary(params.getG()); 244 y = new DOMCryptoBinary(dkey.getY()); 245 } 246 247 DSA(Element elem) throws MarshalException { 248 super(elem); 249 } 250 251 void marshalPublicKey(Node parent, Document doc, String dsPrefix, 252 DOMCryptoContext context) 253 throws MarshalException 254 { 255 Element dsaElem = DOMUtils.createElement(doc, "DSAKeyValue", 256 XMLSignature.XMLNS, 257 dsPrefix); 258 // parameters J, Seed & PgenCounter are not included 259 Element pElem = DOMUtils.createElement(doc, "P", XMLSignature.XMLNS, 260 dsPrefix); 261 Element qElem = DOMUtils.createElement(doc, "Q", XMLSignature.XMLNS, 262 dsPrefix); 263 Element gElem = DOMUtils.createElement(doc, "G", XMLSignature.XMLNS, 264 dsPrefix); 265 Element yElem = DOMUtils.createElement(doc, "Y", XMLSignature.XMLNS, 266 dsPrefix); 267 p.marshal(pElem, dsPrefix, context); 268 q.marshal(qElem, dsPrefix, context); 269 g.marshal(gElem, dsPrefix, context); 270 y.marshal(yElem, dsPrefix, context); 271 dsaElem.appendChild(pElem); 272 dsaElem.appendChild(qElem); 273 dsaElem.appendChild(gElem); 274 dsaElem.appendChild(yElem); 275 parent.appendChild(dsaElem); 276 } 277 278 PublicKey unmarshalKeyValue(Element kvtElem) 279 throws MarshalException 280 { 281 if (dsakf == null) { 282 try { 283 dsakf = KeyFactory.getInstance("DSA"); 284 } catch (NoSuchAlgorithmException e) { 285 throw new RuntimeException 286 ("unable to create DSA KeyFactory: " + e.getMessage()); 287 } 288 } 289 Element curElem = DOMUtils.getFirstChildElement(kvtElem); 290 // check for P and Q 291 if (curElem.getLocalName().equals("P")) { 292 p = new DOMCryptoBinary(curElem.getFirstChild()); 293 curElem = DOMUtils.getNextSiblingElement(curElem, "Q"); 294 q = new DOMCryptoBinary(curElem.getFirstChild()); 295 curElem = DOMUtils.getNextSiblingElement(curElem); 296 } 297 if (curElem.getLocalName().equals("G")) { 298 g = new DOMCryptoBinary(curElem.getFirstChild()); 299 curElem = DOMUtils.getNextSiblingElement(curElem, "Y"); 300 } 301 y = new DOMCryptoBinary(curElem.getFirstChild()); 302 curElem = DOMUtils.getNextSiblingElement(curElem); 303 if (curElem != null && curElem.getLocalName().equals("J")) { 304 j = new DOMCryptoBinary(curElem.getFirstChild()); 305 // curElem = DOMUtils.getNextSiblingElement(curElem); 306 } 307 /* 308 if (curElem != null) { 309 seed = new DOMCryptoBinary(curElem.getFirstChild()); 310 curElem = DOMUtils.getNextSiblingElement(curElem); 311 pgen = new DOMCryptoBinary(curElem.getFirstChild()); 312 } 313 */ 314 //@@@ do we care about j, pgenCounter or seed? 315 DSAPublicKeySpec spec = new DSAPublicKeySpec(y.getBigNum(), 316 p.getBigNum(), 317 q.getBigNum(), 318 g.getBigNum()); 319 return generatePublicKey(dsakf, spec); 320 } 321 } 322 323 static final class EC extends DOMKeyValue { 324 // ECKeyValue CryptoBinaries 325 private byte[] ecPublicKey; 326 private KeyFactory eckf; 327 private ECParameterSpec ecParams; 328 329 /* Supported curve, secp256r1 */ 330 private static final Curve SECP256R1 = initializeCurve( 331 "secp256r1 [NIST P-256, X9.62 prime256v1]", 332 "1.2.840.10045.3.1.7", 333 "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 334 "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 335 "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", 336 "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", 337 "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", 338 "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 339 1 340 ); 341 342 /* Supported curve secp384r1 */ 343 private static final Curve SECP384R1 = initializeCurve( 344 "secp384r1 [NIST P-384]", 345 "1.3.132.0.34", 346 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", 347 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", 348 "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", 349 "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", 350 "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", 351 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", 352 1 353 ); 354 355 /* Supported curve secp521r1 */ 356 private static final Curve SECP521R1 = initializeCurve( 357 "secp521r1 [NIST P-521]", 358 "1.3.132.0.35", 359 "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 360 "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", 361 "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", 362 "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", 363 "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", 364 "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", 365 1 366 ); 367 368 private static Curve initializeCurve(String name, String oid, 369 String sfield, String a, String b, 370 String x, String y, String n, int h) { 371 BigInteger p = bigInt(sfield); 372 ECField field = new ECFieldFp(p); 373 EllipticCurve curve = new EllipticCurve(field, bigInt(a), 374 bigInt(b)); 375 ECPoint g = new ECPoint(bigInt(x), bigInt(y)); 376 return new Curve(name, oid, curve, g, bigInt(n), h); 377 } 378 379 EC(PublicKey key) throws KeyException { 380 super(key); 381 ECPublicKey ecKey = (ECPublicKey)key; 382 ECPoint ecPoint = ecKey.getW(); 383 ecParams = ecKey.getParams(); 384 ecPublicKey = encodePoint(ecPoint, ecParams.getCurve()); 385 } 386 387 EC(Element dmElem) throws MarshalException { 388 super(dmElem); 389 } 390 391 private static ECPoint decodePoint(byte[] data, EllipticCurve curve) 392 throws IOException { 393 if ((data.length == 0) || (data[0] != 4)) { 394 throw new IOException("Only uncompressed point format " + 395 "supported"); 396 } 397 // Per ANSI X9.62, an encoded point is a 1 byte type followed by 398 // ceiling(log base 2 field-size / 8) bytes of x and the same of y. 399 int n = (data.length - 1) / 2; 400 if (n != ((curve.getField().getFieldSize() + 7) >> 3)) { 401 throw new IOException("Point does not match field size"); 402 } 403 404 byte[] xb = Arrays.copyOfRange(data, 1, 1 + n); 405 byte[] yb = Arrays.copyOfRange(data, n + 1, n + 1 + n); 406 407 return new ECPoint(new BigInteger(1, xb), new BigInteger(1, yb)); 408 } 409 410 private static byte[] encodePoint(ECPoint point, EllipticCurve curve) { 411 // get field size in bytes (rounding up) 412 int n = (curve.getField().getFieldSize() + 7) >> 3; 413 byte[] xb = trimZeroes(point.getAffineX().toByteArray()); 414 byte[] yb = trimZeroes(point.getAffineY().toByteArray()); 415 if ((xb.length > n) || (yb.length > n)) { 416 throw new RuntimeException("Point coordinates do not " + 417 "match field size"); 418 } 419 byte[] b = new byte[1 + (n << 1)]; 420 b[0] = 4; // uncompressed 421 System.arraycopy(xb, 0, b, n - xb.length + 1, xb.length); 422 System.arraycopy(yb, 0, b, b.length - yb.length, yb.length); 423 return b; 424 } 425 426 private static byte[] trimZeroes(byte[] b) { 427 int i = 0; 428 while ((i < b.length - 1) && (b[i] == 0)) { 429 i++; 430 } 431 if (i == 0) { 432 return b; 433 } 434 return Arrays.copyOfRange(b, i, b.length); 435 } 436 437 private static String getCurveOid(ECParameterSpec params) { 438 // Check that the params represent one of the supported 439 // curves. If there is a match, return the object identifier 440 // of the curve. 441 Curve match; 442 if (matchCurve(params, SECP256R1)) { 443 match = SECP256R1; 444 } else if (matchCurve(params, SECP384R1)) { 445 match = SECP384R1; 446 } else if (matchCurve(params, SECP521R1)) { 447 match = SECP521R1; 448 } else { 449 return null; 450 } 451 return match.getObjectId(); 452 } 453 454 private static boolean matchCurve(ECParameterSpec params, Curve curve) { 455 int fieldSize = params.getCurve().getField().getFieldSize(); 456 if (curve.getCurve().getField().getFieldSize() == fieldSize 457 && curve.getCurve().equals(params.getCurve()) 458 && curve.getGenerator().equals(params.getGenerator()) 459 && curve.getOrder().equals(params.getOrder()) 460 && curve.getCofactor() == params.getCofactor()) { 461 return true; 462 } else { 463 return false; 464 } 465 } 466 467 private static ECParameterSpec getECParameterSpec(String oid) { 468 if (oid.equals(SECP256R1.getObjectId())) { 469 return SECP256R1; 470 } else if (oid.equals(SECP384R1.getObjectId())) { 471 return SECP384R1; 472 } else if (oid.equals(SECP521R1.getObjectId())) { 473 return SECP521R1; 474 } else { 475 return null; 476 } 477 } 478 479 void marshalPublicKey(Node parent, Document doc, String dsPrefix, 480 DOMCryptoContext context) 481 throws MarshalException 482 { 483 String prefix = DOMUtils.getNSPrefix(context, XMLDSIG_11_XMLNS); 484 Element ecKeyValueElem = DOMUtils.createElement(doc, "ECKeyValue", 485 XMLDSIG_11_XMLNS, 486 prefix); 487 Element namedCurveElem = DOMUtils.createElement(doc, "NamedCurve", 488 XMLDSIG_11_XMLNS, 489 prefix); 490 Element publicKeyElem = DOMUtils.createElement(doc, "PublicKey", 491 XMLDSIG_11_XMLNS, 492 prefix); 493 Object[] args = new Object[] { ecParams }; 494 String oid = getCurveOid(ecParams); 495 if (oid == null) { 496 throw new MarshalException("Invalid ECParameterSpec"); 497 } 498 DOMUtils.setAttribute(namedCurveElem, "URI", "urn:oid:" + oid); 499 String qname = (prefix == null || prefix.length() == 0) 500 ? "xmlns" : "xmlns:" + prefix; 501 namedCurveElem.setAttributeNS("http://www.w3.org/2000/xmlns/", 502 qname, XMLDSIG_11_XMLNS); 503 ecKeyValueElem.appendChild(namedCurveElem); 504 String encoded = Base64.encode(ecPublicKey); 505 publicKeyElem.appendChild 506 (DOMUtils.getOwnerDocument(publicKeyElem).createTextNode(encoded)); 507 ecKeyValueElem.appendChild(publicKeyElem); 508 parent.appendChild(ecKeyValueElem); 509 } 510 511 PublicKey unmarshalKeyValue(Element kvtElem) 512 throws MarshalException 513 { 514 if (eckf == null) { 515 try { 516 eckf = KeyFactory.getInstance("EC"); 517 } catch (NoSuchAlgorithmException e) { 518 throw new RuntimeException 519 ("unable to create EC KeyFactory: " + e.getMessage()); 520 } 521 } 522 ECParameterSpec ecParams = null; 523 Element curElem = DOMUtils.getFirstChildElement(kvtElem); 524 if (curElem.getLocalName().equals("ECParameters")) { 525 throw new UnsupportedOperationException 526 ("ECParameters not supported"); 527 } else if (curElem.getLocalName().equals("NamedCurve")) { 528 String uri = DOMUtils.getAttributeValue(curElem, "URI"); 529 // strip off "urn:oid" 530 if (uri.startsWith("urn:oid:")) { 531 String oid = uri.substring(8); 532 ecParams = getECParameterSpec(oid); 533 if (ecParams == null) { 534 throw new MarshalException("Invalid curve OID"); 535 } 536 } else { 537 throw new MarshalException("Invalid NamedCurve URI"); 538 } 539 } else { 540 throw new MarshalException("Invalid ECKeyValue"); 541 } 542 curElem = DOMUtils.getNextSiblingElement(curElem, "PublicKey"); 543 ECPoint ecPoint = null; 544 545 try { 546 ecPoint = decodePoint(Base64.decode(curElem), 547 ecParams.getCurve()); 548 } catch (Base64DecodingException bde) { 549 throw new MarshalException("Invalid EC PublicKey", bde); 550 } catch (IOException ioe) { 551 throw new MarshalException("Invalid EC Point", ioe); 552 } 553 554 ECPublicKeySpec spec = new ECPublicKeySpec(ecPoint, ecParams); 555 return generatePublicKey(eckf, spec); 556 } 557 558 static final class Curve extends ECParameterSpec { 559 private final String name; 560 private final String oid; 561 562 Curve(String name, String oid, EllipticCurve curve, 563 ECPoint g, BigInteger n, int h) { 564 super(curve, g, n, h); 565 this.name = name; 566 this.oid = oid; 567 } 568 569 private String getName() { 570 return name; 571 } 572 573 private String getObjectId() { 574 return oid; 575 } 576 } 577 } 578 579 private static BigInteger bigInt(String s) { 580 return new BigInteger(s, 16); 581 } 582 583 static final class Unknown extends DOMKeyValue { 584 private javax.xml.crypto.dom.DOMStructure externalPublicKey; 585 Unknown(Element elem) throws MarshalException { 586 super(elem); 587 } 588 PublicKey unmarshalKeyValue(Element kvElem) throws MarshalException { 589 externalPublicKey = new javax.xml.crypto.dom.DOMStructure(kvElem); 590 return null; 591 } 592 void marshalPublicKey(Node parent, Document doc, String dsPrefix, 593 DOMCryptoContext context) 594 throws MarshalException 595 { 596 parent.appendChild(externalPublicKey.getNode()); 597 } 598 } 599} 600