/* |
|
* reserved comment block |
|
* DO NOT REMOVE OR ALTER! |
|
*/ |
|
/** |
|
* 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.jcp.xml.dsig.internal.dom; |
|
import java.security.Key; |
|
import java.security.InvalidAlgorithmParameterException; |
|
import java.security.InvalidKeyException; |
|
import java.security.SignatureException; |
|
import java.security.spec.AlgorithmParameterSpec; |
|
import javax.xml.crypto.MarshalException; |
|
import javax.xml.crypto.dom.DOMCryptoContext; |
|
import javax.xml.crypto.dsig.SignatureMethod; |
|
import javax.xml.crypto.dsig.SignedInfo; |
|
import javax.xml.crypto.dsig.XMLSignature; |
|
import javax.xml.crypto.dsig.XMLSignatureException; |
|
import javax.xml.crypto.dsig.XMLSignContext; |
|
import javax.xml.crypto.dsig.XMLValidateContext; |
|
import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; |
|
import org.w3c.dom.Document; |
|
import org.w3c.dom.Element; |
|
import org.w3c.dom.Node; |
|
/** |
|
* An abstract class representing a SignatureMethod. Subclasses implement |
|
* a specific XML DSig signature algorithm. |
|
*/ |
|
abstract class AbstractDOMSignatureMethod extends DOMStructure |
|
implements SignatureMethod { |
|
// denotes the type of signature algorithm |
|
enum Type { DSA, RSA, ECDSA, HMAC } |
|
/** |
|
* Verifies the passed-in signature with the specified key, using the |
|
* underlying Signature or Mac algorithm. |
|
* |
|
* @param key the verification key |
|
* @param si the SignedInfo |
|
* @param sig the signature bytes to be verified |
|
* @param context the XMLValidateContext |
|
* @return {@code true} if the signature verified successfully, |
|
* {@code false} if not |
|
* @throws NullPointerException if {@code key}, {@code si} or |
|
* {@code sig} are {@code null} |
|
* @throws InvalidKeyException if the key is improperly encoded, of |
|
* the wrong type, or parameters are missing, etc |
|
* @throws SignatureException if an unexpected error occurs, such |
|
* as the passed in signature is improperly encoded |
|
* @throws XMLSignatureException if an unexpected error occurs |
|
*/ |
|
abstract boolean verify(Key key, SignedInfo si, byte[] sig, |
|
XMLValidateContext context) |
|
throws InvalidKeyException, SignatureException, XMLSignatureException; |
|
/** |
|
* Signs the bytes with the specified key, using the underlying |
|
* Signature or Mac algorithm. |
|
* |
|
* @param key the signing key |
|
* @param si the SignedInfo |
|
* @param context the XMLSignContext |
|
* @return the signature |
|
* @throws NullPointerException if {@code key} or |
|
* {@code si} are {@code null} |
|
* @throws InvalidKeyException if the key is improperly encoded, of |
|
* the wrong type, or parameters are missing, etc |
|
* @throws XMLSignatureException if an unexpected error occurs |
|
*/ |
|
abstract byte[] sign(Key key, SignedInfo si, XMLSignContext context) |
|
throws InvalidKeyException, XMLSignatureException; |
|
/** |
|
* Returns the java.security.Signature or javax.crypto.Mac standard |
|
* algorithm name. |
|
*/ |
|
abstract String getJCAAlgorithm(); |
|
/** |
|
* Returns the type of signature algorithm. |
|
*/ |
|
abstract Type getAlgorithmType(); |
|
/** |
|
* This method invokes the {@link #marshalParams marshalParams} |
|
* method to marshal any algorithm-specific parameters. |
|
*/ |
|
@Override |
|
public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) |
|
throws MarshalException |
|
{ |
|
Document ownerDoc = DOMUtils.getOwnerDocument(parent); |
|
Element smElem = DOMUtils.createElement(ownerDoc, "SignatureMethod", |
|
XMLSignature.XMLNS, dsPrefix); |
|
DOMUtils.setAttribute(smElem, "Algorithm", getAlgorithm()); |
|
if (getParameterSpec() != null) { |
|
marshalParams(smElem, dsPrefix); |
|
} |
|
parent.appendChild(smElem); |
|
} |
|
/** |
|
* Marshals the algorithm-specific parameters to an Element and |
|
* appends it to the specified parent element. By default, this method |
|
* throws an exception since most SignatureMethod algorithms do not have |
|
* parameters. Subclasses should override it if they have parameters. |
|
* |
|
* @param parent the parent element to append the parameters to |
|
* @param paramsPrefix the algorithm parameters prefix to use |
|
* @throws MarshalException if the parameters cannot be marshalled |
|
*/ |
|
void marshalParams(Element parent, String paramsPrefix) |
|
throws MarshalException |
|
{ |
|
throw new MarshalException("no parameters should " + |
|
"be specified for the " + getAlgorithm() + |
|
" SignatureMethod algorithm"); |
|
} |
|
/** |
|
* Unmarshals {@code SignatureMethodParameterSpec} from the specified |
|
* {@code Element}. By default, this method throws an exception since |
|
* most SignatureMethod algorithms do not have parameters. Subclasses should |
|
* override it if they have parameters. |
|
* |
|
* @param paramsElem the {@code Element} holding the input params |
|
* @return the algorithm-specific {@code SignatureMethodParameterSpec} |
|
* @throws MarshalException if the parameters cannot be unmarshalled |
|
*/ |
|
SignatureMethodParameterSpec unmarshalParams(Element paramsElem) |
|
throws MarshalException |
|
{ |
|
throw new MarshalException("no parameters should " + |
|
"be specified for the " + getAlgorithm() + |
|
" SignatureMethod algorithm"); |
|
} |
|
/** |
|
* Checks if the specified parameters are valid for this algorithm. By |
|
* default, this method throws an exception if parameters are specified |
|
* since most SignatureMethod algorithms do not have parameters. Subclasses |
|
* should override it if they have parameters. |
|
* |
|
* @param params the algorithm-specific params (may be {@code null}) |
|
* @throws InvalidAlgorithmParameterException if the parameters are not |
|
* appropriate for this signature method |
|
*/ |
|
void checkParams(SignatureMethodParameterSpec params) |
|
throws InvalidAlgorithmParameterException |
|
{ |
|
if (params != null) { |
|
throw new InvalidAlgorithmParameterException("no parameters " + |
|
"should be specified for the " + getAlgorithm() + |
|
" SignatureMethod algorithm"); |
|
} |
|
} |
|
@Override |
|
public boolean equals(Object o) |
|
{ |
|
if (this == o) { |
|
return true; |
|
} |
|
if (!(o instanceof SignatureMethod)) { |
|
return false; |
|
} |
|
SignatureMethod osm = (SignatureMethod)o; |
|
return getAlgorithm().equals(osm.getAlgorithm()) && |
|
paramsEqual(osm.getParameterSpec()); |
|
} |
|
@Override |
|
public int hashCode() { |
|
int result = 17; |
|
result = 31 * result + getAlgorithm().hashCode(); |
|
AlgorithmParameterSpec spec = getParameterSpec(); |
|
if (spec != null) { |
|
result = 31 * result + spec.hashCode(); |
|
} |
|
return result; |
|
} |
|
/** |
|
* Returns true if parameters are equal; false otherwise. |
|
* |
|
* Subclasses should override this method to compare algorithm-specific |
|
* parameters. |
|
*/ |
|
boolean paramsEqual(AlgorithmParameterSpec spec) |
|
{ |
|
return getParameterSpec() == spec; |
|
} |
|
} |