1   /* $RCSfile: DESede3KeySecretKeyImpl.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.DESede3KeySpec;
43  
44  /** 
45   * DESede3KeySecretKeyImpl Class.
46   *
47   * @author  <a href=mailto:uwe@cscc.de>Uwe G&uuml;nther</a>
48   * @version $Revision: 1.3 $
49   */
50  final class DESede3KeySecretKeyImpl implements SecretKey, Cloneable {
51  
52      /**
53       * The class fingerprint that is set to indicate 
54       * serialization compatibility with a previous and
55       * future versions of the class.
56       */
57      private static final long serialVersionUID = 2940543898161466805L;
58      
59      /** The internal key representation as DESede3KeySpec. */    
60      private transient DESede3KeySpec key;
61  
62      /**
63       * Creates a new DESede3KeySecretKeyImpl from a byte array. If the array is 
64       * shorter than 24 bytes it will be filled with 0x00 on the left side until
65       * it is 24 bytes long.
66       *
67       * <p> This Constructor will be used while RSA Key Unwrapping.
68       *
69       * @param key the byte array with the binary DESede3Key.
70       * @throws NullPointerException if key is null.
71       * @throws InvalidKeyException if the given key is weak or semi weak.
72       */
73      DESede3KeySecretKeyImpl(byte[] key) throws InvalidKeyException {
74          if (key == null) {
75              throw new NullPointerException("Prameter key is null.");
76          }
77          byte[] filledKey;
78          if (key.length < 24) {  //align to the right side
79              filledKey = new byte[24];
80              System.arraycopy(key, 0, filledKey, 
81              filledKey.length - key.length, key.length);
82          } else {              //there are nothing to align
83              filledKey = key;
84          }
85          //throws InvalidKeyException
86          this.key = new DESede3KeySpec(filledKey);
87      }    
88      
89      /** 
90       * Creates new DESede3KeySecretKeyImpl from a DESede3KeySpec.
91       * @param key the key.
92       */
93      DESede3KeySecretKeyImpl(DESede3KeySpec key) {
94          this.key = new DESede3KeySpec(key);
95      }
96  
97      /**
98       * Creates and returns a deep copy of this object.
99       *
100      * @return a clone of this instance.
101      * @see java.lang.Cloneable
102      * @exception CloneNotSupportedException if the object's class does not
103      *             support the <code>Cloneable</code> interface. Subclasses
104      *             that override the <code>clone</code> method can also
105      *             throw this exception to indicate that an instance cannot
106      *             be cloned.
107      */            
108     public Object clone() throws CloneNotSupportedException {
109         DESede3KeySecretKeyImpl result = (DESede3KeySecretKeyImpl) super.clone();
110         result.key = (DESede3KeySpec) this.key.clone();
111         return result;
112     }
113 
114     /** 
115      * Indicates whether some other object is "equal to" this one.
116      *
117      * @param   obj   the reference object with which to compare.
118      * @return  <code>true</code> if this object is the same as the obj
119      *         argument; <code>false</code> otherwise.
120      * @see     #hashCode()
121      * @see     java.util.Hashtable
122      */        
123     public boolean equals(Object obj) {
124         //Only for performance.
125         if (this == obj) {
126             return true;
127         } 
128         
129         //If obj == null then instanceof returns false, see JLS 15.20.2      
130         if (!(obj instanceof DESede3KeySecretKeyImpl)) {
131             return false;
132         }
133         
134         DESede3KeySecretKeyImpl temp = (DESede3KeySecretKeyImpl)obj;
135         return this.key.equals(temp.key);
136     }
137 
138     /**
139      * Returns a hash code value for the object. This method is
140      * supported for the benefit of hashtables such as those provided by
141      * <code>java.util.Hashtable</code>.
142      *
143      * @return  a hash code value for this object.
144      * @see     #equals(java.lang.Object)
145      * @see     java.util.Hashtable
146      */    
147     public int hashCode() {
148         int result = 17;
149         result = 37*result + this.key.hashCode();
150         return result;
151     }
152 
153     /**
154      * Returns a string representation of the object. 
155      *
156      * @return  a string representation of the object.
157      */         
158     public String toString() {
159         return this.key.toString();
160     }
161     
162     /**
163      * Write key as <tt>byte[24]</tt> object stream for serialization.
164      *
165      * @param s the ObjectOutputStream.
166      * @throws IOException if there is something wrong with the
167      * ObjectOutputStream.
168      * @serialData First we write the key as <tt>byte[24]</tt>.
169      * @see java.io.ObjectOutputStream
170      */    
171     private void writeObject(ObjectOutputStream s) throws IOException {
172         s.defaultWriteObject();
173         s.writeObject(this.key.getKey());
174     } 
175     
176     /**
177      * Read the key as <tt>byte[24]</tt> object stream for serialization.
178      *
179      * Keep in mind this is a PSEUDOCONSTRUCTOR and you have to set
180      * do devensive copying or use the new readUnshared and secondly
181      * you have to check all invariants.
182      *
183      * @param s the ObjectInputStream.
184      * @throws IOException if there is something wrong with the 
185      * ObjectInputStream.
186      * @throws ClassNotFoundException if the class can not be found.
187      * @throws InvalidObjectException if one or more deserialized objects 
188      * failed validation tests.
189      * @see java.io.ObjectInputStream
190      */    
191     private void readObject(ObjectInputStream s) 
192             throws IOException, ClassNotFoundException {
193             s.defaultReadObject();
194             byte[] keyAsByteArray = (byte[]) s.readUnshared();
195             try {
196                 //The devensive copying and invariant check will
197                 //do the DESede2KeySpec(byte[]) constructor.
198                 this.key = new DESede3KeySpec(keyAsByteArray);
199             } catch (InvalidKeyException e) {
200                 //Convert the checked Exception in a unchecked Exception.
201                 throw (InvalidObjectException) 
202                 new InvalidObjectException(e.toString()).initCause(e);
203             }
204     }            
205             
206     /**
207      * Returns the algorithm name for the algorithm this SecretKey is working.
208      *
209      * @return "DESede3Key".
210      */    
211     public String getAlgorithm() {
212         return "DESede3Key";
213     }
214         
215     /**
216      * Returns the key in its primary encoding format
217      * ("RAW" in our case as byte[24] array).
218      *
219      * @return the key as "RAW" byte[24] array.
220      */    
221     public byte[] getEncoded() {
222         return this.key.getKey();    
223     }
224     
225     /**
226      * Returns the primary encoding format
227      * ("RAW" in our case).
228      *
229      * @return "RAW".
230      */    
231     public String getFormat() {
232         return "RAW";
233     }
234 }
235