1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44:
45: import ;
46: import ;
47: import ;
48: import ;
49:
50:
62: public class AESKeyWrap
63: extends BaseKeyWrappingAlgorithm
64: {
65: private static final byte[] DEFAULT_IV = new byte[] {
66: (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6,
67: (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6 };
68:
69: private Rijndael aes;
70: private byte[] iv;
71:
72: public AESKeyWrap()
73: {
74: super(Registry.AES_KWA);
75:
76: aes = new Rijndael();
77: }
78:
79: protected void engineInit(Map attributes) throws InvalidKeyException
80: {
81: Map cipherAttributes = new HashMap();
82: cipherAttributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(16));
83: cipherAttributes.put(IBlockCipher.KEY_MATERIAL,
84: attributes.get(KEY_ENCRYPTION_KEY_MATERIAL));
85: aes.reset();
86: aes.init(cipherAttributes);
87: byte[] initialValue = (byte[]) attributes.get(INITIAL_VALUE);
88: iv = initialValue == null ? DEFAULT_IV : (byte[]) initialValue.clone();
89: }
90:
91: protected byte[] engineWrap(byte[] in, int inOffset, int length)
92: {
93:
94:
95: if (length % 8 != 0)
96: throw new IllegalArgumentException("Input length MUST be a multiple of 8");
97: int n = length / 8;
98:
99: byte[] result = new byte[length + 8];
100:
101:
102:
103: System.arraycopy(iv, 0, result, 0, 8);
104: System.arraycopy(in, inOffset, result, 8, length);
105: byte[] B = new byte[2 * 8];
106:
107: long t;
108: for (int j = 0; j < 6; j++)
109: for (int i = 1; i <= n; i++)
110: {
111: System.arraycopy(result, 0, B, 0, 8);
112: System.arraycopy(result, i * 8, B, 8, 8);
113: aes.encryptBlock(B, 0, B, 0);
114: t = (n * j) + i;
115: result[0] = (byte)(B[0] ^ (t >>> 56));
116: result[1] = (byte)(B[1] ^ (t >>> 48));
117: result[2] = (byte)(B[2] ^ (t >>> 40));
118: result[3] = (byte)(B[3] ^ (t >>> 32));
119: result[4] = (byte)(B[4] ^ (t >>> 24));
120: result[5] = (byte)(B[5] ^ (t >>> 16));
121: result[6] = (byte)(B[6] ^ (t >>> 8));
122: result[7] = (byte)(B[7] ^ t );
123: System.arraycopy(B, 8, result, i * 8, 8);
124: }
125: return result;
126: }
127:
128: protected byte[] engineUnwrap(byte[] in, int inOffset, int length)
129: throws KeyUnwrappingException
130: {
131:
132:
133: if (length % 8 != 0)
134: throw new IllegalArgumentException("Input length MUST be a multiple of 8");
135:
136: byte[] result = new byte[length - 8];
137:
138:
139: byte[] A = new byte[8];
140: System.arraycopy(in, inOffset, A, 0, 8);
141: System.arraycopy(in, inOffset + 8, result, 0, result.length);
142: byte[] B = new byte[2 * 8];
143:
144: int n = length / 8 - 1;
145: long t;
146: for (int j = 5; j >= 0; j--)
147: for (int i = n; i >= 1; i--)
148: {
149: t = (n * j) + i;
150: B[0] = (byte)(A[0] ^ (t >>> 56));
151: B[1] = (byte)(A[1] ^ (t >>> 48));
152: B[2] = (byte)(A[2] ^ (t >>> 40));
153: B[3] = (byte)(A[3] ^ (t >>> 32));
154: B[4] = (byte)(A[4] ^ (t >>> 24));
155: B[5] = (byte)(A[5] ^ (t >>> 16));
156: B[6] = (byte)(A[6] ^ (t >>> 8));
157: B[7] = (byte)(A[7] ^ t );
158: System.arraycopy(result, (i - 1) * 8, B, 8, 8);
159: aes.decryptBlock(B, 0, B, 0);
160: System.arraycopy(B, 0, A, 0, 8);
161: System.arraycopy(B, 8, result, (i - 1) * 8, 8);
162: }
163: if (! Arrays.equals(A, iv))
164: throw new KeyUnwrappingException();
165:
166: return result;
167: }
168: }