1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18/** 19* @author Alexander Y. Kleymenov 20* @version $Revision$ 21*/ 22 23package javax.crypto.spec; 24 25import java.io.Serializable; 26import java.security.spec.KeySpec; 27import java.util.Arrays; 28import javax.crypto.SecretKey; 29 30/** 31 * A key specification for a <code>SecretKey</code> and also a secret key 32 * implementation that is provider-independent. It can be used for raw secret 33 * keys that can be specified as <code>byte[]</code>. 34 */ 35public class SecretKeySpec implements SecretKey, KeySpec, Serializable { 36 37 // The 5.0 spec. doesn't declare this serialVersionUID field 38 // In order to be compatible it is explicitly declared here 39 // for details see HARMONY-233 40 private static final long serialVersionUID = 6577238317307289933L; 41 42 private final byte[] key; 43 private final String algorithm; 44 45 /** 46 * Creates a new <code>SecretKeySpec</code> for the specified key data and 47 * algorithm name. 48 * 49 * @param key 50 * the key data. 51 * @param algorithm 52 * the algorithm name. 53 * @throws IllegalArgumentException 54 * if the key data or the algorithm name is null or if the key 55 * data is empty. 56 */ 57 public SecretKeySpec(byte[] key, String algorithm) { 58 if (key == null) { 59 throw new IllegalArgumentException("key == null"); 60 } 61 if (key.length == 0) { 62 throw new IllegalArgumentException("key.length == 0"); 63 } 64 if (algorithm == null) { 65 throw new IllegalArgumentException("algorithm == null"); 66 } 67 68 this.algorithm = algorithm; 69 this.key = new byte[key.length]; 70 System.arraycopy(key, 0, this.key, 0, key.length); 71 } 72 73 /** 74 * Creates a new <code>SecretKeySpec</code> for the key data from the 75 * specified buffer <code>key</code> starting at <code>offset</code> with 76 * length <code>len</code> and the specified <code>algorithm</code> name. 77 * 78 * @param key 79 * the key data. 80 * @param offset 81 * the offset. 82 * @param len 83 * the size of the key data. 84 * @param algorithm 85 * the algorithm name. 86 * @throws IllegalArgumentException 87 * if the key data or the algorithm name is null, the key data 88 * is empty or <code>offset</code> and <code>len</code> do not 89 * specify a valid chunk in the buffer <code>key</code>. 90 * @throws ArrayIndexOutOfBoundsException 91 * if <code>offset</code> or <code>len</code> is negative. 92 */ 93 public SecretKeySpec(byte[] key, int offset, int len, String algorithm) { 94 if (key == null) { 95 throw new IllegalArgumentException("key == null"); 96 } 97 if (key.length == 0) { 98 throw new IllegalArgumentException("key.length == 0"); 99 } 100 if (len < 0 || offset < 0) { 101 throw new ArrayIndexOutOfBoundsException("len < 0 || offset < 0"); 102 } 103 if (key.length - offset < len) { 104 throw new IllegalArgumentException("key too short"); 105 } 106 if (algorithm == null) { 107 throw new IllegalArgumentException("algorithm == null"); 108 } 109 this.algorithm = algorithm; 110 this.key = new byte[len]; 111 System.arraycopy(key, offset, this.key, 0, len); 112 } 113 114 /** 115 * Returns the algorithm name. 116 * 117 * @return the algorithm name. 118 */ 119 public String getAlgorithm() { 120 return algorithm; 121 } 122 123 /** 124 * Returns the name of the format used to encode the key. 125 * 126 * @return the format name "RAW". 127 */ 128 public String getFormat() { 129 return "RAW"; 130 } 131 132 /** 133 * Returns the encoded form of this secret key. 134 * 135 * @return the encoded form of this secret key. 136 */ 137 public byte[] getEncoded() { 138 byte[] result = new byte[key.length]; 139 System.arraycopy(key, 0, result, 0, key.length); 140 return result; 141 } 142 143 /** 144 * Returns the hash code of this <code>SecretKeySpec</code> object. 145 * 146 * @return the hash code. 147 */ 148 @Override 149 public int hashCode() { 150 int result = algorithm.length(); 151 for (byte element : key) { 152 result += element; 153 } 154 return result; 155 } 156 157 /** 158 * Compares the specified object with this <code>SecretKeySpec</code> 159 * instance. 160 * 161 * @param obj 162 * the object to compare. 163 * @return true if the algorithm name and key of both object are equal, 164 * otherwise false. 165 */ 166 @Override 167 public boolean equals(Object obj) { 168 if (obj == this) { 169 return true; 170 } 171 if (!(obj instanceof SecretKeySpec)) { 172 return false; 173 } 174 SecretKeySpec ks = (SecretKeySpec) obj; 175 return (algorithm.equalsIgnoreCase(ks.algorithm)) 176 && (Arrays.equals(key, ks.key)); 177 } 178} 179