KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*_############################################################################
2   _##
3   _## SNMP4J - PrivAES.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
22
23
24
25 package org.snmp4j.security;
26
27 import javax.crypto.*;
28
29 import org.snmp4j.log.*;
30 import javax.crypto.spec.IvParameterSpec;
31 import javax.crypto.spec.SecretKeySpec;
32 import org.snmp4j.smi.OctetString;
33
34
35 /**
36  * Base class for PrivAES128, PrivAES192 and PrivAES256.
37  *
38  * This class uses AES in CFB mode to encrypt the data. The protocol
39  * is defined in draft-blumenthal-aes-usm-08.txt.
40  *
41  * @author Jochen Katz
42  * @version 1.0
43  */

44 public abstract class PrivAES
45     implements PrivacyProtocol {
46
47   private static final int DECRYPT_PARAMS_LENGTH = 8;
48
49   private static final LogAdapter logger = LogFactory.getLogger(PrivAES.class);
50   private int keyBytes;
51   protected Salt salt;
52
53   /**
54    * Constructor.
55    *
56    * @param keyBytes
57    * Length of key, must be 16, 24 or 32.
58    * @throws IllegalArgumentException
59    * if keyBytes is illegal
60    */

61   public PrivAES(int keyBytes) {
62     if ((keyBytes != 16) && (keyBytes != 24) && (keyBytes != 32)) {
63       throw new IllegalArgumentException JavaDoc(
64           "Only 128, 192 and 256 bit AES is allowed. Requested ("
65           + (8 * keyBytes) + ").");
66     }
67     this.keyBytes = keyBytes;
68     this.salt = Salt.getInstance();
69   }
70
71   public byte[] encrypt(byte[] unencryptedData, int offset, int length,
72                         byte[] encryptionKey, long engineBoots,
73                         long engineTime, DecryptParams decryptParams) {
74
75     byte[] initVect = new byte[16];
76     long my_salt = salt.getNext();
77
78     if (encryptionKey.length < keyBytes) {
79       throw new IllegalArgumentException JavaDoc(
80           "Needed key length is " + keyBytes + ". Got only " + encryptionKey.length +
81           ".");
82     }
83
84     if ((decryptParams.array == null) ||
85         (decryptParams.length < DECRYPT_PARAMS_LENGTH)) {
86       decryptParams.array = new byte[DECRYPT_PARAMS_LENGTH];
87     }
88     decryptParams.length = DECRYPT_PARAMS_LENGTH;
89     decryptParams.offset = 0;
90
91     /* Set IV as engine_boots + engine_time + salt */
92     initVect[0] = (byte) ( (engineBoots >> 24) & 0xFF);
93     initVect[1] = (byte) ( (engineBoots >> 16) & 0xFF);
94     initVect[2] = (byte) ( (engineBoots >> 8) & 0xFF);
95     initVect[3] = (byte) ( (engineBoots) & 0xFF);
96     initVect[4] = (byte) ( (engineTime >> 24) & 0xFF);
97     initVect[5] = (byte) ( (engineTime >> 16) & 0xFF);
98     initVect[6] = (byte) ( (engineTime >> 8) & 0xFF);
99     initVect[7] = (byte) ( (engineTime) & 0xFF);
100     for (int i = 56, j = 8; i >= 0; i -= 8, j++) {
101       initVect[j] = (byte) ( (my_salt >> i) & 0xFF);
102     }
103     for (int i = 0; i < 8; i++) {
104       decryptParams.array[i] = initVect[i + 8];
105     }
106     if (logger.isDebugEnabled()) {
107       logger.debug("initVect is " + asHex(initVect));
108     }
109
110     // allocate space for encrypted text
111
byte[] encryptedData = null;
112     try {
113       // now do CFB encryption of the plaintext
114
Cipher alg = Cipher.getInstance("AES/CFB/NoPadding");
115       SecretKeySpec key =
116           new SecretKeySpec(encryptionKey, 0, keyBytes, "AES");
117       IvParameterSpec ivSpec = new IvParameterSpec(initVect);
118       alg.init(Cipher.ENCRYPT_MODE, key, ivSpec);
119       encryptedData = alg.doFinal(unencryptedData, offset, length);
120
121       if (logger.isDebugEnabled()) {
122         logger.debug("aes encrypt: Data to encrypt " + asHex(unencryptedData));
123
124         logger.debug("aes encrypt: used key " + asHex(encryptionKey));
125
126         logger.debug("aes encrypt: created privacy_params " +
127                      asHex(decryptParams.array));
128
129         logger.debug("aes encrypt: encrypted Data " +
130                      asHex(encryptedData));
131       }
132     }
133     catch (Exception JavaDoc e) {
134       logger.error("Encrypt Exception " + e);
135     }
136
137     return encryptedData;
138   }
139
140   public byte[] decrypt(byte[] cryptedData, int offset, int length,
141                         byte[] decryptionKey, long engineBoots, long engineTime,
142                         DecryptParams decryptParams) {
143
144     byte[] initVect = new byte[16];
145
146     if (decryptionKey.length < keyBytes) {
147       throw new IllegalArgumentException JavaDoc(
148           "Needed key length is " + keyBytes + ". Got only " + decryptionKey.length +
149           ".");
150     }
151
152     /* Set IV as engine_boots + engine_time + decrypt params */
153     initVect[0] = (byte) ( (engineBoots >> 24) & 0xFF);
154     initVect[1] = (byte) ( (engineBoots >> 16) & 0xFF);
155     initVect[2] = (byte) ( (engineBoots >> 8) & 0xFF);
156     initVect[3] = (byte) ( (engineBoots) & 0xFF);
157     initVect[4] = (byte) ( (engineTime >> 24) & 0xFF);
158     initVect[5] = (byte) ( (engineTime >> 16) & 0xFF);
159     initVect[6] = (byte) ( (engineTime >> 8) & 0xFF);
160     initVect[7] = (byte) ( (engineTime) & 0xFF);
161     for (int i = 0; i < 8; i++) {
162       initVect[i + 8] = decryptParams.array[i + decryptParams.offset];
163
164     }
165     if (logger.isDebugEnabled()) {
166       logger.debug("initVect is " + asHex(initVect));
167     }
168
169     byte[] decryptedData = null;
170     try {
171       // now do CFB decryption of the crypted data
172
Cipher alg = Cipher.getInstance("AES/CFB/NoPadding");
173       SecretKeySpec key =
174           new SecretKeySpec(decryptionKey, 0, keyBytes, "AES");
175       IvParameterSpec ivSpec = new IvParameterSpec(initVect);
176       alg.init(Cipher.DECRYPT_MODE, key, ivSpec);
177       decryptedData = alg.doFinal(cryptedData, offset, length);
178
179       if (logger.isDebugEnabled()) {
180         logger.debug("aes decrypt: Data to decrypt " + asHex(cryptedData));
181
182         logger.debug("aes decrypt: used key " + asHex(decryptionKey));
183
184         logger.debug("aes decrypt: used privacy_params " +
185                      asHex(decryptParams.array));
186
187         logger.debug("aes decrypt: decrypted Data " +
188                      asHex(decryptedData));
189       }
190     }
191     catch (Exception JavaDoc e) {
192       logger.error("Decrypt Exception " + e);
193     }
194
195     return decryptedData;
196   }
197
198   public int getEncryptedLength(int scopedPDULength) {
199     return scopedPDULength;
200   }
201
202   /**
203    * Turns array of bytes into string
204    *
205    * @param buf Array of bytes to convert to hex string
206    * @return Generated hex string
207    */

208   public static String JavaDoc asHex(byte buf[]) {
209     return new OctetString(buf).toHexString();
210   }
211
212   public int getMinKeyLength() {
213     return keyBytes;
214   }
215
216   public int getMaxKeyLength() {
217     return getMinKeyLength();
218   }
219
220   public int getDecryptParamsLength() {
221     return DECRYPT_PARAMS_LENGTH;
222   }
223 }
224
Popular Tags