1 /* 2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.security; 27 28 import java.io.*; 29 import java.security.spec.AlgorithmParameterSpec; 30 import java.security.spec.InvalidParameterSpecException; 31 import java.util.Objects; 32 33 /** 34 * This class is used as an opaque representation of cryptographic parameters. 35 * 36 * <p>An {@code AlgorithmParameters} object for managing the parameters 37 * for a particular algorithm can be obtained by 38 * calling one of the {@code getInstance} factory methods 39 * (static methods that return instances of a given class). 40 * 41 * <p>Once an {@code AlgorithmParameters} object is obtained, it must be 42 * initialized via a call to {@code init}, using an appropriate parameter 43 * specification or parameter encoding. 44 * 45 * <p>A transparent parameter specification is obtained from an 46 * {@code AlgorithmParameters} object via a call to 47 * {@code getParameterSpec}, and a byte encoding of the parameters is 48 * obtained via a call to {@code getEncoded}. 49 * 50 * <p> Every implementation of the Java platform is required to support the 51 * following standard {@code AlgorithmParameters} algorithms: 52 * <ul> 53 * <li>{@code AES}</li> 54 * <li>{@code DESede}</li> 55 * <li>{@code DiffieHellman}</li> 56 * <li>{@code DSA}</li> 57 * </ul> 58 * These algorithms are described in the <a href= 59 * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms"> 60 * AlgorithmParameters section</a> of the 61 * Java Security Standard Algorithm Names Specification. 62 * Consult the release documentation for your implementation to see if any 63 * other algorithms are supported. 64 * 65 * @author Jan Luehe 66 * 67 * 68 * @see java.security.spec.AlgorithmParameterSpec 69 * @see java.security.spec.DSAParameterSpec 70 * @see KeyPairGenerator 71 * 72 * @since 1.2 73 */ 74 75 public class AlgorithmParameters { 76 77 // The provider 78 private Provider provider; 79 80 // The provider implementation (delegate) 81 private AlgorithmParametersSpi paramSpi; 82 83 // The algorithm 84 private String algorithm; 85 86 // Has this object been initialized? 87 private boolean initialized = false; 88 89 /** 90 * Creates an AlgorithmParameters object. 91 * 92 * @param paramSpi the delegate 93 * @param provider the provider 94 * @param algorithm the algorithm 95 */ AlgorithmParameters(AlgorithmParametersSpi paramSpi, Provider provider, String algorithm)96 protected AlgorithmParameters(AlgorithmParametersSpi paramSpi, 97 Provider provider, String algorithm) 98 { 99 this.paramSpi = paramSpi; 100 this.provider = provider; 101 this.algorithm = algorithm; 102 } 103 104 /** 105 * Returns the name of the algorithm associated with this parameter object. 106 * 107 * @return the algorithm name. 108 */ getAlgorithm()109 public final String getAlgorithm() { 110 return this.algorithm; 111 } 112 113 /** 114 * Returns a parameter object for the specified algorithm. 115 * 116 * <p> This method traverses the list of registered security Providers, 117 * starting with the most preferred Provider. 118 * A new AlgorithmParameters object encapsulating the 119 * AlgorithmParametersSpi implementation from the first 120 * Provider that supports the specified algorithm is returned. 121 * 122 * <p> Note that the list of registered providers may be retrieved via 123 * the {@link Security#getProviders() Security.getProviders()} method. 124 * 125 * <p> The returned parameter object must be initialized via a call to 126 * {@code init}, using an appropriate parameter specification or 127 * parameter encoding. 128 * 129 * @implNote 130 * The JDK Reference Implementation additionally uses the 131 * {@code jdk.security.provider.preferred} 132 * {@link Security#getProperty(String) Security} property to determine 133 * the preferred provider order for the specified algorithm. This 134 * may be different than the order of providers returned by 135 * {@link Security#getProviders() Security.getProviders()}. 136 * 137 * @param algorithm the name of the algorithm requested. 138 * See the AlgorithmParameters section in the <a href= 139 * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms"> 140 * Java Security Standard Algorithm Names Specification</a> 141 * for information about standard algorithm names. 142 * 143 * @return the new parameter object 144 * 145 * @throws NoSuchAlgorithmException if no {@code Provider} supports an 146 * {@code AlgorithmParametersSpi} implementation for the 147 * specified algorithm 148 * 149 * @throws NullPointerException if {@code algorithm} is {@code null} 150 * 151 * @see Provider 152 */ getInstance(String algorithm)153 public static AlgorithmParameters getInstance(String algorithm) 154 throws NoSuchAlgorithmException { 155 Objects.requireNonNull(algorithm, "null algorithm name"); 156 try { 157 Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters", 158 (String)null); 159 return new AlgorithmParameters((AlgorithmParametersSpi)objs[0], 160 (Provider)objs[1], 161 algorithm); 162 } catch(NoSuchProviderException e) { 163 throw new NoSuchAlgorithmException(algorithm + " not found"); 164 } 165 } 166 167 /** 168 * Returns a parameter object for the specified algorithm. 169 * 170 * <p> A new AlgorithmParameters object encapsulating the 171 * AlgorithmParametersSpi implementation from the specified provider 172 * is returned. The specified provider must be registered 173 * in the security provider list. 174 * 175 * <p> Note that the list of registered providers may be retrieved via 176 * the {@link Security#getProviders() Security.getProviders()} method. 177 * 178 * <p>The returned parameter object must be initialized via a call to 179 * {@code init}, using an appropriate parameter specification or 180 * parameter encoding. 181 * 182 * @param algorithm the name of the algorithm requested. 183 * See the AlgorithmParameters section in the <a href= 184 * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms"> 185 * Java Security Standard Algorithm Names Specification</a> 186 * for information about standard algorithm names. 187 * 188 * @param provider the name of the provider. 189 * 190 * @return the new parameter object 191 * 192 * @throws IllegalArgumentException if the provider name is {@code null} 193 * or empty 194 * 195 * @throws NoSuchAlgorithmException if an {@code AlgorithmParametersSpi} 196 * implementation for the specified algorithm is not 197 * available from the specified provider 198 * 199 * @throws NoSuchProviderException if the specified provider is not 200 * registered in the security provider list 201 * 202 * @throws NullPointerException if {@code algorithm} is {@code null} 203 * 204 * @see Provider 205 */ getInstance(String algorithm, String provider)206 public static AlgorithmParameters getInstance(String algorithm, 207 String provider) 208 throws NoSuchAlgorithmException, NoSuchProviderException 209 { 210 Objects.requireNonNull(algorithm, "null algorithm name"); 211 if (provider == null || provider.isEmpty()) 212 throw new IllegalArgumentException("missing provider"); 213 Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters", 214 provider); 215 return new AlgorithmParameters((AlgorithmParametersSpi)objs[0], 216 (Provider)objs[1], 217 algorithm); 218 } 219 220 /** 221 * Returns a parameter object for the specified algorithm. 222 * 223 * <p> A new AlgorithmParameters object encapsulating the 224 * AlgorithmParametersSpi implementation from the specified Provider 225 * object is returned. Note that the specified Provider object 226 * does not have to be registered in the provider list. 227 * 228 * <p>The returned parameter object must be initialized via a call to 229 * {@code init}, using an appropriate parameter specification or 230 * parameter encoding. 231 * 232 * @param algorithm the name of the algorithm requested. 233 * See the AlgorithmParameters section in the <a href= 234 * "{@docRoot}/../specs/security/standard-names.html#algorithmparameters-algorithms"> 235 * Java Security Standard Algorithm Names Specification</a> 236 * for information about standard algorithm names. 237 * 238 * @param provider the name of the provider. 239 * 240 * @return the new parameter object 241 * 242 * @throws IllegalArgumentException if the provider is {@code null} 243 * 244 * @throws NoSuchAlgorithmException if an 245 * {@code AlgorithmParameterGeneratorSpi} 246 * implementation for the specified algorithm is not available 247 * from the specified {@code Provider} object 248 * 249 * @throws NullPointerException if {@code algorithm} is {@code null} 250 * 251 * @see Provider 252 * 253 * @since 1.4 254 */ getInstance(String algorithm, Provider provider)255 public static AlgorithmParameters getInstance(String algorithm, 256 Provider provider) 257 throws NoSuchAlgorithmException 258 { 259 Objects.requireNonNull(algorithm, "null algorithm name"); 260 if (provider == null) 261 throw new IllegalArgumentException("missing provider"); 262 Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters", 263 provider); 264 return new AlgorithmParameters((AlgorithmParametersSpi)objs[0], 265 (Provider)objs[1], 266 algorithm); 267 } 268 269 /** 270 * Returns the provider of this parameter object. 271 * 272 * @return the provider of this parameter object 273 */ getProvider()274 public final Provider getProvider() { 275 return this.provider; 276 } 277 278 /** 279 * Initializes this parameter object using the parameters 280 * specified in {@code paramSpec}. 281 * 282 * @param paramSpec the parameter specification. 283 * 284 * @throws InvalidParameterSpecException if the given parameter 285 * specification is inappropriate for the initialization of this parameter 286 * object, or if this parameter object has already been initialized. 287 */ init(AlgorithmParameterSpec paramSpec)288 public final void init(AlgorithmParameterSpec paramSpec) 289 throws InvalidParameterSpecException 290 { 291 if (this.initialized) 292 throw new InvalidParameterSpecException("already initialized"); 293 paramSpi.engineInit(paramSpec); 294 this.initialized = true; 295 } 296 297 /** 298 * Imports the specified parameters and decodes them according to the 299 * primary decoding format for parameters. The primary decoding 300 * format for parameters is ASN.1, if an ASN.1 specification for this type 301 * of parameters exists. 302 * 303 * @param params the encoded parameters. 304 * 305 * @throws IOException on decoding errors, or if this parameter object 306 * has already been initialized. 307 */ init(byte[] params)308 public final void init(byte[] params) throws IOException { 309 if (this.initialized) 310 throw new IOException("already initialized"); 311 paramSpi.engineInit(params); 312 this.initialized = true; 313 } 314 315 /** 316 * Imports the parameters from {@code params} and decodes them 317 * according to the specified decoding scheme. 318 * If {@code format} is null, the 319 * primary decoding format for parameters is used. The primary decoding 320 * format is ASN.1, if an ASN.1 specification for these parameters 321 * exists. 322 * 323 * @param params the encoded parameters. 324 * 325 * @param format the name of the decoding scheme. 326 * 327 * @throws IOException on decoding errors, or if this parameter object 328 * has already been initialized. 329 */ init(byte[] params, String format)330 public final void init(byte[] params, String format) throws IOException { 331 if (this.initialized) 332 throw new IOException("already initialized"); 333 paramSpi.engineInit(params, format); 334 this.initialized = true; 335 } 336 337 /** 338 * Returns a (transparent) specification of this parameter object. 339 * {@code paramSpec} identifies the specification class in which 340 * the parameters should be returned. It could, for example, be 341 * {@code DSAParameterSpec.class}, to indicate that the 342 * parameters should be returned in an instance of the 343 * {@code DSAParameterSpec} class. 344 * 345 * @param <T> the type of the parameter specification to be returrned 346 * @param paramSpec the specification class in which 347 * the parameters should be returned. 348 * 349 * @return the parameter specification. 350 * 351 * @throws InvalidParameterSpecException if the requested parameter 352 * specification is inappropriate for this parameter object, or if this 353 * parameter object has not been initialized. 354 */ 355 public final <T extends AlgorithmParameterSpec> getParameterSpec(Class<T> paramSpec)356 T getParameterSpec(Class<T> paramSpec) 357 throws InvalidParameterSpecException 358 { 359 if (this.initialized == false) { 360 throw new InvalidParameterSpecException("not initialized"); 361 } 362 return paramSpi.engineGetParameterSpec(paramSpec); 363 } 364 365 /** 366 * Returns the parameters in their primary encoding format. 367 * The primary encoding format for parameters is ASN.1, if an ASN.1 368 * specification for this type of parameters exists. 369 * 370 * @return the parameters encoded using their primary encoding format. 371 * 372 * @throws IOException on encoding errors, or if this parameter object 373 * has not been initialized. 374 */ getEncoded()375 public final byte[] getEncoded() throws IOException 376 { 377 if (this.initialized == false) { 378 throw new IOException("not initialized"); 379 } 380 return paramSpi.engineGetEncoded(); 381 } 382 383 /** 384 * Returns the parameters encoded in the specified scheme. 385 * If {@code format} is null, the 386 * primary encoding format for parameters is used. The primary encoding 387 * format is ASN.1, if an ASN.1 specification for these parameters 388 * exists. 389 * 390 * @param format the name of the encoding format. 391 * 392 * @return the parameters encoded using the specified encoding scheme. 393 * 394 * @throws IOException on encoding errors, or if this parameter object 395 * has not been initialized. 396 */ getEncoded(String format)397 public final byte[] getEncoded(String format) throws IOException 398 { 399 if (this.initialized == false) { 400 throw new IOException("not initialized"); 401 } 402 return paramSpi.engineGetEncoded(format); 403 } 404 405 /** 406 * Returns a formatted string describing the parameters. 407 * 408 * @return a formatted string describing the parameters, or null if this 409 * parameter object has not been initialized. 410 */ toString()411 public final String toString() { 412 if (this.initialized == false) { 413 return null; 414 } 415 return paramSpi.engineToString(); 416 } 417 } 418