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 }