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