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 package org.jcp.xml.dsig.internal.dom; 25 26 import java.security.Key; 27 import java.security.InvalidAlgorithmParameterException; 28 import java.security.InvalidKeyException; 29 import java.security.SignatureException; 30 import java.security.spec.AlgorithmParameterSpec; 31 import javax.xml.crypto.MarshalException; 32 import javax.xml.crypto.dom.DOMCryptoContext; 33 import javax.xml.crypto.dsig.SignatureMethod; 34 import javax.xml.crypto.dsig.SignedInfo; 35 import javax.xml.crypto.dsig.XMLSignature; 36 import javax.xml.crypto.dsig.XMLSignatureException; 37 import javax.xml.crypto.dsig.XMLSignContext; 38 import javax.xml.crypto.dsig.XMLValidateContext; 39 import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; 40 import org.w3c.dom.Document; 41 import org.w3c.dom.Element; 42 import org.w3c.dom.Node; 43 44 /** 45 * An abstract class representing a SignatureMethod. Subclasses implement 46 * a specific XML DSig signature algorithm. 47 */ 48 abstract class AbstractDOMSignatureMethod extends DOMStructure 49 implements SignatureMethod { 50 51 // denotes the type of signature algorithm 52 enum Type { DSA, RSA, ECDSA, HMAC } 53 54 /** 55 * Verifies the passed-in signature with the specified key, using the 56 * underlying Signature or Mac algorithm. 57 * 58 * @param key the verification key 59 * @param si the SignedInfo 60 * @param sig the signature bytes to be verified 61 * @param context the XMLValidateContext 62 * @return <code>true</code> if the signature verified successfully, 63 * <code>false</code> if not 64 * @throws NullPointerException if <code>key</code>, <code>si</code> or 65 * <code>sig</code> are <code>null</code> 66 * @throws InvalidKeyException if the key is improperly encoded, of 67 * the wrong type, or parameters are missing, etc 68 * @throws SignatureException if an unexpected error occurs, such 69 * as the passed in signature is improperly encoded 70 * @throws XMLSignatureException if an unexpected error occurs 71 */ 72 abstract boolean verify(Key key, SignedInfo si, byte[] sig, 73 XMLValidateContext context) 74 throws InvalidKeyException, SignatureException, XMLSignatureException; 75 76 /** 77 * Signs the bytes with the specified key, using the underlying 78 * Signature or Mac algorithm. 79 * 80 * @param key the signing key 81 * @param si the SignedInfo 82 * @param context the XMLSignContext 83 * @return the signature 84 * @throws NullPointerException if <code>key</code> or 85 * <code>si</code> are <code>null</code> 86 * @throws InvalidKeyException if the key is improperly encoded, of 87 * the wrong type, or parameters are missing, etc 88 * @throws XMLSignatureException if an unexpected error occurs 89 */ 90 abstract byte[] sign(Key key, SignedInfo si, XMLSignContext context) 91 throws InvalidKeyException, XMLSignatureException; 92 93 /** 94 * Returns the java.security.Signature or javax.crypto.Mac standard 95 * algorithm name. 96 */ 97 abstract String getJCAAlgorithm(); 98 99 /** 100 * Returns the type of signature algorithm. 101 */ 102 abstract Type getAlgorithmType(); 103 104 /** 105 * This method invokes the {@link #marshalParams marshalParams} 106 * method to marshal any algorithm-specific parameters. 107 */ 108 public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) 109 throws MarshalException 110 { 111 Document ownerDoc = DOMUtils.getOwnerDocument(parent); 112 113 Element smElem = DOMUtils.createElement(ownerDoc, "SignatureMethod", 114 XMLSignature.XMLNS, dsPrefix); 115 DOMUtils.setAttribute(smElem, "Algorithm", getAlgorithm()); 116 117 if (getParameterSpec() != null) { 118 marshalParams(smElem, dsPrefix); 119 } 120 121 parent.appendChild(smElem); 122 } 123 124 /** 125 * Marshals the algorithm-specific parameters to an Element and 126 * appends it to the specified parent element. By default, this method 127 * throws an exception since most SignatureMethod algorithms do not have 128 * parameters. Subclasses should override it if they have parameters. 129 * 130 * @param parent the parent element to append the parameters to 131 * @param paramsPrefix the algorithm parameters prefix to use 132 * @throws MarshalException if the parameters cannot be marshalled 133 */ 134 void marshalParams(Element parent, String paramsPrefix) 135 throws MarshalException 136 { 137 throw new MarshalException("no parameters should " + 138 "be specified for the " + getAlgorithm() + 139 " SignatureMethod algorithm"); 140 } 141 142 /** 143 * Unmarshals <code>SignatureMethodParameterSpec</code> from the specified 144 * <code>Element</code>. By default, this method throws an exception since 145 * most SignatureMethod algorithms do not have parameters. Subclasses should 146 * override it if they have parameters. 147 * 148 * @param paramsElem the <code>Element</code> holding the input params 149 * @return the algorithm-specific <code>SignatureMethodParameterSpec</code> 150 * @throws MarshalException if the parameters cannot be unmarshalled 151 */ 152 SignatureMethodParameterSpec unmarshalParams(Element paramsElem) 153 throws MarshalException 154 { 155 throw new MarshalException("no parameters should " + 156 "be specified for the " + getAlgorithm() + 157 " SignatureMethod algorithm"); 158 } 159 160 /** 161 * Checks if the specified parameters are valid for this algorithm. By 162 * default, this method throws an exception if parameters are specified 163 * since most SignatureMethod algorithms do not have parameters. Subclasses 164 * should override it if they have parameters. 165 * 166 * @param params the algorithm-specific params (may be <code>null</code>) 167 * @throws InvalidAlgorithmParameterException if the parameters are not 168 * appropriate for this signature method 169 */ 170 void checkParams(SignatureMethodParameterSpec params) 171 throws InvalidAlgorithmParameterException 172 { 173 if (params != null) { 174 throw new InvalidAlgorithmParameterException("no parameters " + 175 "should be specified for the " + getAlgorithm() + 176 " SignatureMethod algorithm"); 177 } 178 } 179 180 @Override 181 public boolean equals(Object o) 182 { 183 if (this == o) { 184 return true; 185 } 186 187 if (!(o instanceof SignatureMethod)) { 188 return false; 189 } 190 SignatureMethod osm = (SignatureMethod)o; 191 192 return (getAlgorithm().equals(osm.getAlgorithm()) && 193 paramsEqual(osm.getParameterSpec())); 194 } 195 196 @Override 197 public int hashCode() { 198 int result = 17; 199 result = 31 * result + getAlgorithm().hashCode(); 200 AlgorithmParameterSpec spec = getParameterSpec(); 201 if (spec != null) { 202 result = 31 * result + spec.hashCode(); 203 } 204 205 return result; 206 } 207 208 /** 209 * Returns true if parameters are equal; false otherwise. 210 * 211 * Subclasses should override this method to compare algorithm-specific 212 * parameters. 213 */ 214 boolean paramsEqual(AlgorithmParameterSpec spec) 215 { 216 return (getParameterSpec() == spec); 217 } 218 }