Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: cryptix/jce/provider/cipher/SKIPJACK.java


1   /* $Id: SKIPJACK.java,v 1.5 2000/02/10 01:31:42 gelderen Exp $
2    *
3    * Copyright (C) 1995-2000 The Cryptix Foundation Limited.
4    * All rights reserved.
5    *
6    * Use, modification, copying and distribution of this software is subject
7    * the terms and conditions of the Cryptix General Licence. You should have
8    * received a copy of the Cryptix General Licence along with this library;
9    * if not, you can download a copy from http://www.cryptix.org/ .
10   */
11  package cryptix.jce.provider.cipher;
12  
13  
14  import java.security.InvalidKeyException;
15  import java.security.Key;
16  
17  
18  /**
19   * SKIPJACK
20   *
21   * @version $Revision: 1.5 $
22   * @author  Jeroen C. van Gelderen (gelderen@cryptix.org)
23   */
24  public final class SKIPJACK
25  extends BlockCipher
26  {
27      
28  // Constants and static variables
29  //............................................................................
30  
31      private static final int
32          BLOCK_SIZE = 8,
33          KEY_LENGTH = 10;
34  
35      private static final int F[] =
36      {
37          0xA3, 0xD7, 0x09, 0x83, 0xF8, 0x48, 0xF6, 0xF4,
38          0xB3, 0x21, 0x15, 0x78, 0x99, 0xB1, 0xAF, 0xF9,
39          0xE7, 0x2D, 0x4D, 0x8A, 0xCE, 0x4C, 0xCA, 0x2E,
40          0x52, 0x95, 0xD9, 0x1E, 0x4E, 0x38, 0x44, 0x28,
41          0x0A, 0xDF, 0x02, 0xA0, 0x17, 0xF1, 0x60, 0x68,
42          0x12, 0xB7, 0x7A, 0xC3, 0xE9, 0xFA, 0x3D, 0x53,
43          0x96, 0x84, 0x6B, 0xBA, 0xF2, 0x63, 0x9A, 0x19,
44          0x7C, 0xAE, 0xE5, 0xF5, 0xF7, 0x16, 0x6A, 0xA2,
45          0x39, 0xB6, 0x7B, 0x0F, 0xC1, 0x93, 0x81, 0x1B,
46          0xEE, 0xB4, 0x1A, 0xEA, 0xD0, 0x91, 0x2F, 0xB8,
47          0x55, 0xB9, 0xDA, 0x85, 0x3F, 0x41, 0xBF, 0xE0,
48          0x5A, 0x58, 0x80, 0x5F, 0x66, 0x0B, 0xD8, 0x90,
49          0x35, 0xD5, 0xC0, 0xA7, 0x33, 0x06, 0x65, 0x69,
50          0x45, 0x00, 0x94, 0x56, 0x6D, 0x98, 0x9B, 0x76,
51          0x97, 0xFC, 0xB2, 0xC2, 0xB0, 0xFE, 0xDB, 0x20,
52          0xE1, 0xEB, 0xD6, 0xE4, 0xDD, 0x47, 0x4A, 0x1D,
53          0x42, 0xED, 0x9E, 0x6E, 0x49, 0x3C, 0xCD, 0x43,
54          0x27, 0xD2, 0x07, 0xD4, 0xDE, 0xC7, 0x67, 0x18,
55          0x89, 0xCB, 0x30, 0x1F, 0x8D, 0xC6, 0x8F, 0xAA,
56          0xC8, 0x74, 0xDC, 0xC9, 0x5D, 0x5C, 0x31, 0xA4,
57          0x70, 0x88, 0x61, 0x2C, 0x9F, 0x0D, 0x2B, 0x87,
58          0x50, 0x82, 0x54, 0x64, 0x26, 0x7D, 0x03, 0x40,
59          0x34, 0x4B, 0x1C, 0x73, 0xD1, 0xC4, 0xFD, 0x3B,
60          0xCC, 0xFB, 0x7F, 0xAB, 0xE6, 0x3E, 0x5B, 0xA5,
61          0xAD, 0x04, 0x23, 0x9C, 0x14, 0x51, 0x22, 0xF0,
62          0x29, 0x79, 0x71, 0x7E, 0xFF, 0x8C, 0x0E, 0xE2,
63          0x0C, 0xEF, 0xBC, 0x72, 0x75, 0x6F, 0x37, 0xA1,
64          0xEC, 0xD3, 0x8E, 0x62, 0x8B, 0x86, 0x10, 0xE8,
65          0x08, 0x77, 0x11, 0xBE, 0x92, 0x4F, 0x24, 0xC5,
66          0x32, 0x36, 0x9D, 0xCF, 0xF3, 0xA6, 0xBB, 0xAC,
67          0x5E, 0x6C, 0xA9, 0x13, 0x57, 0x25, 0xB5, 0xE3,
68          0xBD, 0xA8, 0x3A, 0x01, 0x05, 0x59, 0x2A, 0x46
69      };
70  
71  
72  // Instance variables
73  //............................................................................
74  
75      /**
76       * Twelf-byte array of subkeys. It's 12 to save on modulus operations. 
77       * The last 2 bytes must be equal to the first two bytes.
78       */
79      private final int[] K = new int[12];
80      
81      /** We are in decrypt mode */
82      private boolean decrypt;
83  
84  
85  // Constructor
86  //............................................................................
87  
88      public SKIPJACK() 
89      {
90          super(BLOCK_SIZE);
91      }
92  
93  
94  // Implementation of abstract methods
95  //............................................................................
96   
97      protected void coreInit(Key key, boolean decrypt)
98      throws InvalidKeyException 
99      {
100         byte[] userkey = key.getEncoded();
101         if( userkey == null )
102             throw new InvalidKeyException("Null user key");
103 
104         if( userkey.length != KEY_LENGTH )
105             throw new InvalidKeyException("Invalid user key length");
106             
107         for( int i=0; i<K.length; i++)
108             K[i] = userkey[i%KEY_LENGTH]&0xFF;
109             
110         this.decrypt = decrypt;
111     }
112 
113     
114     protected void coreCrypt(byte[] in, int inOffset, byte[] out, int outOffset) 
115     {
116         if(decrypt)
117             blockDecrypt(in, inOffset, out, outOffset);
118         else
119             blockEncrypt(in, inOffset, out, outOffset);
120     }
121 
122 
123 // Private parts
124 //............................................................................
125 
126     /**
127      * Encrypt a single, 8-byte block. Input and output may overlap.
128      */
129     private final void blockEncrypt(byte[] in, int inOffset, byte[] out, int outOffset)
130     {
131         int w1 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
132         int w2 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
133         int w3 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
134         int w4 = (in[inOffset++]&0xFF) << 8 | (in[inOffset  ]&0xFF);
135 
136         // A
137         w1  = G(w1, 0); w4 ^= w1 ^ 1;
138         w4  = G(w4, 4); w3 ^= w4 ^ 2;
139         w3  = G(w3, 8); w2 ^= w3 ^ 3;
140         w2  = G(w2, 2); w1 ^= w2 ^ 4;
141         w1  = G(w1, 6); w4 ^= w1 ^ 5;
142         w4  = G(w4, 0); w3 ^= w4 ^ 6;
143         w3  = G(w3, 4); w2 ^= w3 ^ 7;
144         w2  = G(w2, 8); w1 ^= w2 ^ 8;
145         // B
146         w2 ^= w1 ^  9; w1  = G(w1, 2);
147         w1 ^= w4 ^ 10; w4  = G(w4, 6);
148         w4 ^= w3 ^ 11; w3  = G(w3, 0);
149         w3 ^= w2 ^ 12; w2  = G(w2, 4);
150         w2 ^= w1 ^ 13; w1  = G(w1, 8);
151         w1 ^= w4 ^ 14; w4  = G(w4, 2);
152         w4 ^= w3 ^ 15; w3  = G(w3, 6);
153         w3 ^= w2 ^ 16; w2  = G(w2, 0);
154         // A
155         w1  = G(w1, 4); w4 ^= w1 ^ 17;
156         w4  = G(w4, 8); w3 ^= w4 ^ 18;
157         w3  = G(w3, 2); w2 ^= w3 ^ 19;
158         w2  = G(w2, 6); w1 ^= w2 ^ 20;
159         w1  = G(w1, 0); w4 ^= w1 ^ 21;
160         w4  = G(w4, 4); w3 ^= w4 ^ 22;
161         w3  = G(w3, 8); w2 ^= w3 ^ 23;
162         w2  = G(w2, 2); w1 ^= w2 ^ 24;
163         // B
164         w2 ^= w1 ^ 25; w1  = G(w1, 6);
165         w1 ^= w4 ^ 26; w4  = G(w4, 0);
166         w4 ^= w3 ^ 27; w3  = G(w3, 4);
167         w3 ^= w2 ^ 28; w2  = G(w2, 8);
168         w2 ^= w1 ^ 29; w1  = G(w1, 2);
169         w1 ^= w4 ^ 30; w4  = G(w4, 6);
170         w4 ^= w3 ^ 31; w3  = G(w3, 0);
171         w3 ^= w2 ^ 32; w2  = G(w2, 4);
172 
173         out[outOffset++] = (byte)(w1 >>> 8);
174         out[outOffset++] = (byte)(w1      );
175         out[outOffset++] = (byte)(w2 >>> 8);
176         out[outOffset++] = (byte)(w2      );
177         out[outOffset++] = (byte)(w3 >>> 8);
178         out[outOffset++] = (byte)(w3      );
179         out[outOffset++] = (byte)(w4 >>> 8);
180         out[outOffset  ] = (byte)(w4      );
181     }
182 
183     
184     /** G-function used by blockEncrypt */
185     private final int G(int in, int counter)
186     {
187         int low  = (in & 0x000000FF);
188         int high = (in             ) >>> 8;
189 
190         high ^= F[low  ^ K[counter  ]];
191         low  ^= F[high ^ K[counter+1]];
192         high ^= F[low  ^ K[counter+2]];
193         low  ^= F[high ^ K[counter+3]];
194 
195         return (high << 8) | low;
196     }
197 
198 
199     /**
200      * Decrypt a single block. Input and output may overlap.
201      */
202     private final void blockDecrypt(byte[] in, int inOffset, byte[] out, int outOffset)
203     {
204         int w1 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
205         int w2 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
206         int w3 = (in[inOffset++]&0xFF) << 8 | (in[inOffset++]&0xFF);
207         int w4 = (in[inOffset++]&0xFF) << 8 | (in[inOffset  ]&0xFF);
208 
209         // B-1
210         w2  = GINV(w2,  7); w3 ^= w2 ^ 32;
211         w3  = GINV(w3,  3); w4 ^= w3 ^ 31;
212         w4  = GINV(w4,  9); w1 ^= w4 ^ 30;
213         w1  = GINV(w1,  5); w2 ^= w1 ^ 29;
214         w2  = GINV(w2, 11); w3 ^= w2 ^ 28;
215         w3  = GINV(w3,  7); w4 ^= w3 ^ 27;
216         w4  = GINV(w4,  3); w1 ^= w4 ^ 26;
217         w1  = GINV(w1,  9); w2 ^= w1 ^ 25;
218         // A-1
219         w1 ^= w2 ^ 24; w2 = GINV(w2,  5);
220         w2 ^= w3 ^ 23; w3 = GINV(w3, 11);
221         w3 ^= w4 ^ 22; w4 = GINV(w4,  7);
222         w4 ^= w1 ^ 21; w1 = GINV(w1,  3);
223         w1 ^= w2 ^ 20; w2 = GINV(w2,  9);
224         w2 ^= w3 ^ 19; w3 = GINV(w3,  5);
225         w3 ^= w4 ^ 18; w4 = GINV(w4, 11);
226         w4 ^= w1 ^ 17; w1 = GINV(w1,  7);
227         // B-1
228         w2  = GINV(w2,  3); w3 ^= w2 ^ 16;
229         w3  = GINV(w3,  9); w4 ^= w3 ^ 15;
230         w4  = GINV(w4,  5); w1 ^= w4 ^ 14;
231         w1  = GINV(w1, 11); w2 ^= w1 ^ 13;
232         w2  = GINV(w2,  7); w3 ^= w2 ^ 12;
233         w3  = GINV(w3,  3); w4 ^= w3 ^ 11;
234         w4  = GINV(w4,  9); w1 ^= w4 ^ 10;
235         w1  = GINV(w1,  5); w2 ^= w1 ^  9;
236         // A-1
237         w1 ^= w2 ^ 8; w2 = GINV(w2, 11);
238         w2 ^= w3 ^ 7; w3 = GINV(w3,  7);
239         w3 ^= w4 ^ 6; w4 = GINV(w4,  3);
240         w4 ^= w1 ^ 5; w1 = GINV(w1,  9);
241         w1 ^= w2 ^ 4; w2 = GINV(w2,  5);
242         w2 ^= w3 ^ 3; w3 = GINV(w3, 11);
243         w3 ^= w4 ^ 2; w4 = GINV(w4,  7);
244         w4 ^= w1 ^ 1; w1 = GINV(w1,  3);
245 
246         out[outOffset++] = (byte)(w1 >>> 8);
247         out[outOffset++] = (byte)(w1      );
248         out[outOffset++] = (byte)(w2 >>> 8);
249         out[outOffset++] = (byte)(w2      );
250         out[outOffset++] = (byte)(w3 >>> 8);
251         out[outOffset++] = (byte)(w3      );
252         out[outOffset++] = (byte)(w4 >>> 8);
253         out[outOffset  ] = (byte)(w4      );
254 
255     }
256 
257 
258     /** G-inverse function used by blockDecrypt */
259     private final int GINV(int in, int counter)
260     {
261         int low  = (in & 0x000000FF);
262         int high = (in             ) >>> 8;
263 
264         low  ^= F[high ^ K[counter  ]];
265         high ^= F[low  ^ K[counter-1]];
266         low  ^= F[high ^ K[counter-2]];
267         high ^= F[low  ^ K[counter-3]];
268 
269         return (high << 8) | low;
270     }
271 }