KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snmp4j > security > PrivDES


1 /*_############################################################################
2   _##
3   _## SNMP4J - PrivDES.java
4   _##
5   _## Copyright 2003-2007 Frank Fock and Jochen Katz (SNMP4J.org)
6   _##
7   _## Licensed under the Apache License, Version 2.0 (the "License");
8   _## you may not use this file except in compliance with the License.
9   _## You may obtain a copy of the License at
10   _##
11   _## http://www.apache.org/licenses/LICENSE-2.0
12   _##
13   _## Unless required by applicable law or agreed to in writing, software
14   _## distributed under the License is distributed on an "AS IS" BASIS,
15   _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   _## See the License for the specific language governing permissions and
17   _## limitations under the License.
18   _##
19   _##########################################################################*/

20
21 package org.snmp4j.security;
22
23 import org.snmp4j.smi.OID;
24 import org.snmp4j.log.*;
25 import javax.crypto.spec.SecretKeySpec;
26 import javax.crypto.spec.IvParameterSpec;
27 import javax.crypto.Cipher;
28
29 /**
30  * Privacy protocol class for DES.
31  *
32  * This class uses DES in CBC mode to encrypt the data. The protocol
33  * is defined in the IETF standard "User-based Security Model (USM)
34  * for SNMPv3".
35  *
36  * @author Jochen Katz
37  * @version 1.2
38  */

39 public class PrivDES
40     implements PrivacyProtocol {
41
42   private static final long serialVersionUID = 2526070176429255416L;
43
44   /**
45    * Unique ID of this privacy protocol.
46    */

47   public static final OID ID = new OID("1.3.6.1.6.3.10.1.2.2");
48
49   private static final int DECRYPT_PARAMS_LENGTH = 8;
50   protected Salt salt;
51
52   private static final LogAdapter logger = LogFactory.getLogger(PrivDES.class);
53
54   public PrivDES()
55   {
56     this.salt = Salt.getInstance();
57   }
58
59   public byte[] encrypt(byte[] unencryptedData,
60                         int offset,
61                         int length,
62                         byte[] encryptionKey,
63                         long engineBoots,
64                         long engineTime,
65                         DecryptParams decryptParams) {
66     int mySalt = (int)salt.getNext();
67
68     if (encryptionKey.length < 16) {
69       logger.error("Wrong Key length: need at least 16 bytes, is " +
70                    encryptionKey.length +
71                    " bytes.");
72       throw new IllegalArgumentException JavaDoc("encryptionKey has illegal length "
73                                          + encryptionKey.length
74                                          + " (should be at least 16).");
75     }
76
77     if ( (decryptParams.array == null) || (decryptParams.length < 8)) {
78       decryptParams.array = new byte[8];
79     }
80     decryptParams.length = 8;
81     decryptParams.offset = 0;
82
83     // put salt in decryption_params (sent as priv params)
84
if (logger.isDebugEnabled()) {
85       logger.debug("Preparing decrypt_params.");
86     }
87     for (int i = 0; i < 4; ++i) {
88       decryptParams.array[3 - i] = (byte) (0xFF & (engineBoots >> (8 * i)));
89       decryptParams.array[7 - i] = (byte) (0xFF & (mySalt >> (8 * i)));
90     }
91
92     byte[] iv = new byte[8];
93
94     // last eight bytes of key xored with decrypt params are used as iv
95
if (logger.isDebugEnabled()) {
96       logger.debug("Preparing iv for encryption.");
97     }
98     for (int i = 0; i < 8; ++i) {
99       iv[i] = (byte) (encryptionKey[8 + i] ^ decryptParams.array[i]);
100     }
101
102     byte[] encryptedData = null;
103
104     try {
105       // now do CBC encryption of the plaintext
106
Cipher alg = Cipher.getInstance("DES/CBC/NoPadding");
107       SecretKeySpec key =
108           new SecretKeySpec(encryptionKey, 0, 8, "DES");
109       IvParameterSpec ivSpec = new IvParameterSpec(iv);
110       alg.init(Cipher.ENCRYPT_MODE, key, ivSpec);
111
112       // allocate space for encrypted text
113
if (length % 8 == 0) {
114         encryptedData = alg.doFinal(unencryptedData, offset, length);
115       }
116       else {
117         if (logger.isDebugEnabled()) {
118           logger.debug("Using padding.");
119         }
120
121         encryptedData = new byte[8 * ( (length / 8) + 1)];
122         byte[] tmp = new byte[8];
123
124         int encryptedLength = alg.update(unencryptedData, offset, length,
125                                          encryptedData);
126         encryptedLength += alg.doFinal(tmp, 0, 8 - (length % 8),
127                                        encryptedData, encryptedLength);
128       }
129     }
130     catch (Exception JavaDoc e) {
131       logger.error(e);
132       if (logger.isDebugEnabled()) {
133         e.printStackTrace();
134       }
135     }
136
137     if (logger.isDebugEnabled()) {
138       logger.debug("Encryption finished.");
139     }
140     return encryptedData;
141   }
142
143   /**
144    * Decrypts a message using a given decryption key, engine boots count, and
145    * engine ID.
146    *
147    * @param cryptedData
148    * @param offset
149    * @param length
150    * @param decryptionKey
151    * @param engineBoots
152    * @param engineTime
153    * @return
154    * the decrypted data, or <code>null</code> if decryption failed.
155    */

156   public byte[] decrypt(byte[] cryptedData,
157                         int offset,
158                         int length,
159                         byte[] decryptionKey,
160                         long engineBoots,
161                         long engineTime,
162                         DecryptParams decryptParams) {
163     if ( (length % 8 != 0) ||
164         (length < 8) ||
165         (decryptParams.length != 8)) {
166       throw new IllegalArgumentException JavaDoc("Length (" + length +
167                                          ")is not multiple of 8 or decrypt params has not length 8 ("
168                                          + decryptParams.length + ").");
169     }
170     if (decryptionKey.length < 16) {
171       logger.error("Wrong Key length: need at least 16 bytes, is " +
172                    decryptionKey.length +
173                    " bytes.");
174       throw new IllegalArgumentException JavaDoc("decryptionKey has illegal length "
175                                          + decryptionKey.length
176                                          + " (should be at least 16).");
177     }
178
179     byte[] iv = new byte[8];
180
181     // last eight bytes of key xored with decrypt params are used as iv
182
for (int i = 0; i < 8; ++i) {
183       iv[i] = (byte) (decryptionKey[8 + i] ^ decryptParams.array[i]);
184     }
185
186     byte[] decryptedData = null;
187     try {
188       // now do CBC decryption of the crypted data
189
Cipher alg = Cipher.getInstance("DES/CBC/NoPadding");
190       SecretKeySpec key =
191           new SecretKeySpec(decryptionKey, 0, 8, "DES");
192       IvParameterSpec ivSpec = new IvParameterSpec(iv);
193       alg.init(Cipher.DECRYPT_MODE, key, ivSpec);
194       decryptedData = alg.doFinal(cryptedData, offset, length);
195     }
196     catch (Exception JavaDoc e) {
197       logger.error(e);
198       if (logger.isDebugEnabled()) {
199         e.printStackTrace();
200       }
201     }
202
203     return decryptedData;
204   }
205
206   /**
207    * Gets the OID uniquely identifying the privacy protocol.
208    * @return
209    * an <code>OID</code> instance.
210    */

211   public OID getID() {
212     return (OID) ID.clone();
213   }
214
215   public int getEncryptedLength(int scopedPDULength) {
216     if (scopedPDULength % 8 == 0) {
217       return scopedPDULength;
218     }
219     return 8 * ( (scopedPDULength / 8) + 1);
220   }
221
222   public int getMinKeyLength() {
223     return 16;
224   }
225
226   public int getDecryptParamsLength() {
227     return DECRYPT_PARAMS_LENGTH;
228   }
229
230   public int getMaxKeyLength() {
231     return getMinKeyLength();
232   }
233
234 }
235
Popular Tags