1   /* $RCSfile: DESede2KeySecretKeyImpl.java,v $
2    * $Revision: 1.3 $
3    * $Date: 2002/11/23 11:09:56 $
4    * $Author: uwe_guenther $
5    * $State: Exp $
6    *
7    * Created on August 13, 2001 9:35 AM
8    *
9    * Copyright (C) 2001 Uwe Guenther <uwe@cscc.de>
10   *
11   * This file is part of the jhbci JCE-ServiceProvider. The jhbci JCE-
12   * ServiceProvider is a library, written in JavaTM, that should be 
13   * used in HBCI banking applications (clients and may be servers),
14   * to do cryptographic operations.
15   *
16   * The jhbci library is free software; you can redistribute it and/or
17   * modify it under the terms of the GNU Lesser General Public
18   * License as published by the Free Software Foundation; either
19   * version 2.1 of the License, or (at your option) any later version.
20   *
21   * The jhbci library is distributed in the hope that it will be useful,
22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24   * Lesser General Public License for more details.
25   *
26   * You should have received a copy of the GNU Lesser General Public
27   * License along with this library; if not, write to the Free Software
28   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29   *
30   */
31  
32  package de.cscc.crypto.provider;
33  
34  import java.io.IOException;
35  import java.io.InvalidObjectException;
36  import java.io.ObjectInputStream;
37  import java.io.ObjectOutputStream;
38  import java.security.InvalidKeyException;
39  
40  import javax.crypto.SecretKey;
41  
42  import de.cscc.crypto.provider.spec.DESede2KeySpec;
43  
44  /** DESede2KeySecretKeyImpl Class.
45   *
46   * @author  <a href=mailto:uwe@cscc.de>Uwe G&uuml;nther</a>
47   * @version $Revision: 1.3 $
48   */
49  final class DESede2KeySecretKeyImpl implements SecretKey, Cloneable {
50      
51      /**
52       * The class fingerprint that is set to indicate 
53       * serialization compatibility with a previous and
54       * future versions of the class.
55       */
56      private static final long serialVersionUID = 7202413106463874889L;
57      
58      /** The internal key representation as DESede2KeySpec. */    
59      private transient DESede2KeySpec key;
60  
61      /**
62       * Creates a new DESede2KeySecretKeyImpl from a byte array. If the array is 
63       * shorter than 16 bytes it will be filled with 0x00 on the left side until
64       * it is 16 bytes long.
65       *
66       * <p> This Constructor will be used while RSA Key Unwrapping.
67       *
68       * @param key the byte array with the binary DESede2Key.
69       * @throws NullPointerException if key is null.
70       * @throws InvalidKeyException if the given key is weak or semi weak.
71       */
72      DESede2KeySecretKeyImpl(byte[] key) throws InvalidKeyException {
73          if (key == null) {
74              throw new NullPointerException("Prameter key is null.");
75          }
76          byte[] filledKey;
77          if (key.length < 16) {  //align to the right side
78              filledKey = new byte[16];
79              System.arraycopy(key, 0, filledKey, 
80              filledKey.length - key.length, key.length);
81          } else {              //there are nothing to align
82              filledKey = key;
83          }
84          //throws InvalidKeyException
85          this.key = new DESede2KeySpec(filledKey);
86      }
87      
88      /** 
89       * Creates new DESede2KeySecretKeyImpl from a DESede2KeySpec.
90       *
91       * @param key the key.
92       */
93      DESede2KeySecretKeyImpl(DESede2KeySpec key) {
94          if (key == null) {
95              throw new NullPointerException("Prameter key is null.");
96          }        
97          this.key = new DESede2KeySpec(key);
98      }
99      
100     /** 
101      * Creates and returns a deep copy of this object.
102      *
103      * @return a clone of this instance.
104      * @see java.lang.Cloneable
105      * @exception CloneNotSupportedException if the object's class does not
106      *             support the <code>Cloneable</code> interface. Subclasses
107      *             that override the <code>clone</code> method can also
108      *             throw this exception to indicate that an instance cannot
109      *             be cloned.
110      */            
111     public Object clone() throws CloneNotSupportedException {
112         DESede2KeySecretKeyImpl result = (DESede2KeySecretKeyImpl) super.clone();
113         result.key = (DESede2KeySpec) this.key.clone();
114         return result;
115     }
116 
117     /** 
118      * Indicates whether some other object is "equal to" this one.
119      *
120      * @param   obj   the reference object with which to compare.
121      * @return  <code>true</code> if this object is the same as the obj
122      *         argument; <code>false</code> otherwise.
123      * @see     #hashCode()
124      * @see     java.util.Hashtable
125      */        
126     public boolean equals(Object obj) {
127         //Only for performance.
128         if (this == obj) {
129             return true;
130         } 
131         
132         //If obj == null then instanceof returns false, see JLS 15.20.2           
133         if (!(obj instanceof DESede2KeySecretKeyImpl)) {            
134             return false;
135         }
136         
137         DESede2KeySecretKeyImpl temp = (DESede2KeySecretKeyImpl)obj;
138         return this.key.equals(temp.key);
139     }
140 
141     /**
142      * Returns a hash code value for the object. This method is
143      * supported for the benefit of hashtables such as those provided by
144      * <code>java.util.Hashtable</code>.
145      *
146      * @return  a hash code value for this object.
147      * @see     #equals(java.lang.Object)
148      * @see     java.util.Hashtable
149      */    
150     public int hashCode() {
151         int result = 17;
152         result = 37*result + this.key.hashCode();
153         return result;
154     }
155 
156     /**
157      * Returns a string representation of the object. 
158      *
159      * @return  a string representation of the object.
160      */         
161     public String toString() {
162         return this.key.toString();
163     }
164     
165     /**
166      * Write key as <tt>byte[16]</tt> object stream for serialization.
167      *
168      * @param s the ObjectOutputStream.
169      * @throws IOException if there is something wrong with the
170      * ObjectOutputStream.
171      * @serialData First we write the key as <tt>byte[16]</tt>.
172      * @see java.io.ObjectOutputStream
173      */    
174     private void writeObject(ObjectOutputStream s) throws IOException {
175         s.defaultWriteObject();
176         s.writeObject(this.key.getKey());
177     } 
178     
179     /**
180      * Read the key as <tt>byte[16]</tt> object stream for serialization.
181      *
182      * Keep in mind this is a PSEUDOCONSTRUCTOR and you have to set
183      * do devensive copying or use the new readUnshared and secondly
184      * you have to check all invariants.
185      *
186      * @param s the ObjectInputStream.
187      * @throws IOException if there is something wrong with the 
188      * ObjectInputStream.
189      * @throws ClassNotFoundException if the class can not be found.
190      * @throws InvalidObjectException if one or more deserialized objects 
191      * failed validation tests.
192      * @see java.io.ObjectInputStream
193      */    
194     private void readObject(ObjectInputStream s) 
195             throws IOException, ClassNotFoundException {
196             s.defaultReadObject();
197             byte[] keyAsByteArray = (byte[]) s.readUnshared();
198             try {
199                 //The devensive copying and invariant check will
200                 //do the DESede2KeySpec(byte[]) constructor.
201                 this.key = new DESede2KeySpec(keyAsByteArray);
202             } catch (InvalidKeyException e) {
203                 //Convert the checked Exception in a unchecked Exception.
204                 throw (InvalidObjectException) 
205                 new InvalidObjectException(e.toString()).initCause(e);
206             }
207     }            
208         
209     
210     /**
211      * Returns the algorithm name for the algorithm this SecretKey is working.
212      *
213      * @return "DESede2Key".
214      */    
215     public String getAlgorithm() {
216         return "DESede2Key";
217     }
218     
219     /**
220      * Returns the key in its primary encoding format
221      * ("RAW" in our case as byte[16] array).
222      *
223      * @return the key as "RAW" byte[16] array.
224      */    
225     public byte[] getEncoded() {
226         return this.key.getKey();    
227     }
228     
229     /**
230      * Returns the primary encoding format
231      * ("RAW" in our case).
232      *
233      * @return "RAW".
234      */    
235     public String getFormat() {
236         return "RAW";
237     }
238 }
239