1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright  1999-2004 The Apache Software Foundation.
   7  *
   8  *  Licensed under the Apache License, Version 2.0 (the "License");
   9  *  you may not use this file except in compliance with the License.
  10  *  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  *  Unless required by applicable law or agreed to in writing, software
  15  *  distributed under the License is distributed on an "AS IS" BASIS,
  16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  *  See the License for the specific language governing permissions and
  18  *  limitations under the License.
  19  *
  20  */
  21 package com.sun.org.apache.xml.internal.security.algorithms;
  22 
  23 import java.security.MessageDigest;
  24 import java.security.NoSuchProviderException;
  25 import java.util.HashMap;
  26 import java.util.Map;
  27 
  28 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
  29 import com.sun.org.apache.xml.internal.security.utils.Constants;
  30 import com.sun.org.apache.xml.internal.security.utils.EncryptionConstants;
  31 import org.w3c.dom.Document;
  32 
  33 
  34 /**
  35  * Digest Message wrapper & selector class.
  36  *
  37  * <pre>
  38  * MessageDigestAlgorithm.getInstance()
  39  * </pre>
  40  *
  41  */
  42 public class MessageDigestAlgorithm extends Algorithm {
  43 
  44     /** Message Digest - NOT RECOMMENDED MD5*/
  45    public static final String ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5 = Constants.MoreAlgorithmsSpecNS + "md5";
  46    /** Digest - Required SHA1*/
  47    public static final String ALGO_ID_DIGEST_SHA1 = Constants.SignatureSpecNS + "sha1";
  48    /** Message Digest - RECOMMENDED SHA256*/
  49    public static final String ALGO_ID_DIGEST_SHA256 = EncryptionConstants.EncryptionSpecNS + "sha256";
  50    /** Message Digest - OPTIONAL SHA384*/
  51    public static final String ALGO_ID_DIGEST_SHA384 = Constants.MoreAlgorithmsSpecNS + "sha384";
  52    /** Message Digest - OPTIONAL SHA512*/
  53    public static final String ALGO_ID_DIGEST_SHA512 = EncryptionConstants.EncryptionSpecNS + "sha512";
  54    /** Message Digest - OPTIONAL RIPEMD-160*/
  55    public static final String ALGO_ID_DIGEST_RIPEMD160 = EncryptionConstants.EncryptionSpecNS + "ripemd160";
  56 
  57    /** Field algorithm stores the actual {@link java.security.MessageDigest} */
  58    java.security.MessageDigest algorithm = null;
  59 
  60    /**
  61     * Constructor for the brave who pass their own message digest algorithms and the corresponding URI.
  62     * @param doc
  63     * @param messageDigest
  64     * @param algorithmURI
  65     */
  66    private MessageDigestAlgorithm(Document doc, MessageDigest messageDigest,
  67                                   String algorithmURI) {
  68 
  69       super(doc, algorithmURI);
  70 
  71       this.algorithm = messageDigest;
  72    }
  73 
  74    static ThreadLocal<Map<String, MessageDigest>> instances=new
  75        ThreadLocal<Map<String, MessageDigest>>() {
  76            protected Map<String, MessageDigest> initialValue() {
  77                return new HashMap<String, MessageDigest>();
  78            };
  79    };
  80 
  81    /**
  82     * Factory method for constructing a message digest algorithm by name.
  83     *
  84     * @param doc
  85     * @param algorithmURI
  86     * @return The MessageDigestAlgorithm element to attach in document and to digest
  87     * @throws XMLSignatureException
  88     */
  89    public static MessageDigestAlgorithm getInstance(
  90            Document doc, String algorithmURI) throws XMLSignatureException {
  91           MessageDigest md = getDigestInstance(algorithmURI);
  92       return new MessageDigestAlgorithm(doc, md, algorithmURI);
  93    }
  94 
  95 private static MessageDigest getDigestInstance(String algorithmURI) throws XMLSignatureException {
  96         MessageDigest result= instances.get().get(algorithmURI);
  97         if (result!=null)
  98                 return result;
  99     String algorithmID = JCEMapper.translateURItoJCEID(algorithmURI);
 100 
 101           if (algorithmID == null) {
 102                   Object[] exArgs = { algorithmURI };
 103                   throw new XMLSignatureException("algorithms.NoSuchMap", exArgs);
 104           }
 105 
 106       MessageDigest md;
 107       String provider=JCEMapper.getProviderId();
 108       try {
 109          if (provider==null) {
 110                 md = MessageDigest.getInstance(algorithmID);
 111          } else {
 112                 md = MessageDigest.getInstance(algorithmID,provider);
 113          }
 114       } catch (java.security.NoSuchAlgorithmException ex) {
 115          Object[] exArgs = { algorithmID,
 116                              ex.getLocalizedMessage() };
 117 
 118          throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
 119       } catch (NoSuchProviderException ex) {
 120         Object[] exArgs = { algorithmID,
 121                                                 ex.getLocalizedMessage() };
 122 
 123         throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
 124         }
 125         instances.get().put(algorithmURI, md);
 126         return md;
 127 }
 128 
 129    /**
 130     * Returns the actual {@link java.security.MessageDigest} algorithm object
 131     *
 132     * @return the actual {@link java.security.MessageDigest} algorithm object
 133     */
 134    public java.security.MessageDigest getAlgorithm() {
 135       return this.algorithm;
 136    }
 137 
 138    /**
 139     * Proxy method for {@link java.security.MessageDigest#isEqual}
 140     * which is executed on the internal {@link java.security.MessageDigest} object.
 141     *
 142     * @param digesta
 143     * @param digestb
 144     * @return the result of the {@link java.security.MessageDigest#isEqual} method
 145     */
 146    public static boolean isEqual(byte[] digesta, byte[] digestb) {
 147       return java.security.MessageDigest.isEqual(digesta, digestb);
 148    }
 149 
 150    /**
 151     * Proxy method for {@link java.security.MessageDigest#digest()}
 152     * which is executed on the internal {@link java.security.MessageDigest} object.
 153     *
 154     * @return the result of the {@link java.security.MessageDigest#digest()} method
 155     */
 156    public byte[] digest() {
 157       return this.algorithm.digest();
 158    }
 159 
 160    /**
 161     * Proxy method for {@link java.security.MessageDigest#digest(byte[])}
 162     * which is executed on the internal {@link java.security.MessageDigest} object.
 163     *
 164     * @param input
 165     * @return the result of the {@link java.security.MessageDigest#digest(byte[])} method
 166     */
 167    public byte[] digest(byte input[]) {
 168       return this.algorithm.digest(input);
 169    }
 170 
 171    /**
 172     * Proxy method for {@link java.security.MessageDigest#digest(byte[], int, int)}
 173     * which is executed on the internal {@link java.security.MessageDigest} object.
 174     *
 175     * @param buf
 176     * @param offset
 177     * @param len
 178     * @return the result of the {@link java.security.MessageDigest#digest(byte[], int, int)} method
 179     * @throws java.security.DigestException
 180     */
 181    public int digest(byte buf[], int offset, int len)
 182            throws java.security.DigestException {
 183       return this.algorithm.digest(buf, offset, len);
 184    }
 185 
 186    /**
 187     * Proxy method for {@link java.security.MessageDigest#getAlgorithm}
 188     * which is executed on the internal {@link java.security.MessageDigest} object.
 189     *
 190     * @return the result of the {@link java.security.MessageDigest#getAlgorithm} method
 191     */
 192    public String getJCEAlgorithmString() {
 193       return this.algorithm.getAlgorithm();
 194    }
 195 
 196    /**
 197     * Proxy method for {@link java.security.MessageDigest#getProvider}
 198     * which is executed on the internal {@link java.security.MessageDigest} object.
 199     *
 200     * @return the result of the {@link java.security.MessageDigest#getProvider} method
 201     */
 202    public java.security.Provider getJCEProvider() {
 203       return this.algorithm.getProvider();
 204    }
 205 
 206    /**
 207     * Proxy method for {@link java.security.MessageDigest#getDigestLength}
 208     * which is executed on the internal {@link java.security.MessageDigest} object.
 209     *
 210     * @return the result of the {@link java.security.MessageDigest#getDigestLength} method
 211     */
 212    public int getDigestLength() {
 213       return this.algorithm.getDigestLength();
 214    }
 215 
 216    /**
 217     * Proxy method for {@link java.security.MessageDigest#reset}
 218     * which is executed on the internal {@link java.security.MessageDigest} object.
 219     *
 220     */
 221    public void reset() {
 222       this.algorithm.reset();
 223    }
 224 
 225    /**
 226     * Proxy method for {@link java.security.MessageDigest#update(byte[])}
 227     * which is executed on the internal {@link java.security.MessageDigest} object.
 228     *
 229     * @param input
 230     */
 231    public void update(byte[] input) {
 232       this.algorithm.update(input);
 233    }
 234 
 235    /**
 236     * Proxy method for {@link java.security.MessageDigest#update(byte)}
 237     * which is executed on the internal {@link java.security.MessageDigest} object.
 238     *
 239     * @param input
 240     */
 241    public void update(byte input) {
 242       this.algorithm.update(input);
 243    }
 244 
 245    /**
 246     * Proxy method for {@link java.security.MessageDigest#update(byte[], int, int)}
 247     * which is executed on the internal {@link java.security.MessageDigest} object.
 248     *
 249     * @param buf
 250     * @param offset
 251     * @param len
 252     */
 253    public void update(byte buf[], int offset, int len) {
 254       this.algorithm.update(buf, offset, len);
 255    }
 256 
 257    /** @inheritDoc */
 258    public String getBaseNamespace() {
 259       return Constants.SignatureSpecNS;
 260    }
 261 
 262    /** @inheritDoc */
 263    public String getBaseLocalName() {
 264       return Constants._TAG_DIGESTMETHOD;
 265    }
 266 }