org.jcp.xml.dsig.internal.dom.DOMReference Maven / Gradle / Ivy
The newest version!
/* */ package org.jcp.xml.dsig.internal.dom;
/* */
/* */ import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
/* */ import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
/* */ import com.sun.org.apache.xml.internal.security.utils.Base64;
/* */ import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream;
/* */ import java.io.ByteArrayInputStream;
/* */ import java.io.InputStream;
/* */ import java.io.OutputStream;
/* */ import java.net.URI;
/* */ import java.net.URISyntaxException;
/* */ import java.security.MessageDigest;
/* */ import java.security.NoSuchAlgorithmException;
/* */ import java.util.ArrayList;
/* */ import java.util.Arrays;
/* */ import java.util.Collections;
/* */ import java.util.List;
/* */ import java.util.logging.Level;
/* */ import java.util.logging.Logger;
/* */ import javax.xml.crypto.Data;
/* */ import javax.xml.crypto.MarshalException;
/* */ import javax.xml.crypto.NodeSetData;
/* */ import javax.xml.crypto.OctetStreamData;
/* */ import javax.xml.crypto.URIDereferencer;
/* */ import javax.xml.crypto.URIReferenceException;
/* */ import javax.xml.crypto.XMLCryptoContext;
/* */ import javax.xml.crypto.dom.DOMCryptoContext;
/* */ import javax.xml.crypto.dom.DOMURIReference;
/* */ import javax.xml.crypto.dsig.DigestMethod;
/* */ import javax.xml.crypto.dsig.Reference;
/* */ import javax.xml.crypto.dsig.Transform;
/* */ import javax.xml.crypto.dsig.TransformException;
/* */ import javax.xml.crypto.dsig.TransformService;
/* */ import javax.xml.crypto.dsig.XMLSignContext;
/* */ import javax.xml.crypto.dsig.XMLSignatureException;
/* */ import javax.xml.crypto.dsig.XMLValidateContext;
/* */ import org.jcp.xml.dsig.internal.DigesterOutputStream;
/* */ import org.w3c.dom.Attr;
/* */ import org.w3c.dom.Document;
/* */ import org.w3c.dom.Element;
/* */ import org.w3c.dom.Node;
/* */
/* */ public final class DOMReference extends DOMStructure
/* */ implements Reference, DOMURIReference
/* */ {
/* 48 */ private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom");
/* */ private final DigestMethod digestMethod;
/* */ private final String id;
/* */ private final List appliedTransforms;
/* */ private final List transforms;
/* */ private final List allTransforms;
/* */ private final Data appliedTransformData;
/* */ private Attr here;
/* */ private final String uri;
/* */ private final String type;
/* */ private byte[] digestValue;
/* */ private byte[] calcDigestValue;
/* */ private Element refElem;
/* 62 */ private boolean digested = false;
/* 63 */ private boolean validated = false;
/* */ private boolean validationStatus;
/* */ private Data derefData;
/* */ private InputStream dis;
/* */ private MessageDigest md;
/* */
/* */ public DOMReference(String uri, String type, DigestMethod dm, List transforms, String id)
/* */ {
/* 86 */ this(uri, type, dm, null, null, transforms, id, null);
/* */ }
/* */
/* */ public DOMReference(String uri, String type, DigestMethod dm, List appliedTransforms, Data result, List transforms, String id)
/* */ {
/* 91 */ this(uri, type, dm, appliedTransforms, result, transforms, id, null);
/* */ }
/* */
/* */ public DOMReference(String uri, String type, DigestMethod dm, List appliedTransforms, Data result, List transforms, String id, byte[] digestValue)
/* */ {
/* 97 */ if (dm == null) {
/* 98 */ throw new NullPointerException("DigestMethod must be non-null");
/* */ }
/* 100 */ if ((appliedTransforms == null) || (appliedTransforms.isEmpty())) {
/* 101 */ this.appliedTransforms = Collections.EMPTY_LIST;
/* */ } else {
/* 103 */ List transformsCopy = new ArrayList(appliedTransforms);
/* 104 */ int i = 0; for (int size = transformsCopy.size(); i < size; i++) {
/* 105 */ if (!(transformsCopy.get(i) instanceof Transform)) {
/* 106 */ throw new ClassCastException("appliedTransforms[" + i + "] is not a valid type");
/* */ }
/* */ }
/* */
/* 110 */ this.appliedTransforms = Collections.unmodifiableList(transformsCopy);
/* */ }
/* */
/* 113 */ if ((transforms == null) || (transforms.isEmpty())) {
/* 114 */ this.transforms = Collections.EMPTY_LIST;
/* */ } else {
/* 116 */ List transformsCopy = new ArrayList(transforms);
/* 117 */ int i = 0; for (int size = transformsCopy.size(); i < size; i++) {
/* 118 */ if (!(transformsCopy.get(i) instanceof Transform)) {
/* 119 */ throw new ClassCastException("transforms[" + i + "] is not a valid type");
/* */ }
/* */ }
/* */
/* 123 */ this.transforms = Collections.unmodifiableList(transformsCopy);
/* */ }
/* 125 */ List all = new ArrayList(this.appliedTransforms);
/* 126 */ all.addAll(this.transforms);
/* 127 */ this.allTransforms = Collections.unmodifiableList(all);
/* 128 */ this.digestMethod = dm;
/* 129 */ this.uri = uri;
/* 130 */ if ((uri != null) && (!uri.equals(""))) {
/* */ try {
/* 132 */ new URI(uri);
/* */ } catch (URISyntaxException e) {
/* 134 */ throw new IllegalArgumentException(e.getMessage());
/* */ }
/* */ }
/* 137 */ this.type = type;
/* 138 */ this.id = id;
/* 139 */ if (digestValue != null) {
/* 140 */ this.digestValue = ((byte[])digestValue.clone());
/* 141 */ this.digested = true;
/* */ }
/* 143 */ this.appliedTransformData = result;
/* */ }
/* */
/* */ public DOMReference(Element refElem, XMLCryptoContext context)
/* */ throws MarshalException
/* */ {
/* 154 */ Element nextSibling = DOMUtils.getFirstChildElement(refElem);
/* 155 */ List transforms = new ArrayList(5);
/* 156 */ if (nextSibling.getLocalName().equals("Transforms")) {
/* 157 */ Element transformElem = DOMUtils.getFirstChildElement(nextSibling);
/* 158 */ while (transformElem != null) {
/* 159 */ transforms.add(new DOMTransform(transformElem, context));
/* 160 */ transformElem = DOMUtils.getNextSiblingElement(transformElem);
/* */ }
/* 162 */ nextSibling = DOMUtils.getNextSiblingElement(nextSibling);
/* */ }
/* */
/* 166 */ Element dmElem = nextSibling;
/* 167 */ this.digestMethod = DOMDigestMethod.unmarshal(dmElem);
/* */ try
/* */ {
/* 171 */ Element dvElem = DOMUtils.getNextSiblingElement(dmElem);
/* 172 */ this.digestValue = Base64.decode(dvElem);
/* */ } catch (Base64DecodingException bde) {
/* 174 */ throw new MarshalException(bde);
/* */ }
/* */
/* 178 */ this.uri = DOMUtils.getAttributeValue(refElem, "URI");
/* 179 */ this.id = DOMUtils.getAttributeValue(refElem, "Id");
/* */
/* 181 */ this.type = DOMUtils.getAttributeValue(refElem, "Type");
/* 182 */ this.here = refElem.getAttributeNodeNS(null, "URI");
/* 183 */ this.refElem = refElem;
/* */
/* 185 */ if (transforms.isEmpty())
/* 186 */ this.transforms = Collections.EMPTY_LIST;
/* */ else {
/* 188 */ this.transforms = Collections.unmodifiableList(transforms);
/* */ }
/* 190 */ this.appliedTransforms = Collections.EMPTY_LIST;
/* 191 */ this.allTransforms = transforms;
/* 192 */ this.appliedTransformData = null;
/* */ }
/* */
/* */ public DigestMethod getDigestMethod() {
/* 196 */ return this.digestMethod;
/* */ }
/* */
/* */ public String getId() {
/* 200 */ return this.id;
/* */ }
/* */
/* */ public String getURI() {
/* 204 */ return this.uri;
/* */ }
/* */
/* */ public String getType() {
/* 208 */ return this.type;
/* */ }
/* */
/* */ public List getTransforms() {
/* 212 */ return this.allTransforms;
/* */ }
/* */
/* */ public byte[] getDigestValue() {
/* 216 */ return this.digestValue == null ? null : (byte[])this.digestValue.clone();
/* */ }
/* */
/* */ public byte[] getCalculatedDigestValue() {
/* 220 */ return this.calcDigestValue == null ? null : (byte[])this.calcDigestValue.clone();
/* */ }
/* */
/* */ public void marshal(Node parent, String dsPrefix, DOMCryptoContext context)
/* */ throws MarshalException
/* */ {
/* 226 */ if (log.isLoggable(Level.FINE)) {
/* 227 */ log.log(Level.FINE, "Marshalling Reference");
/* */ }
/* 229 */ Document ownerDoc = DOMUtils.getOwnerDocument(parent);
/* */
/* 231 */ this.refElem = DOMUtils.createElement(ownerDoc, "Reference", "http://www.w3.org/2000/09/xmldsig#", dsPrefix);
/* */
/* 235 */ DOMUtils.setAttributeID(this.refElem, "Id", this.id);
/* 236 */ DOMUtils.setAttribute(this.refElem, "URI", this.uri);
/* 237 */ DOMUtils.setAttribute(this.refElem, "Type", this.type);
/* */
/* 240 */ if ((!this.transforms.isEmpty()) || (!this.appliedTransforms.isEmpty())) {
/* 241 */ Element transformsElem = DOMUtils.createElement(ownerDoc, "Transforms", "http://www.w3.org/2000/09/xmldsig#", dsPrefix);
/* */
/* 243 */ this.refElem.appendChild(transformsElem);
/* 244 */ int i = 0; for (int size = this.appliedTransforms.size(); i < size; i++) {
/* 245 */ DOMStructure transform = (DOMStructure)this.appliedTransforms.get(i);
/* */
/* 247 */ transform.marshal(transformsElem, dsPrefix, context);
/* */ }
/* 249 */ int i = 0; for (int size = this.transforms.size(); i < size; i++) {
/* 250 */ DOMStructure transform = (DOMStructure)this.transforms.get(i);
/* 251 */ transform.marshal(transformsElem, dsPrefix, context);
/* */ }
/* */
/* */ }
/* */
/* 256 */ ((DOMDigestMethod)this.digestMethod).marshal(this.refElem, dsPrefix, context);
/* */
/* 259 */ if (log.isLoggable(Level.FINE)) {
/* 260 */ log.log(Level.FINE, "Adding digestValueElem");
/* */ }
/* 262 */ Element digestValueElem = DOMUtils.createElement(ownerDoc, "DigestValue", "http://www.w3.org/2000/09/xmldsig#", dsPrefix);
/* */
/* 264 */ if (this.digestValue != null) {
/* 265 */ digestValueElem.appendChild(ownerDoc.createTextNode(Base64.encode(this.digestValue)));
/* */ }
/* */
/* 268 */ this.refElem.appendChild(digestValueElem);
/* */
/* 270 */ parent.appendChild(this.refElem);
/* 271 */ this.here = this.refElem.getAttributeNodeNS(null, "URI");
/* */ }
/* */
/* */ public void digest(XMLSignContext signContext) throws XMLSignatureException
/* */ {
/* 276 */ Data data = null;
/* 277 */ if (this.appliedTransformData == null)
/* 278 */ data = dereference(signContext);
/* */ else {
/* 280 */ data = this.appliedTransformData;
/* */ }
/* 282 */ byte[] digestInput = transform(data, signContext);
/* 283 */ this.digestValue = digestInput;
/* */
/* 286 */ String encodedDV = Base64.encode(this.digestValue);
/* 287 */ if (log.isLoggable(Level.FINE)) {
/* 288 */ log.log(Level.FINE, "Reference object uri = " + this.uri);
/* */ }
/* 290 */ Element digestElem = DOMUtils.getLastChildElement(this.refElem);
/* 291 */ if (digestElem == null) {
/* 292 */ throw new XMLSignatureException("DigestValue element expected");
/* */ }
/* 294 */ DOMUtils.removeAllChildren(digestElem);
/* 295 */ digestElem.appendChild(this.refElem.getOwnerDocument().createTextNode(encodedDV));
/* */
/* 298 */ Boolean cache = (Boolean)signContext.getProperty("javax.xml.dsig.cacheReference");
/* */
/* 300 */ if ((cache != null) && (cache.booleanValue() == true)) {
/* 301 */ this.dis = new ByteArrayInputStream(digestInput);
/* 302 */ this.derefData = data;
/* */ }
/* 304 */ this.digested = true;
/* 305 */ if (log.isLoggable(Level.FINE))
/* 306 */ log.log(Level.FINE, "Reference digesting completed");
/* */ }
/* */
/* */ public boolean validate(XMLValidateContext validateContext)
/* */ throws XMLSignatureException
/* */ {
/* 312 */ if (validateContext == null) {
/* 313 */ throw new NullPointerException("validateContext cannot be null");
/* */ }
/* 315 */ if (this.validated) {
/* 316 */ return this.validationStatus;
/* */ }
/* 318 */ Data data = dereference(validateContext);
/* 319 */ byte[] digestInput = transform(data, validateContext);
/* */
/* 321 */ this.calcDigestValue = digestInput;
/* 322 */ if (log.isLoggable(Level.FINE)) {
/* 323 */ log.log(Level.FINE, "Expected digest: " + Base64.encode(this.digestValue));
/* */
/* 325 */ log.log(Level.FINE, "Actual digest: " + Base64.encode(this.calcDigestValue));
/* */ }
/* */
/* 329 */ this.validationStatus = Arrays.equals(this.digestValue, this.calcDigestValue);
/* 330 */ Boolean cache = (Boolean)validateContext.getProperty("javax.xml.dsig.cacheReference");
/* */
/* 332 */ if ((cache != null) && (cache.booleanValue() == true)) {
/* 333 */ this.dis = new ByteArrayInputStream(digestInput);
/* 334 */ this.derefData = data;
/* */ }
/* 336 */ this.validated = true;
/* 337 */ return this.validationStatus;
/* */ }
/* */
/* */ public Data getDereferencedData() {
/* 341 */ return this.derefData;
/* */ }
/* */
/* */ public InputStream getDigestInputStream() {
/* 345 */ return this.dis;
/* */ }
/* */
/* */ private Data dereference(XMLCryptoContext context) throws XMLSignatureException
/* */ {
/* 350 */ Data data = null;
/* */
/* 353 */ URIDereferencer deref = context.getURIDereferencer();
/* 354 */ if (deref == null)
/* 355 */ deref = DOMURIDereferencer.INSTANCE;
/* */ try
/* */ {
/* 358 */ data = deref.dereference(this, context);
/* 359 */ if (log.isLoggable(Level.FINE)) {
/* 360 */ log.log(Level.FINE, "URIDereferencer class name: " + deref.getClass().getName());
/* */
/* 362 */ log.log(Level.FINE, "Data class name: " + data.getClass().getName());
/* */ }
/* */ }
/* */ catch (URIReferenceException ure) {
/* 366 */ throw new XMLSignatureException(ure);
/* */ }
/* */
/* 369 */ return data;
/* */ }
/* */
/* */ private byte[] transform(Data dereferencedData, XMLCryptoContext context)
/* */ throws XMLSignatureException
/* */ {
/* 375 */ Data data = dereferencedData;
/* */
/* 377 */ if (this.md == null) {
/* */ try {
/* 379 */ this.md = MessageDigest.getInstance("SHA-1");
/* */ } catch (NoSuchAlgorithmException nsae) {
/* 381 */ throw new XMLSignatureException(nsae);
/* */ }
/* */ }
/* 384 */ this.md.reset();
/* 385 */ DigesterOutputStream dos = new DigesterOutputStream(this.md);
/* 386 */ OutputStream os = new UnsyncBufferedOutputStream(dos);
/* 387 */ int i = 0; for (int size = this.transforms.size(); i < size; i++) {
/* 388 */ DOMTransform transform = (DOMTransform)this.transforms.get(i);
/* */ try {
/* 390 */ if (i < size - 1)
/* 391 */ data = transform.transform(data, context);
/* */ else
/* 393 */ data = transform.transform(data, context, os);
/* */ }
/* */ catch (TransformException te) {
/* 396 */ throw new XMLSignatureException(te);
/* */ }
/* */ }
/* */ try
/* */ {
/* 401 */ if (data != null)
/* */ {
/* */ XMLSignatureInput xi;
/* 403 */ if ((data instanceof ApacheData)) {
/* 404 */ xi = ((ApacheData)data).getXMLSignatureInput();
/* */ }
/* */ else
/* */ {
/* */ XMLSignatureInput xi;
/* 405 */ if ((data instanceof OctetStreamData)) {
/* 406 */ xi = new XMLSignatureInput(((OctetStreamData)data).getOctetStream());
/* */ }
/* */ else
/* */ {
/* */ XMLSignatureInput xi;
/* 408 */ if ((data instanceof NodeSetData)) {
/* 409 */ TransformService spi = TransformService.getInstance("http://www.w3.org/TR/2001/REC-xml-c14n-20010315", "DOM");
/* */
/* 411 */ data = spi.transform(data, context);
/* 412 */ xi = new XMLSignatureInput(((OctetStreamData)data).getOctetStream());
/* */ }
/* */ else {
/* 415 */ throw new XMLSignatureException("unrecognized Data type");
/* */ }
/* */ }
/* */ }
/* */ XMLSignatureInput xi;
/* 417 */ xi.updateOutputStream(os);
/* */ }
/* 419 */ os.flush();
/* 420 */ return dos.getDigestValue();
/* */ } catch (Exception e) {
/* 422 */ throw new XMLSignatureException(e);
/* */ }
/* */ }
/* */
/* */ public Node getHere() {
/* 427 */ return this.here;
/* */ }
/* */
/* */ public boolean equals(Object o) {
/* 431 */ if (this == o) {
/* 432 */ return true;
/* */ }
/* */
/* 435 */ if (!(o instanceof DOMURIReference)) {
/* 436 */ return false;
/* */ }
/* 438 */ Reference oref = (DOMURIReference)o;
/* */
/* 440 */ boolean idsEqual = this.id == null ? false : oref.getId() == null ? true : this.id.equals(oref.getId());
/* */
/* 442 */ boolean urisEqual = this.uri == null ? false : oref.getURI() == null ? true : this.uri.equals(oref.getURI());
/* */
/* 444 */ boolean typesEqual = this.type == null ? false : oref.getType() == null ? true : this.type.equals(oref.getType());
/* */
/* 446 */ boolean digestValuesEqual = Arrays.equals(this.digestValue, oref.getDigestValue());
/* */
/* 449 */ return (this.digestMethod.equals(oref.getDigestMethod())) && (idsEqual) && (urisEqual) && (typesEqual) && (this.transforms.equals(oref.getTransforms()));
/* */ }
/* */
/* */ boolean isDigested()
/* */ {
/* 454 */ return this.digested;
/* */ }
/* */ }
/* Location: E:\HYN\Java\trunk\ref\lib-dep\xmldsig\xmldsig.jar
* Qualified Name: org.jcp.xml.dsig.internal.dom.DOMReference
* JD-Core Version: 0.6.2
*/