CipherTest.java revision 5eea67dda648cec5ce6239ae64659d8cff0a15c0
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.javax.crypto;
18
19import com.android.org.bouncycastle.asn1.x509.KeyUsage;
20import java.io.ByteArrayOutputStream;
21import java.io.PrintStream;
22import java.math.BigInteger;
23import java.nio.ByteBuffer;
24import java.security.AlgorithmParameters;
25import java.security.InvalidAlgorithmParameterException;
26import java.security.InvalidKeyException;
27import java.security.Key;
28import java.security.KeyFactory;
29import java.security.NoSuchAlgorithmException;
30import java.security.PrivateKey;
31import java.security.Provider;
32import java.security.PublicKey;
33import java.security.SecureRandom;
34import java.security.Security;
35import java.security.cert.Certificate;
36import java.security.spec.AlgorithmParameterSpec;
37import java.security.spec.RSAPrivateKeySpec;
38import java.security.spec.RSAPublicKeySpec;
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.Collections;
42import java.util.HashMap;
43import java.util.HashSet;
44import java.util.List;
45import java.util.Locale;
46import java.util.Map;
47import java.util.Set;
48import javax.crypto.BadPaddingException;
49import javax.crypto.Cipher;
50import javax.crypto.IllegalBlockSizeException;
51import javax.crypto.KeyGenerator;
52import javax.crypto.SecretKey;
53import javax.crypto.SecretKeyFactory;
54import javax.crypto.ShortBufferException;
55import javax.crypto.spec.GCMParameterSpec;
56import javax.crypto.spec.IvParameterSpec;
57import javax.crypto.spec.PBEKeySpec;
58import javax.crypto.spec.PBEParameterSpec;
59import javax.crypto.spec.SecretKeySpec;
60import junit.framework.TestCase;
61import libcore.java.security.StandardNames;
62import libcore.java.security.TestKeyStore;
63
64public final class CipherTest extends TestCase {
65
66    /** GCM tag size used for tests. */
67    private static final int GCM_TAG_SIZE_BITS = 96;
68
69    private static final String[] RSA_PROVIDERS = ((StandardNames.IS_RI)
70                                                   ? new String[] { "SunJCE" }
71                                                   : new String[] { "BC" , "AndroidOpenSSL" });
72
73    private static final String[] AES_PROVIDERS = ((StandardNames.IS_RI)
74                                                   ? new String[] { "SunJCE" }
75                                                   : new String[] { "BC", "AndroidOpenSSL" });
76
77    private static boolean isSupported(String algorithm, String provider) {
78        if (algorithm.equals("RC2")) {
79            return false;
80        }
81        if (algorithm.equals("PBEWITHMD5ANDRC2")) {
82            return false;
83        }
84        if (algorithm.startsWith("PBEWITHSHA1ANDRC2")) {
85            return false;
86        }
87        if (algorithm.equals("PBEWITHSHAAND40BITRC2-CBC")) {
88            return false;
89        }
90        if (algorithm.equals("PBEWITHSHAAND128BITRC2-CBC")) {
91            return false;
92        }
93        if (algorithm.equals("PBEWITHSHAANDTWOFISH-CBC")) {
94            return false;
95        }
96        if (!IS_UNLIMITED) {
97            if (algorithm.equals("PBEWITHMD5ANDTRIPLEDES")) {
98                return false;
99            }
100        }
101        // stream modes CFB, CTR, CTS, OFB with PKCS5Padding or PKCS7Padding don't really make sense
102        if (!provider.equals("AndroidOpenSSL") &&
103            (algorithm.equals("AES/CFB/PKCS5PADDING")
104             || algorithm.equals("AES/CFB/PKCS7PADDING")
105             || algorithm.equals("AES/CTR/PKCS5PADDING")
106             || algorithm.equals("AES/CTR/PKCS7PADDING")
107             || algorithm.equals("AES/CTS/PKCS5PADDING")
108             || algorithm.equals("AES/CTS/PKCS7PADDING")
109             || algorithm.equals("AES/OFB/PKCS5PADDING")
110             || algorithm.equals("AES/OFB/PKCS7PADDING"))) {
111            return false;
112        }
113        return true;
114    }
115
116    private static boolean isSupportedForWrapping(String algorithm) {
117        if (isOnlyWrappingAlgorithm(algorithm)) {
118            return true;
119        }
120        // http://b/9097343 RSA with NoPadding won't work since
121        // leading zeroes in the underlying key material are lost.
122        if (algorithm.equals("RSA/ECB/NOPADDING")) {
123            return false;
124        }
125        // AESWRAP should be used instead, fails with BC and SunJCE otherwise.
126        if (algorithm.startsWith("AES") || algorithm.startsWith("DESEDE")) {
127            return false;
128        }
129        return true;
130    }
131
132    private synchronized static int getEncryptMode(String algorithm) throws Exception {
133        if (isOnlyWrappingAlgorithm(algorithm)) {
134            return Cipher.WRAP_MODE;
135        }
136        return Cipher.ENCRYPT_MODE;
137    }
138
139    private synchronized static int getDecryptMode(String algorithm) throws Exception {
140        if (isOnlyWrappingAlgorithm(algorithm)) {
141            return Cipher.UNWRAP_MODE;
142        }
143        return Cipher.DECRYPT_MODE;
144    }
145
146    private static String getBaseAlgorithm(String algorithm) {
147        if (algorithm.equals("AESWRAP")) {
148            return "AES";
149        }
150        if (algorithm.startsWith("AES/")) {
151            return "AES";
152        }
153        if (algorithm.equals("GCM")) {
154            return "AES";
155        }
156        if (algorithm.startsWith("DESEDE/")) {
157            return "DESEDE";
158        }
159        if (algorithm.equals("PBEWITHMD5AND128BITAES-CBC-OPENSSL")) {
160            return "AES";
161        }
162        if (algorithm.equals("PBEWITHMD5AND192BITAES-CBC-OPENSSL")) {
163            return "AES";
164        }
165        if (algorithm.equals("PBEWITHMD5AND256BITAES-CBC-OPENSSL")) {
166            return "AES";
167        }
168        if (algorithm.equals("PBEWITHSHA256AND128BITAES-CBC-BC")) {
169            return "AES";
170        }
171        if (algorithm.equals("PBEWITHSHA256AND192BITAES-CBC-BC")) {
172            return "AES";
173        }
174        if (algorithm.equals("PBEWITHSHA256AND256BITAES-CBC-BC")) {
175            return "AES";
176        }
177        if (algorithm.equals("PBEWITHSHAAND128BITAES-CBC-BC")) {
178            return "AES";
179        }
180        if (algorithm.equals("PBEWITHSHAAND192BITAES-CBC-BC")) {
181            return "AES";
182        }
183        if (algorithm.equals("PBEWITHSHAAND256BITAES-CBC-BC")) {
184            return "AES";
185        }
186        if (algorithm.equals("PBEWITHMD5ANDDES")) {
187            return "DES";
188        }
189        if (algorithm.equals("PBEWITHSHA1ANDDES")) {
190            return "DES";
191        }
192        if (algorithm.equals("DESEDEWRAP")) {
193            return "DESEDE";
194        }
195        if (algorithm.equals("PBEWITHSHAAND2-KEYTRIPLEDES-CBC")) {
196            return "DESEDE";
197        }
198        if (algorithm.equals("PBEWITHSHAAND3-KEYTRIPLEDES-CBC")) {
199            return "DESEDE";
200        }
201        if (algorithm.equals("PBEWITHMD5ANDTRIPLEDES")) {
202            return "DESEDE";
203        }
204        if (algorithm.equals("PBEWITHSHA1ANDDESEDE")) {
205            return "DESEDE";
206        }
207        if (algorithm.equals("RSA/ECB/NOPADDING")) {
208            return "RSA";
209        }
210        if (algorithm.equals("RSA/ECB/PKCS1PADDING")) {
211            return "RSA";
212        }
213        if (algorithm.equals("PBEWITHSHAAND40BITRC4")) {
214            return "ARC4";
215        }
216        if (algorithm.equals("PBEWITHSHAAND128BITRC4")) {
217            return "ARC4";
218        }
219        return algorithm;
220    }
221
222    private static boolean isAsymmetric(String algorithm) {
223        return getBaseAlgorithm(algorithm).equals("RSA");
224    }
225
226    private static boolean isOnlyWrappingAlgorithm(String algorithm) {
227        return algorithm.endsWith("WRAP");
228    }
229
230    private static boolean isPBE(String algorithm) {
231        return algorithm.startsWith("PBE");
232    }
233
234    private static boolean isStreamMode(String algorithm) {
235        return algorithm.contains("/CTR/") || algorithm.contains("/OFB")
236                || algorithm.contains("/CFB");
237    }
238
239    private static Map<String, Key> ENCRYPT_KEYS = new HashMap<String, Key>();
240    private synchronized static Key getEncryptKey(String algorithm) throws Exception {
241        Key key = ENCRYPT_KEYS.get(algorithm);
242        if (key != null) {
243            return key;
244        }
245        if (algorithm.startsWith("RSA")) {
246            KeyFactory kf = KeyFactory.getInstance("RSA");
247            RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
248                                                              RSA_2048_privateExponent);
249            key = kf.generatePrivate(keySpec);
250        } else if (isPBE(algorithm)) {
251            SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
252            key = skf.generateSecret(new PBEKeySpec("secret".toCharArray()));
253        } else {
254            KeyGenerator kg = KeyGenerator.getInstance(getBaseAlgorithm(algorithm));
255            key = kg.generateKey();
256        }
257        ENCRYPT_KEYS.put(algorithm, key);
258        return key;
259    }
260
261    private static Map<String, Key> DECRYPT_KEYS = new HashMap<String, Key>();
262    private synchronized static Key getDecryptKey(String algorithm) throws Exception {
263        Key key = DECRYPT_KEYS.get(algorithm);
264        if (key != null) {
265            return key;
266        }
267        if (algorithm.startsWith("RSA")) {
268            KeyFactory kf = KeyFactory.getInstance("RSA");
269            RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus,
270                                                            RSA_2048_publicExponent);
271            key = kf.generatePublic(keySpec);
272        } else {
273            assertFalse(algorithm, isAsymmetric(algorithm));
274            key = getEncryptKey(algorithm);
275        }
276        DECRYPT_KEYS.put(algorithm, key);
277        return key;
278    }
279
280    private static Map<String, Integer> EXPECTED_BLOCK_SIZE = new HashMap<String, Integer>();
281    static {
282        setExpectedBlockSize("AES", 16);
283        setExpectedBlockSize("AES/CBC/PKCS5PADDING", 16);
284        setExpectedBlockSize("AES/CBC/PKCS7PADDING", 16);
285        setExpectedBlockSize("AES/CBC/NOPADDING", 16);
286        setExpectedBlockSize("AES/CFB/PKCS5PADDING", 16);
287        setExpectedBlockSize("AES/CFB/PKCS7PADDING", 16);
288        setExpectedBlockSize("AES/CFB/NOPADDING", 16);
289        setExpectedBlockSize("AES/CTR/PKCS5PADDING", 16);
290        setExpectedBlockSize("AES/CTR/PKCS7PADDING", 16);
291        setExpectedBlockSize("AES/CTR/NOPADDING", 16);
292        setExpectedBlockSize("AES/CTS/PKCS5PADDING", 16);
293        setExpectedBlockSize("AES/CTS/PKCS7PADDING", 16);
294        setExpectedBlockSize("AES/CTS/NOPADDING", 16);
295        setExpectedBlockSize("AES/ECB/PKCS5PADDING", 16);
296        setExpectedBlockSize("AES/ECB/PKCS7PADDING", 16);
297        setExpectedBlockSize("AES/ECB/NOPADDING", 16);
298        setExpectedBlockSize("AES/OFB/PKCS5PADDING", 16);
299        setExpectedBlockSize("AES/OFB/PKCS7PADDING", 16);
300        setExpectedBlockSize("AES/OFB/NOPADDING", 16);
301        setExpectedBlockSize("GCM", 16);
302        setExpectedBlockSize("PBEWITHMD5AND128BITAES-CBC-OPENSSL", 16);
303        setExpectedBlockSize("PBEWITHMD5AND192BITAES-CBC-OPENSSL", 16);
304        setExpectedBlockSize("PBEWITHMD5AND256BITAES-CBC-OPENSSL", 16);
305        setExpectedBlockSize("PBEWITHSHA256AND128BITAES-CBC-BC", 16);
306        setExpectedBlockSize("PBEWITHSHA256AND192BITAES-CBC-BC", 16);
307        setExpectedBlockSize("PBEWITHSHA256AND256BITAES-CBC-BC", 16);
308        setExpectedBlockSize("PBEWITHSHAAND128BITAES-CBC-BC", 16);
309        setExpectedBlockSize("PBEWITHSHAAND192BITAES-CBC-BC", 16);
310        setExpectedBlockSize("PBEWITHSHAAND256BITAES-CBC-BC", 16);
311
312        if (StandardNames.IS_RI) {
313            setExpectedBlockSize("AESWRAP", 16);
314        } else {
315            setExpectedBlockSize("AESWRAP", 0);
316        }
317
318        setExpectedBlockSize("ARC4", 0);
319        setExpectedBlockSize("ARCFOUR", 0);
320        setExpectedBlockSize("PBEWITHSHAAND40BITRC4", 0);
321        setExpectedBlockSize("PBEWITHSHAAND128BITRC4", 0);
322
323        setExpectedBlockSize("BLOWFISH", 8);
324
325        setExpectedBlockSize("DES", 8);
326        setExpectedBlockSize("PBEWITHMD5ANDDES", 8);
327        setExpectedBlockSize("PBEWITHSHA1ANDDES", 8);
328
329        setExpectedBlockSize("DESEDE", 8);
330        setExpectedBlockSize("DESEDE/CBC/PKCS5PADDING", 8);
331        setExpectedBlockSize("DESEDE/CBC/PKCS7PADDING", 8);
332        setExpectedBlockSize("DESEDE/CBC/NOPADDING", 8);
333        setExpectedBlockSize("DESEDE/CFB/PKCS5PADDING", 8);
334        setExpectedBlockSize("DESEDE/CFB/PKCS7PADDING", 8);
335        setExpectedBlockSize("DESEDE/CFB/NOPADDING", 8);
336        setExpectedBlockSize("DESEDE/CTR/PKCS5PADDING", 8);
337        setExpectedBlockSize("DESEDE/CTR/PKCS7PADDING", 8);
338        setExpectedBlockSize("DESEDE/CTR/NOPADDING", 8);
339        setExpectedBlockSize("DESEDE/CTS/PKCS5PADDING", 8);
340        setExpectedBlockSize("DESEDE/CTS/PKCS7PADDING", 8);
341        setExpectedBlockSize("DESEDE/CTS/NOPADDING", 8);
342        setExpectedBlockSize("DESEDE/ECB/PKCS5PADDING", 8);
343        setExpectedBlockSize("DESEDE/ECB/PKCS7PADDING", 8);
344        setExpectedBlockSize("DESEDE/ECB/NOPADDING", 8);
345        setExpectedBlockSize("DESEDE/OFB/PKCS5PADDING", 8);
346        setExpectedBlockSize("DESEDE/OFB/PKCS7PADDING", 8);
347        setExpectedBlockSize("DESEDE/OFB/NOPADDING", 8);
348        setExpectedBlockSize("PBEWITHSHAAND2-KEYTRIPLEDES-CBC", 8);
349        setExpectedBlockSize("PBEWITHSHAAND3-KEYTRIPLEDES-CBC", 8);
350        setExpectedBlockSize("PBEWITHMD5ANDTRIPLEDES", 8);
351        setExpectedBlockSize("PBEWITHSHA1ANDDESEDE", 8);
352
353
354        if (StandardNames.IS_RI) {
355            setExpectedBlockSize("DESEDEWRAP", 8);
356        } else {
357            setExpectedBlockSize("DESEDEWRAP", 0);
358        }
359
360        if (StandardNames.IS_RI) {
361            setExpectedBlockSize("RSA", 0);
362            setExpectedBlockSize("RSA/ECB/NoPadding", 0);
363            setExpectedBlockSize("RSA/ECB/PKCS1Padding", 0);
364        } else {
365            setExpectedBlockSize("RSA", Cipher.ENCRYPT_MODE, 256);
366            setExpectedBlockSize("RSA/ECB/NoPadding", Cipher.ENCRYPT_MODE, 256);
367            setExpectedBlockSize("RSA/ECB/PKCS1Padding", Cipher.ENCRYPT_MODE, 245);
368
369            // BC strips the leading 0 for us even when NoPadding is specified
370            setExpectedBlockSize("RSA", Cipher.ENCRYPT_MODE, "BC", 255);
371            setExpectedBlockSize("RSA/ECB/NoPadding", Cipher.ENCRYPT_MODE, "BC", 255);
372
373            setExpectedBlockSize("RSA", Cipher.DECRYPT_MODE, 256);
374            setExpectedBlockSize("RSA/ECB/NoPadding", Cipher.DECRYPT_MODE, 256);
375            setExpectedBlockSize("RSA/ECB/PKCS1Padding", Cipher.DECRYPT_MODE, 256);
376        }
377    }
378
379    private static String modeKey(String algorithm, int mode) {
380        return algorithm + ":" + mode;
381    }
382
383    private static String modeProviderKey(String algorithm, int mode, String provider) {
384        return algorithm + ":" + mode + ":" + provider;
385    }
386
387    private static void setExpectedSize(Map<String, Integer> map,
388                                        String algorithm, int value) {
389        algorithm = algorithm.toUpperCase(Locale.US);
390        map.put(algorithm, value);
391    }
392
393    private static void setExpectedSize(Map<String, Integer> map,
394                                        String algorithm, int mode, int value) {
395        setExpectedSize(map, modeKey(algorithm, mode), value);
396    }
397
398    private static void setExpectedSize(Map<String, Integer> map,
399                                        String algorithm, int mode, String provider, int value) {
400        setExpectedSize(map, modeProviderKey(algorithm, mode, provider), value);
401    }
402
403    private static int getExpectedSize(Map<String, Integer> map, String algorithm, int mode, String provider) {
404        algorithm = algorithm.toUpperCase(Locale.US);
405        provider = provider.toUpperCase(Locale.US);
406        Integer expected = map.get(modeProviderKey(algorithm, mode, provider));
407        if (expected != null) {
408            return expected;
409        }
410        expected = map.get(modeKey(algorithm, mode));
411        if (expected != null) {
412            return expected;
413        }
414        expected = map.get(algorithm);
415        assertNotNull("Algorithm " + algorithm + " with mode " + mode + " and provider " + provider
416                      + " not found in " + map, expected);
417        return expected;
418    }
419
420    private static void setExpectedBlockSize(String algorithm, int value) {
421        setExpectedSize(EXPECTED_BLOCK_SIZE, algorithm, value);
422    }
423
424    private static void setExpectedBlockSize(String algorithm, int mode, int value) {
425        setExpectedSize(EXPECTED_BLOCK_SIZE, algorithm, mode, value);
426    }
427
428    private static void setExpectedBlockSize(String algorithm, int mode, String provider, int value) {
429        setExpectedSize(EXPECTED_BLOCK_SIZE, algorithm, mode, provider, value);
430    }
431
432    private static int getExpectedBlockSize(String algorithm, int mode, String provider) {
433        return getExpectedSize(EXPECTED_BLOCK_SIZE, algorithm, mode, provider);
434    }
435
436    private static Map<String, Integer> EXPECTED_OUTPUT_SIZE = new HashMap<String, Integer>();
437    static {
438        setExpectedOutputSize("AES/CBC/NOPADDING", 0);
439        setExpectedOutputSize("AES/CFB/NOPADDING", 0);
440        setExpectedOutputSize("AES/CTR/NOPADDING", 0);
441        setExpectedOutputSize("AES/CTS/NOPADDING", 0);
442        setExpectedOutputSize("AES/ECB/NOPADDING", 0);
443        setExpectedOutputSize("AES/OFB/NOPADDING", 0);
444
445        setExpectedOutputSize("AES", Cipher.ENCRYPT_MODE, 16);
446        setExpectedOutputSize("AES/CBC/PKCS5PADDING", Cipher.ENCRYPT_MODE, 16);
447        setExpectedOutputSize("AES/CBC/PKCS7PADDING", Cipher.ENCRYPT_MODE, 16);
448        setExpectedOutputSize("AES/CFB/PKCS5PADDING", Cipher.ENCRYPT_MODE, 16);
449        setExpectedOutputSize("AES/CFB/PKCS7PADDING", Cipher.ENCRYPT_MODE, 16);
450        setExpectedOutputSize("AES/CTR/PKCS5PADDING", Cipher.ENCRYPT_MODE, 16);
451        setExpectedOutputSize("AES/CTR/PKCS7PADDING", Cipher.ENCRYPT_MODE, 16);
452        setExpectedOutputSize("AES/CTS/PKCS5PADDING", Cipher.ENCRYPT_MODE, 16);
453        setExpectedOutputSize("AES/CTS/PKCS7PADDING", Cipher.ENCRYPT_MODE, 16);
454        setExpectedOutputSize("AES/ECB/PKCS5PADDING", Cipher.ENCRYPT_MODE, 16);
455        setExpectedOutputSize("AES/ECB/PKCS7PADDING", Cipher.ENCRYPT_MODE, 16);
456        setExpectedOutputSize("AES/OFB/PKCS5PADDING", Cipher.ENCRYPT_MODE, 16);
457        setExpectedOutputSize("AES/OFB/PKCS7PADDING", Cipher.ENCRYPT_MODE, 16);
458        setExpectedOutputSize("GCM", Cipher.ENCRYPT_MODE, GCM_TAG_SIZE_BITS / 8);
459        setExpectedOutputSize("PBEWITHMD5AND128BITAES-CBC-OPENSSL", 16);
460        setExpectedOutputSize("PBEWITHMD5AND192BITAES-CBC-OPENSSL", 16);
461        setExpectedOutputSize("PBEWITHMD5AND256BITAES-CBC-OPENSSL", 16);
462        setExpectedOutputSize("PBEWITHSHA256AND128BITAES-CBC-BC", 16);
463        setExpectedOutputSize("PBEWITHSHA256AND192BITAES-CBC-BC", 16);
464        setExpectedOutputSize("PBEWITHSHA256AND256BITAES-CBC-BC", 16);
465        setExpectedOutputSize("PBEWITHSHAAND128BITAES-CBC-BC", 16);
466        setExpectedOutputSize("PBEWITHSHAAND192BITAES-CBC-BC", 16);
467        setExpectedOutputSize("PBEWITHSHAAND256BITAES-CBC-BC", 16);
468        // AndroidOpenSSL returns zero for the non-block ciphers
469        setExpectedOutputSize("AES/CFB/PKCS5PADDING", Cipher.ENCRYPT_MODE, "AndroidOpenSSL", 0);
470        setExpectedOutputSize("AES/CFB/PKCS7PADDING", Cipher.ENCRYPT_MODE, "AndroidOpenSSL", 0);
471        setExpectedOutputSize("AES/CTR/PKCS5PADDING", Cipher.ENCRYPT_MODE, "AndroidOpenSSL", 0);
472        setExpectedOutputSize("AES/CTR/PKCS7PADDING", Cipher.ENCRYPT_MODE, "AndroidOpenSSL", 0);
473        setExpectedOutputSize("AES/CTS/PKCS5PADDING", Cipher.ENCRYPT_MODE, "AndroidOpenSSL", 0);
474        setExpectedOutputSize("AES/CTS/PKCS7PADDING", Cipher.ENCRYPT_MODE, "AndroidOpenSSL", 0);
475        setExpectedOutputSize("AES/OFB/PKCS5PADDING", Cipher.ENCRYPT_MODE, "AndroidOpenSSL", 0);
476        setExpectedOutputSize("AES/OFB/PKCS7PADDING", Cipher.ENCRYPT_MODE, "AndroidOpenSSL", 0);
477
478        setExpectedOutputSize("AES", Cipher.DECRYPT_MODE, 0);
479        setExpectedOutputSize("AES/CBC/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
480        setExpectedOutputSize("AES/CBC/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
481        setExpectedOutputSize("AES/CFB/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
482        setExpectedOutputSize("AES/CFB/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
483        setExpectedOutputSize("AES/CTR/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
484        setExpectedOutputSize("AES/CTR/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
485        setExpectedOutputSize("AES/CTS/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
486        setExpectedOutputSize("AES/CTS/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
487        setExpectedOutputSize("AES/ECB/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
488        setExpectedOutputSize("AES/ECB/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
489        setExpectedOutputSize("AES/OFB/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
490        setExpectedOutputSize("AES/OFB/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
491        setExpectedOutputSize("GCM", Cipher.DECRYPT_MODE, 0);
492        setExpectedOutputSize("PBEWITHMD5AND128BITAES-CBC-OPENSSL", Cipher.DECRYPT_MODE, 0);
493        setExpectedOutputSize("PBEWITHMD5AND192BITAES-CBC-OPENSSL", Cipher.DECRYPT_MODE, 0);
494        setExpectedOutputSize("PBEWITHMD5AND256BITAES-CBC-OPENSSL", Cipher.DECRYPT_MODE, 0);
495        setExpectedOutputSize("PBEWITHSHA256AND128BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0);
496        setExpectedOutputSize("PBEWITHSHA256AND192BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0);
497        setExpectedOutputSize("PBEWITHSHA256AND256BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0);
498        setExpectedOutputSize("PBEWITHSHAAND128BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0);
499        setExpectedOutputSize("PBEWITHSHAAND192BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0);
500        setExpectedOutputSize("PBEWITHSHAAND256BITAES-CBC-BC", Cipher.DECRYPT_MODE, 0);
501        // AndroidOpenSSL returns the block size for the block ciphers
502        setExpectedOutputSize("AES/CBC/PKCS5PADDING", Cipher.DECRYPT_MODE, "AndroidOpenSSL", 16);
503        setExpectedOutputSize("AES/CBC/PKCS7PADDING", Cipher.DECRYPT_MODE, "AndroidOpenSSL", 16);
504        setExpectedOutputSize("AES/ECB/PKCS5PADDING", Cipher.DECRYPT_MODE, "AndroidOpenSSL", 16);
505        setExpectedOutputSize("AES/ECB/PKCS7PADDING", Cipher.DECRYPT_MODE, "AndroidOpenSSL", 16);
506        setExpectedOutputSize("DESEDE/CBC/PKCS5PADDING", Cipher.DECRYPT_MODE, "AndroidOpenSSL", 8);
507        setExpectedOutputSize("DESEDE/CBC/PKCS7PADDING", Cipher.DECRYPT_MODE, "AndroidOpenSSL", 8);
508        setExpectedOutputSize("DESEDE/ECB/PKCS5PADDING", Cipher.DECRYPT_MODE, "AndroidOpenSSL", 8);
509        setExpectedOutputSize("DESEDE/ECB/PKCS7PADDING", Cipher.DECRYPT_MODE, "AndroidOpenSSL", 8);
510
511        if (StandardNames.IS_RI) {
512            setExpectedOutputSize("AESWRAP", Cipher.WRAP_MODE, 8);
513            setExpectedOutputSize("AESWRAP", Cipher.UNWRAP_MODE, 0);
514        } else {
515            setExpectedOutputSize("AESWRAP", -1);
516        }
517
518        setExpectedOutputSize("ARC4", 0);
519        setExpectedOutputSize("ARCFOUR", 0);
520        setExpectedOutputSize("PBEWITHSHAAND40BITRC4", 0);
521        setExpectedOutputSize("PBEWITHSHAAND128BITRC4", 0);
522
523        setExpectedOutputSize("BLOWFISH", Cipher.ENCRYPT_MODE, 8);
524        setExpectedOutputSize("BLOWFISH", Cipher.DECRYPT_MODE, 0);
525
526        setExpectedOutputSize("DES", Cipher.ENCRYPT_MODE, 8);
527        setExpectedOutputSize("PBEWITHMD5ANDDES", Cipher.ENCRYPT_MODE, 8);
528        setExpectedOutputSize("PBEWITHSHA1ANDDES", Cipher.ENCRYPT_MODE, 8);
529
530        setExpectedOutputSize("DES", Cipher.DECRYPT_MODE, 0);
531        setExpectedOutputSize("PBEWITHMD5ANDDES", Cipher.DECRYPT_MODE, 0);
532        setExpectedOutputSize("PBEWITHSHA1ANDDES", Cipher.DECRYPT_MODE, 0);
533
534        setExpectedOutputSize("DESEDE/CBC/NOPADDING", 0);
535        setExpectedOutputSize("DESEDE/CFB/NOPADDING", 0);
536        setExpectedOutputSize("DESEDE/CTR/NOPADDING", 0);
537        setExpectedOutputSize("DESEDE/CTS/NOPADDING", 0);
538        setExpectedOutputSize("DESEDE/ECB/NOPADDING", 0);
539        setExpectedOutputSize("DESEDE/OFB/NOPADDING", 0);
540
541        setExpectedOutputSize("DESEDE", Cipher.ENCRYPT_MODE, 8);
542        setExpectedOutputSize("DESEDE/CBC/PKCS5PADDING", Cipher.ENCRYPT_MODE, 8);
543        setExpectedOutputSize("DESEDE/CBC/PKCS7PADDING", Cipher.ENCRYPT_MODE, 8);
544        setExpectedOutputSize("DESEDE/CFB/PKCS5PADDING", Cipher.ENCRYPT_MODE, 8);
545        setExpectedOutputSize("DESEDE/CFB/PKCS7PADDING", Cipher.ENCRYPT_MODE, 8);
546        setExpectedOutputSize("DESEDE/CTR/PKCS5PADDING", Cipher.ENCRYPT_MODE, 8);
547        setExpectedOutputSize("DESEDE/CTR/PKCS7PADDING", Cipher.ENCRYPT_MODE, 8);
548        setExpectedOutputSize("DESEDE/CTS/PKCS5PADDING", Cipher.ENCRYPT_MODE, 8);
549        setExpectedOutputSize("DESEDE/CTS/PKCS7PADDING", Cipher.ENCRYPT_MODE, 8);
550        setExpectedOutputSize("DESEDE/ECB/PKCS5PADDING", Cipher.ENCRYPT_MODE, 8);
551        setExpectedOutputSize("DESEDE/ECB/PKCS7PADDING", Cipher.ENCRYPT_MODE, 8);
552        setExpectedOutputSize("DESEDE/OFB/PKCS5PADDING", Cipher.ENCRYPT_MODE, 8);
553        setExpectedOutputSize("DESEDE/OFB/PKCS7PADDING", Cipher.ENCRYPT_MODE, 8);
554        setExpectedOutputSize("PBEWITHSHAAND2-KEYTRIPLEDES-CBC", Cipher.ENCRYPT_MODE, 8);
555        setExpectedOutputSize("PBEWITHSHAAND3-KEYTRIPLEDES-CBC", Cipher.ENCRYPT_MODE, 8);
556        setExpectedOutputSize("PBEWITHMD5ANDTRIPLEDES", Cipher.ENCRYPT_MODE, 8);
557        setExpectedOutputSize("PBEWITHSHA1ANDDESEDE", Cipher.ENCRYPT_MODE, 8);
558
559        setExpectedOutputSize("DESEDE", Cipher.DECRYPT_MODE, 0);
560        setExpectedOutputSize("DESEDE/CBC/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
561        setExpectedOutputSize("DESEDE/CBC/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
562        setExpectedOutputSize("DESEDE/CFB/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
563        setExpectedOutputSize("DESEDE/CFB/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
564        setExpectedOutputSize("DESEDE/CTR/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
565        setExpectedOutputSize("DESEDE/CTR/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
566        setExpectedOutputSize("DESEDE/CTS/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
567        setExpectedOutputSize("DESEDE/CTS/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
568        setExpectedOutputSize("DESEDE/ECB/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
569        setExpectedOutputSize("DESEDE/ECB/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
570        setExpectedOutputSize("DESEDE/OFB/PKCS5PADDING", Cipher.DECRYPT_MODE, 0);
571        setExpectedOutputSize("DESEDE/OFB/PKCS7PADDING", Cipher.DECRYPT_MODE, 0);
572        setExpectedOutputSize("PBEWITHSHAAND2-KEYTRIPLEDES-CBC", Cipher.DECRYPT_MODE, 0);
573        setExpectedOutputSize("PBEWITHSHAAND3-KEYTRIPLEDES-CBC", Cipher.DECRYPT_MODE, 0);
574        setExpectedOutputSize("PBEWITHMD5ANDTRIPLEDES", Cipher.DECRYPT_MODE, 0);
575        setExpectedOutputSize("PBEWITHSHA1ANDDESEDE", Cipher.DECRYPT_MODE, 0);
576
577        if (StandardNames.IS_RI) {
578            setExpectedOutputSize("DESEDEWRAP", Cipher.WRAP_MODE, 16);
579            setExpectedOutputSize("DESEDEWRAP", Cipher.UNWRAP_MODE, 0);
580        } else {
581            setExpectedOutputSize("DESEDEWRAP", -1);
582        }
583
584        setExpectedOutputSize("RSA", Cipher.ENCRYPT_MODE, 256);
585        setExpectedOutputSize("RSA/ECB/NoPadding", Cipher.ENCRYPT_MODE, 256);
586        setExpectedOutputSize("RSA/ECB/PKCS1Padding", Cipher.ENCRYPT_MODE, 256);
587
588        setExpectedOutputSize("RSA", Cipher.DECRYPT_MODE, 256);
589        setExpectedOutputSize("RSA/ECB/NoPadding", Cipher.DECRYPT_MODE, 256);
590        setExpectedOutputSize("RSA/ECB/PKCS1Padding", Cipher.DECRYPT_MODE, 245);
591
592        // SunJCE returns the full for size even when PKCS1Padding is specified
593        setExpectedOutputSize("RSA/ECB/PKCS1Padding", Cipher.DECRYPT_MODE, "SunJCE", 256);
594
595        // BC strips the leading 0 for us even when NoPadding is specified
596        setExpectedOutputSize("RSA", Cipher.DECRYPT_MODE, "BC", 255);
597        setExpectedOutputSize("RSA/ECB/NoPadding", Cipher.DECRYPT_MODE, "BC", 255);
598    }
599
600    private static void setExpectedOutputSize(String algorithm, int value) {
601        setExpectedSize(EXPECTED_OUTPUT_SIZE, algorithm, value);
602    }
603
604    private static void setExpectedOutputSize(String algorithm, int mode, int value) {
605        setExpectedSize(EXPECTED_OUTPUT_SIZE, algorithm, mode, value);
606    }
607
608    private static void setExpectedOutputSize(String algorithm, int mode, String provider, int value) {
609        setExpectedSize(EXPECTED_OUTPUT_SIZE, algorithm, mode, provider, value);
610    }
611
612    private static int getExpectedOutputSize(String algorithm, int mode, String provider) {
613        return getExpectedSize(EXPECTED_OUTPUT_SIZE, algorithm, mode, provider);
614    }
615
616    private static byte[] ORIGINAL_PLAIN_TEXT = new byte[] { 0x0a, 0x0b, 0x0c };
617    private static byte[] SIXTEEN_BYTE_BLOCK_PLAIN_TEXT = new byte[] { 0x0a, 0x0b, 0x0c, 0x00,
618                                                                       0x00, 0x00, 0x00, 0x00,
619                                                                       0x00, 0x00, 0x00, 0x00,
620                                                                       0x00, 0x00, 0x00, 0x00 };
621    private static byte[] EIGHT_BYTE_BLOCK_PLAIN_TEXT = new byte[] { 0x0a, 0x0b, 0x0c, 0x00,
622                                                                     0x00, 0x00, 0x00, 0x00 };
623    private static byte[] PKCS1_BLOCK_TYPE_00_PADDED_PLAIN_TEXT = new byte[] {
624        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
625        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
626        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
627        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
628        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
629        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
630        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
631        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
632        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
633        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
634        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
635        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
636        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
637        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
638        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
639        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0a, 0x0b, 0x0c
640    };
641    private static byte[] PKCS1_BLOCK_TYPE_01_PADDED_PLAIN_TEXT = new byte[] {
642        (byte) 0x00, (byte) 0x01, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
643        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
644        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
645        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
646        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
647        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
648        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
649        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
650        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
651        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
652        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
653        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
654        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
655        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
656        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
657        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
658        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
659        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
660        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
661        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
662        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
663        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
664        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
665        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
666        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
667        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
668        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
669        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
670        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
671        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
672        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
673        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x0a, (byte) 0x0b, (byte) 0x0c
674    };
675    private static byte[] PKCS1_BLOCK_TYPE_02_PADDED_PLAIN_TEXT = new byte[] {
676        (byte) 0x00, (byte) 0x02, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
677        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
678        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
679        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
680        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
681        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
682        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
683        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
684        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
685        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
686        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
687        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
688        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
689        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
690        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
691        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
692        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
693        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
694        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
695        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
696        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
697        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
698        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
699        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
700        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
701        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
702        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
703        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
704        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
705        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
706        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
707        (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x0a, (byte) 0x0b, (byte) 0x0c
708    };
709
710
711    private static byte[] getActualPlainText(String algorithm) {
712        // Block mode AES with NoPadding needs to match underlying block size
713        if (algorithm.equals("AES")
714            || algorithm.equals("AES/CBC/NOPADDING")
715            || algorithm.equals("AES/CTS/NOPADDING")
716            || algorithm.equals("AES/ECB/NOPADDING")) {
717            return SIXTEEN_BYTE_BLOCK_PLAIN_TEXT;
718        }
719        if (algorithm.equals("DESEDE")
720            || algorithm.equals("DESEDE/CBC/NOPADDING")
721            || algorithm.equals("DESEDE/ECB/NOPADDING")) {
722            return EIGHT_BYTE_BLOCK_PLAIN_TEXT;
723        }
724        return ORIGINAL_PLAIN_TEXT;
725    }
726
727    private static byte[] getExpectedPlainText(String algorithm, String provider) {
728        // Block mode AES with NoPadding needs to match underlying block size
729        if (algorithm.equals("AES")
730            || algorithm.equals("AES/CBC/NOPADDING")
731            || algorithm.equals("AES/CTS/NOPADDING")
732            || algorithm.equals("AES/ECB/NOPADDING")) {
733            return SIXTEEN_BYTE_BLOCK_PLAIN_TEXT;
734        }
735        if (algorithm.equals("DESEDE")
736            || algorithm.equals("DESEDE/CBC/NOPADDING")
737            || algorithm.equals("DESEDE/ECB/NOPADDING")) {
738            return EIGHT_BYTE_BLOCK_PLAIN_TEXT;
739        }
740        // BC strips the leading 0 for us even when NoPadding is specified
741        if (!provider.equals("BC") && algorithm.equals("RSA/ECB/NOPADDING")) {
742            return PKCS1_BLOCK_TYPE_00_PADDED_PLAIN_TEXT;
743        }
744        return ORIGINAL_PLAIN_TEXT;
745    }
746
747    private static AlgorithmParameterSpec getEncryptAlgorithmParameterSpec(String algorithm) {
748        if (isPBE(algorithm)) {
749            final byte[] salt = new byte[8];
750            new SecureRandom().nextBytes(salt);
751            return new PBEParameterSpec(salt, 1024);
752        }
753        if (algorithm.equals("GCM")) {
754            final byte[] iv = new byte[8];
755            new SecureRandom().nextBytes(iv);
756            return new GCMParameterSpec(GCM_TAG_SIZE_BITS, iv);
757        }
758        if (algorithm.equals("AES/CBC/NOPADDING")
759            || algorithm.equals("AES/CBC/PKCS5PADDING")
760            || algorithm.equals("AES/CBC/PKCS7PADDING")
761            || algorithm.equals("AES/CFB/NOPADDING")
762            || algorithm.equals("AES/CTR/NOPADDING")
763            || algorithm.equals("AES/CTS/NOPADDING")
764            || algorithm.equals("AES/OFB/NOPADDING")) {
765            final byte[] iv = new byte[16];
766            new SecureRandom().nextBytes(iv);
767            return new IvParameterSpec(iv);
768        }
769        if (algorithm.equals("DESEDE/CBC/NOPADDING")
770            || algorithm.equals("DESEDE/CBC/PKCS5PADDING")
771            || algorithm.equals("DESEDE/CBC/PKCS7PADDING")
772            || algorithm.equals("DESEDE/CFB/NOPADDING")
773            || algorithm.equals("DESEDE/CTR/NOPADDING")
774            || algorithm.equals("DESEDE/CTS/NOPADDING")
775            || algorithm.equals("DESEDE/OFB/NOPADDING")) {
776            final byte[] iv = new byte[8];
777            new SecureRandom().nextBytes(iv);
778            return new IvParameterSpec(iv);
779        }
780        return null;
781    }
782
783    private static AlgorithmParameterSpec getDecryptAlgorithmParameterSpec(AlgorithmParameterSpec encryptSpec,
784                                                                           Cipher encryptCipher) {
785        String algorithm = encryptCipher.getAlgorithm().toUpperCase(Locale.US);
786        if (isPBE(algorithm)) {
787            return encryptSpec;
788        }
789        if (isOnlyWrappingAlgorithm(algorithm)) {
790            return null;
791        }
792        byte[] iv = encryptCipher.getIV();
793        if (iv != null) {
794            if ("GCM".equals(algorithm)) {
795                return new GCMParameterSpec(GCM_TAG_SIZE_BITS, iv);
796            }
797            return new IvParameterSpec(iv);
798        }
799        return null;
800    }
801
802    /*
803     * This must be below everything else to make sure the other static blocks
804     * have run first.
805     */
806    private static final boolean IS_UNLIMITED;
807    static {
808        boolean is_unlimited;
809        if (StandardNames.IS_RI) {
810            try {
811                String algorithm = "PBEWITHMD5ANDTRIPLEDES";
812                Cipher.getInstance(algorithm).init(getEncryptMode(algorithm),
813                                                   getEncryptKey(algorithm),
814                                                   getEncryptAlgorithmParameterSpec(algorithm));
815                is_unlimited = true;
816            } catch (Exception e) {
817                is_unlimited = false;
818                System.out.println("WARNING: Some tests disabled due to lack of "
819                                   + "'Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files'");
820            }
821        } else {
822            is_unlimited = true;
823        }
824        IS_UNLIMITED = is_unlimited;
825    }
826
827    private static abstract class MockProvider extends Provider {
828        public MockProvider(String name) {
829            super(name, 1.0, "Mock provider used for testing");
830            setup();
831        }
832
833        public abstract void setup();
834    }
835
836    public void testCipher_getInstance_SuppliedProviderNotRegistered_Success() throws Exception {
837        Provider mockProvider = new MockProvider("MockProvider") {
838            public void setup() {
839                put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
840            }
841        };
842
843        {
844            Cipher c = Cipher.getInstance("FOO", mockProvider);
845            c.init(Cipher.ENCRYPT_MODE, new MockKey());
846            assertEquals(mockProvider, c.getProvider());
847        }
848    }
849
850    public void testCipher_getInstance_SuppliedProviderNotRegistered_MultipartTransform_Success()
851            throws Exception {
852        Provider mockProvider = new MockProvider("MockProvider") {
853            public void setup() {
854                put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
855            }
856        };
857
858        {
859            Cipher c = Cipher.getInstance("FOO/FOO/FOO", mockProvider);
860            c.init(Cipher.ENCRYPT_MODE, new MockKey());
861            assertEquals(mockProvider, c.getProvider());
862        }
863    }
864
865    public void testCipher_getInstance_OnlyUsesSpecifiedProvider_SameNameAndClass_Success()
866            throws Exception {
867        Provider mockProvider = new MockProvider("MockProvider") {
868            public void setup() {
869                put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
870            }
871        };
872
873        Security.addProvider(mockProvider);
874        try {
875            {
876                Provider mockProvider2 = new MockProvider("MockProvider") {
877                    public void setup() {
878                        put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
879                    }
880                };
881                Cipher c = Cipher.getInstance("FOO", mockProvider2);
882                assertEquals(mockProvider2, c.getProvider());
883            }
884        } finally {
885            Security.removeProvider(mockProvider.getName());
886        }
887    }
888
889    public void testCipher_getInstance_DelayedInitialization_KeyType() throws Exception {
890        Provider mockProviderSpecific = new MockProvider("MockProviderSpecific") {
891            public void setup() {
892                put("Cipher.FOO", MockCipherSpi.SpecificKeyTypes.class.getName());
893                put("Cipher.FOO SupportedKeyClasses", MockKey.class.getName());
894            }
895        };
896        Provider mockProviderSpecific2 = new MockProvider("MockProviderSpecific2") {
897            public void setup() {
898                put("Cipher.FOO", MockCipherSpi.SpecificKeyTypes2.class.getName());
899                put("Cipher.FOO SupportedKeyClasses", MockKey2.class.getName());
900            }
901        };
902        Provider mockProviderAll = new MockProvider("MockProviderAll") {
903            public void setup() {
904                put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
905            }
906        };
907
908        Security.addProvider(mockProviderSpecific);
909        Security.addProvider(mockProviderSpecific2);
910        Security.addProvider(mockProviderAll);
911
912        try {
913            {
914                System.out.println(Arrays.deepToString(Security.getProviders("Cipher.FOO")));
915                Cipher c = Cipher.getInstance("FOO");
916                c.init(Cipher.ENCRYPT_MODE, new MockKey());
917                assertEquals(mockProviderSpecific, c.getProvider());
918
919                try {
920                    c.init(Cipher.ENCRYPT_MODE, new MockKey2());
921                    assertEquals(mockProviderSpecific2, c.getProvider());
922                    if (StandardNames.IS_RI) {
923                        fail("RI was broken before; fix tests now that it works!");
924                    }
925                } catch (InvalidKeyException e) {
926                    if (!StandardNames.IS_RI) {
927                        fail("Non-RI should select the right provider");
928                    }
929                }
930            }
931
932            {
933                Cipher c = Cipher.getInstance("FOO");
934                c.init(Cipher.ENCRYPT_MODE, new Key() {
935                    @Override
936                    public String getAlgorithm() {
937                        throw new UnsupportedOperationException("not implemented");
938                    }
939
940                    @Override
941                    public String getFormat() {
942                        throw new UnsupportedOperationException("not implemented");
943                    }
944
945                    @Override
946                    public byte[] getEncoded() {
947                        throw new UnsupportedOperationException("not implemented");
948                    }
949                });
950                assertEquals(mockProviderAll, c.getProvider());
951            }
952
953            {
954                Cipher c = Cipher.getInstance("FOO");
955                assertEquals(mockProviderSpecific, c.getProvider());
956            }
957        } finally {
958            Security.removeProvider(mockProviderSpecific.getName());
959            Security.removeProvider(mockProviderSpecific2.getName());
960            Security.removeProvider(mockProviderAll.getName());
961        }
962    }
963
964    public void testCipher_getInstance_WrongType_Failure() throws Exception {
965        Provider mockProviderInvalid = new MockProvider("MockProviderInvalid") {
966            public void setup() {
967                put("Cipher.FOO", Object.class.getName());
968            }
969        };
970
971        Security.addProvider(mockProviderInvalid);
972        try {
973            Cipher.getInstance("FOO");
974            fail("Should not find any matching providers");
975        } catch (NoSuchAlgorithmException expected) {
976        } finally {
977            Security.removeProvider(mockProviderInvalid.getName());
978        }
979    }
980
981    public void test_getInstance() throws Exception {
982        final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();
983        PrintStream out = new PrintStream(errBuffer);
984
985        Set<String> seenBaseCipherNames = new HashSet<String>();
986        Set<String> seenCiphersWithModeAndPadding = new HashSet<String>();
987
988        Provider[] providers = Security.getProviders();
989        for (Provider provider : providers) {
990            Set<Provider.Service> services = provider.getServices();
991            for (Provider.Service service : services) {
992                String type = service.getType();
993                if (!type.equals("Cipher")) {
994                    continue;
995                }
996
997                String algorithm = service.getAlgorithm();
998
999                /*
1000                 * Any specific modes and paddings aren't tested directly here,
1001                 * but we need to make sure we see the bare algorithm from some
1002                 * provider. We will test each mode specifically when we get the
1003                 * base cipher.
1004                 */
1005                final int firstSlash = algorithm.indexOf('/');
1006                if (firstSlash == -1) {
1007                    seenBaseCipherNames.add(algorithm);
1008                } else {
1009                    final String baseCipherName = algorithm.substring(0, firstSlash);
1010                    if (!seenBaseCipherNames.contains(baseCipherName)) {
1011                        seenCiphersWithModeAndPadding.add(baseCipherName);
1012                    }
1013                    if (!"AndroidOpenSSL".equals(provider.getName())) {
1014                        continue;
1015                    }
1016                }
1017
1018                try {
1019                    test_Cipher_Algorithm(provider, algorithm);
1020                } catch (Throwable e) {
1021                    out.append("Error encountered checking " + algorithm
1022                               + " with provider " + provider.getName() + "\n");
1023                    e.printStackTrace(out);
1024                }
1025
1026                Set<String> modes = StandardNames.getModesForCipher(algorithm);
1027                if (modes != null) {
1028                    for (String mode : modes) {
1029                        Set<String> paddings = StandardNames.getPaddingsForCipher(algorithm);
1030                        if (paddings != null) {
1031                            for (String padding : paddings) {
1032                                final String algorithmName = algorithm + "/" + mode + "/" + padding;
1033                                try {
1034                                    test_Cipher_Algorithm(provider, algorithmName);
1035                                } catch (Throwable e) {
1036                                    out.append("Error encountered checking " + algorithmName
1037                                               + " with provider " + provider.getName() + "\n");
1038                                    e.printStackTrace(out);
1039                                }
1040                            }
1041                        }
1042                    }
1043                }
1044            }
1045        }
1046
1047        seenCiphersWithModeAndPadding.removeAll(seenBaseCipherNames);
1048        assertEquals("Ciphers seen with mode and padding but not base cipher",
1049                Collections.EMPTY_SET, seenCiphersWithModeAndPadding);
1050
1051        out.flush();
1052        if (errBuffer.size() > 0) {
1053            throw new Exception("Errors encountered:\n\n" + errBuffer.toString() + "\n\n");
1054        }
1055    }
1056
1057    private void test_Cipher_Algorithm(Provider provider, String algorithm) throws Exception {
1058        if (algorithm.equals("RSA") && provider.getName().equals("BC")) {
1059            // http://b/9097343 BC's Cipher.RSA defaults to NoPadding
1060            // which makes it fail the key wrapping test if the
1061            // generated AES key to wrap starts with a leading
1062            // zero. For the purposes of the test, use the same
1063            // default behavior as the RI. Real code really should
1064            // specify the exact mode and padding they need and not
1065            // rely on defaults. http://b/9097343
1066            algorithm = "RSA/ECB/PKCS1Padding";
1067        }
1068
1069        // Cipher.getInstance(String)
1070        Cipher c1 = Cipher.getInstance(algorithm);
1071        if (provider.equals(c1.getProvider())) {
1072            assertEquals(algorithm, c1.getAlgorithm());
1073            test_Cipher(c1);
1074        }
1075
1076        // Cipher.getInstance(String, Provider)
1077        Cipher c2 = Cipher.getInstance(algorithm, provider);
1078        assertEquals(algorithm, c2.getAlgorithm());
1079        assertEquals(provider, c2.getProvider());
1080        test_Cipher(c2);
1081
1082        // Cipher.getInstance(String, String)
1083        Cipher c3 = Cipher.getInstance(algorithm, provider.getName());
1084        assertEquals(algorithm, c3.getAlgorithm());
1085        assertEquals(provider, c3.getProvider());
1086        test_Cipher(c3);
1087    }
1088
1089    private void test_Cipher(Cipher c) throws Exception {
1090        String algorithm = c.getAlgorithm().toUpperCase(Locale.US);
1091        String providerName = c.getProvider().getName();
1092        if (!isSupported(algorithm, providerName)) {
1093            return;
1094        }
1095        String cipherID = algorithm + ":" + providerName;
1096
1097        try {
1098            c.getOutputSize(0);
1099        } catch (IllegalStateException expected) {
1100        }
1101
1102        // TODO: test keys from different factories (e.g. OpenSSLRSAPrivateKey vs JCERSAPrivateKey)
1103        Key encryptKey = getEncryptKey(algorithm);
1104
1105        final AlgorithmParameterSpec encryptSpec = getEncryptAlgorithmParameterSpec(algorithm);
1106        int encryptMode = getEncryptMode(algorithm);
1107
1108        // Bouncycastle doesn't return a default PBEParameterSpec
1109        if (isPBE(algorithm) && !"BC".equals(providerName)) {
1110            assertNotNull(cipherID + " getParameters()", c.getParameters());
1111            assertNotNull(c.getParameters().getParameterSpec(PBEParameterSpec.class));
1112        } else {
1113            assertNull(cipherID + " getParameters()", c.getParameters());
1114        }
1115        try {
1116            assertNull(cipherID + " getIV()", c.getIV());
1117        } catch (NullPointerException e) {
1118            // Bouncycastle apparently has a bug here with AESWRAP, et al.
1119            if (!("BC".equals(providerName) && isOnlyWrappingAlgorithm(algorithm))) {
1120                throw e;
1121            }
1122        }
1123
1124        test_Cipher_init_NullParameters(c, encryptMode, encryptKey);
1125
1126        c.init(encryptMode, encryptKey, encryptSpec);
1127        assertEquals(cipherID + " getBlockSize() encryptMode",
1128                     getExpectedBlockSize(algorithm, encryptMode, providerName), c.getBlockSize());
1129        assertEquals(cipherID + " getOutputSize(0) encryptMode",
1130                     getExpectedOutputSize(algorithm, encryptMode, providerName), c.getOutputSize(0));
1131        if ((algorithm.endsWith("/PKCS5PADDING") || algorithm.endsWith("/PKCS7PADDING"))
1132                && isStreamMode(algorithm)) {
1133            assertEquals(getExpectedOutputSize(algorithm, encryptMode, providerName),
1134                    c.doFinal(new byte[1]).length);
1135        }
1136
1137        final AlgorithmParameterSpec decryptSpec = getDecryptAlgorithmParameterSpec(encryptSpec, c);
1138        int decryptMode = getDecryptMode(algorithm);
1139        c.init(decryptMode, encryptKey, decryptSpec);
1140        assertEquals(cipherID + " getBlockSize() decryptMode",
1141                     getExpectedBlockSize(algorithm, decryptMode, providerName), c.getBlockSize());
1142        assertEquals(cipherID + " getOutputSize(0) decryptMode",
1143                     getExpectedOutputSize(algorithm, decryptMode, providerName), c.getOutputSize(0));
1144
1145        if (isPBE(algorithm)) {
1146            if (algorithm.endsWith("RC4")) {
1147                assertNull(cipherID + " getIV()", c.getIV());
1148            } else {
1149                assertNotNull(cipherID + " getIV()", c.getIV());
1150            }
1151        } else if (decryptSpec instanceof IvParameterSpec) {
1152            assertEquals(cipherID + " getIV()",
1153                    Arrays.toString(((IvParameterSpec) decryptSpec).getIV()),
1154                    Arrays.toString(c.getIV()));
1155        } else if (decryptSpec instanceof GCMParameterSpec) {
1156            assertNotNull(c.getIV());
1157            assertEquals(cipherID + " getIV()",
1158                    Arrays.toString(((GCMParameterSpec) decryptSpec).getIV()),
1159                    Arrays.toString(c.getIV()));
1160        } else {
1161            try {
1162                assertNull(cipherID + " getIV()", c.getIV());
1163            } catch (NullPointerException e) {
1164                // Bouncycastle apparently has a bug here with AESWRAP, et al.
1165                if (!("BC".equals(providerName) && isOnlyWrappingAlgorithm(algorithm))) {
1166                    throw e;
1167                }
1168            }
1169        }
1170
1171        AlgorithmParameters params = c.getParameters();
1172        if (decryptSpec == null) {
1173            assertNull(cipherID + " getParameters()", params);
1174        } else if (decryptSpec instanceof IvParameterSpec) {
1175            IvParameterSpec ivDecryptSpec = (IvParameterSpec) params.getParameterSpec(IvParameterSpec.class);
1176            assertEquals(cipherID + " getIV()",
1177                    Arrays.toString(((IvParameterSpec) decryptSpec).getIV()),
1178                    Arrays.toString(ivDecryptSpec.getIV()));
1179        } else if (decryptSpec instanceof PBEParameterSpec) {
1180            // Bouncycastle seems to be schizophrenic about whther it returns this or not
1181            if (!"BC".equals(providerName)) {
1182                assertNotNull(cipherID + " getParameters()", params);
1183            }
1184        }
1185
1186        assertNull(cipherID, c.getExemptionMechanism());
1187
1188        // Test wrapping a key.  Every cipher should be able to wrap. Except those that can't.
1189        /* Bouncycastle is broken for wrapping because getIV() fails. */
1190        if (isSupportedForWrapping(algorithm)
1191                && !algorithm.equals("GCM") && !providerName.equals("BC")) {
1192            // Generate a small SecretKey for AES.
1193            KeyGenerator kg = KeyGenerator.getInstance("AES");
1194            kg.init(128);
1195            SecretKey sk = kg.generateKey();
1196
1197            // Wrap it
1198            c.init(Cipher.WRAP_MODE, encryptKey, encryptSpec);
1199            byte[] cipherText = c.wrap(sk);
1200
1201            // Unwrap it
1202            c.init(Cipher.UNWRAP_MODE, getDecryptKey(algorithm), decryptSpec);
1203            Key decryptedKey = c.unwrap(cipherText, sk.getAlgorithm(), Cipher.SECRET_KEY);
1204
1205            assertEquals(cipherID
1206                    + " sk.getAlgorithm()=" + sk.getAlgorithm()
1207                    + " decryptedKey.getAlgorithm()=" + decryptedKey.getAlgorithm()
1208                    + " encryptKey.getEncoded()=" + Arrays.toString(sk.getEncoded())
1209                    + " decryptedKey.getEncoded()=" + Arrays.toString(decryptedKey.getEncoded()),
1210                    sk, decryptedKey);
1211        }
1212
1213        if (!isOnlyWrappingAlgorithm(algorithm)) {
1214            c.init(Cipher.ENCRYPT_MODE, encryptKey, encryptSpec);
1215            byte[] cipherText = c.doFinal(getActualPlainText(algorithm));
1216            byte[] cipherText2 = c.doFinal(getActualPlainText(algorithm));
1217            assertEquals(cipherID,
1218                         Arrays.toString(cipherText),
1219                         Arrays.toString(cipherText2));
1220            c.init(Cipher.DECRYPT_MODE, getDecryptKey(algorithm), decryptSpec);
1221            byte[] decryptedPlainText = c.doFinal(cipherText);
1222            assertEquals(cipherID,
1223                         Arrays.toString(getExpectedPlainText(algorithm, providerName)),
1224                         Arrays.toString(decryptedPlainText));
1225            byte[] decryptedPlainText2 = c.doFinal(cipherText);
1226            assertEquals(cipherID,
1227                         Arrays.toString(decryptedPlainText),
1228                         Arrays.toString(decryptedPlainText2));
1229        }
1230    }
1231
1232    /**
1233     * Try various .init(...) calls with null parameters to make sure it is
1234     * handled.
1235     */
1236    private void test_Cipher_init_NullParameters(Cipher c, int encryptMode, Key encryptKey)
1237            throws Exception {
1238        try {
1239            c.init(encryptMode, encryptKey, (AlgorithmParameterSpec) null);
1240        } catch (InvalidAlgorithmParameterException e) {
1241            if (!isPBE(c.getAlgorithm())) {
1242                throw e;
1243            }
1244        }
1245
1246        try {
1247            c.init(encryptMode, encryptKey, (AlgorithmParameterSpec) null, (SecureRandom) null);
1248        } catch (InvalidAlgorithmParameterException e) {
1249            if (!isPBE(c.getAlgorithm())) {
1250                throw e;
1251            }
1252        }
1253
1254        try {
1255            c.init(encryptMode, encryptKey, (AlgorithmParameters) null);
1256        } catch (InvalidAlgorithmParameterException e) {
1257            if (!isPBE(c.getAlgorithm())) {
1258                throw e;
1259            }
1260        }
1261
1262        try {
1263            c.init(encryptMode, encryptKey, (AlgorithmParameters) null, (SecureRandom) null);
1264        } catch (InvalidAlgorithmParameterException e) {
1265            if (!isPBE(c.getAlgorithm())) {
1266                throw e;
1267            }
1268        }
1269    }
1270
1271    public void testInputPKCS1Padding() throws Exception {
1272        for (String provider : RSA_PROVIDERS) {
1273            testInputPKCS1Padding(provider);
1274        }
1275    }
1276
1277    private void testInputPKCS1Padding(String provider) throws Exception {
1278        testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_01_PADDED_PLAIN_TEXT, getEncryptKey("RSA"), getDecryptKey("RSA"));
1279        try {
1280            testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_02_PADDED_PLAIN_TEXT, getEncryptKey("RSA"), getDecryptKey("RSA"));
1281            fail();
1282        } catch (BadPaddingException expected) {
1283        }
1284        try {
1285            testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_01_PADDED_PLAIN_TEXT, getDecryptKey("RSA"), getEncryptKey("RSA"));
1286            fail();
1287        } catch (BadPaddingException expected) {
1288        }
1289        testInputPKCS1Padding(provider, PKCS1_BLOCK_TYPE_02_PADDED_PLAIN_TEXT, getDecryptKey("RSA"), getEncryptKey("RSA"));
1290    }
1291
1292    private void testInputPKCS1Padding(String provider, byte[] prePaddedPlainText, Key encryptKey, Key decryptKey) throws Exception {
1293        Cipher encryptCipher = Cipher.getInstance("RSA/ECB/NoPadding", provider);
1294        encryptCipher.init(Cipher.ENCRYPT_MODE, encryptKey);
1295        byte[] cipherText = encryptCipher.doFinal(prePaddedPlainText);
1296        Cipher decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
1297        decryptCipher.init(Cipher.DECRYPT_MODE, decryptKey);
1298        byte[] plainText = decryptCipher.doFinal(cipherText);
1299        assertEquals(Arrays.toString(ORIGINAL_PLAIN_TEXT),
1300                     Arrays.toString(plainText));
1301    }
1302
1303    public void testOutputPKCS1Padding() throws Exception {
1304        for (String provider : RSA_PROVIDERS) {
1305            testOutputPKCS1Padding(provider);
1306        }
1307    }
1308
1309    private void testOutputPKCS1Padding(String provider) throws Exception {
1310       testOutputPKCS1Padding(provider, (byte) 1, getEncryptKey("RSA"), getDecryptKey("RSA"));
1311       testOutputPKCS1Padding(provider, (byte) 2, getDecryptKey("RSA"), getEncryptKey("RSA"));
1312    }
1313
1314    private void testOutputPKCS1Padding(String provider, byte expectedBlockType, Key encryptKey, Key decryptKey) throws Exception {
1315        Cipher encryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
1316        encryptCipher.init(Cipher.ENCRYPT_MODE, encryptKey);
1317        byte[] cipherText = encryptCipher.doFinal(ORIGINAL_PLAIN_TEXT);
1318        Cipher decryptCipher = Cipher.getInstance("RSA/ECB/NoPadding", provider);
1319        decryptCipher.init(Cipher.DECRYPT_MODE, decryptKey);
1320        byte[] plainText = decryptCipher.doFinal(cipherText);
1321        assertPadding(provider, expectedBlockType, ORIGINAL_PLAIN_TEXT, plainText);
1322    }
1323
1324    private void assertPadding(String provider, byte expectedBlockType, byte[] expectedData, byte[] actualDataWithPadding) {
1325        assertNotNull(provider, actualDataWithPadding);
1326        int expectedOutputSize = getExpectedOutputSize("RSA", Cipher.DECRYPT_MODE, provider);
1327        assertEquals(provider, expectedOutputSize, actualDataWithPadding.length);
1328        int expectedBlockTypeOffset;
1329        if (provider.equals("BC")) {
1330            // BC strips the leading 0 for us on decrypt even when NoPadding is specified...
1331            expectedBlockTypeOffset = 0;
1332        } else {
1333            expectedBlockTypeOffset = 1;
1334            assertEquals(provider, 0, actualDataWithPadding[0]);
1335        }
1336        byte actualBlockType = actualDataWithPadding[expectedBlockTypeOffset];
1337        assertEquals(provider, expectedBlockType, actualBlockType);
1338        int actualDataOffset = actualDataWithPadding.length - expectedData.length;
1339        if (actualBlockType == 1) {
1340            int expectedDataOffset = expectedBlockTypeOffset + 1;
1341            for (int i = expectedDataOffset; i < actualDataOffset - 1; i++) {
1342                assertEquals(provider, (byte) 0xFF, actualDataWithPadding[i]);
1343            }
1344        }
1345        assertEquals(provider, 0x00, actualDataWithPadding[actualDataOffset-1]);
1346        byte[] actualData = new byte[expectedData.length];
1347        System.arraycopy(actualDataWithPadding, actualDataOffset, actualData, 0, actualData.length);
1348        assertEquals(provider, Arrays.toString(expectedData), Arrays.toString(actualData));
1349    }
1350
1351    public void testCipherInitWithCertificate () throws Exception {
1352        // no key usage specified, everything is fine
1353        assertCipherInitWithKeyUsage(0,                         true,  true, true,  true);
1354
1355        // common case is that encrypt/wrap is prohibited when special usage is specified
1356        assertCipherInitWithKeyUsage(KeyUsage.digitalSignature, false, true, false, true);
1357        assertCipherInitWithKeyUsage(KeyUsage.nonRepudiation,   false, true, false, true);
1358        assertCipherInitWithKeyUsage(KeyUsage.keyAgreement,     false, true, false, true);
1359        assertCipherInitWithKeyUsage(KeyUsage.keyCertSign,      false, true, false, true);
1360        assertCipherInitWithKeyUsage(KeyUsage.cRLSign,          false, true, false, true);
1361
1362        // Note they encipherOnly/decipherOnly don't have to do with
1363        // ENCRYPT_MODE or DECRYPT_MODE, but restrict usage relative
1364        // to keyAgreement. There is not a *_MODE option that
1365        // corresponds to this in Cipher, the RI does not enforce
1366        // anything in Cipher.
1367        // http://code.google.com/p/android/issues/detail?id=12955
1368        assertCipherInitWithKeyUsage(KeyUsage.encipherOnly,     false, true, false, true);
1369        assertCipherInitWithKeyUsage(KeyUsage.decipherOnly,     false, true, false, true);
1370        assertCipherInitWithKeyUsage(KeyUsage.keyAgreement | KeyUsage.encipherOnly,
1371                                                                false, true, false, true);
1372        assertCipherInitWithKeyUsage(KeyUsage.keyAgreement | KeyUsage.decipherOnly,
1373                                                                false, true, false, true);
1374
1375        // except when wrapping a key is specifically allowed or
1376        assertCipherInitWithKeyUsage(KeyUsage.keyEncipherment,  false, true, true,  true);
1377        // except when wrapping data encryption is specifically allowed
1378        assertCipherInitWithKeyUsage(KeyUsage.dataEncipherment, true,  true, false, true);
1379    }
1380
1381    private void assertCipherInitWithKeyUsage (int keyUsage,
1382                                               boolean allowEncrypt,
1383                                               boolean allowDecrypt,
1384                                               boolean allowWrap,
1385                                               boolean allowUnwrap) throws Exception {
1386        Certificate certificate = certificateWithKeyUsage(keyUsage);
1387        assertCipherInitWithKeyUsage(certificate, allowEncrypt, Cipher.ENCRYPT_MODE);
1388        assertCipherInitWithKeyUsage(certificate, allowDecrypt, Cipher.DECRYPT_MODE);
1389        assertCipherInitWithKeyUsage(certificate, allowWrap,    Cipher.WRAP_MODE);
1390        assertCipherInitWithKeyUsage(certificate, allowUnwrap,  Cipher.UNWRAP_MODE);
1391    }
1392
1393    private void assertCipherInitWithKeyUsage(Certificate certificate,
1394                                              boolean allowMode,
1395                                              int mode) throws Exception {
1396        Cipher cipher = Cipher.getInstance("RSA");
1397        if (allowMode) {
1398            cipher.init(mode, certificate);
1399        } else {
1400            try {
1401                cipher.init(mode, certificate);
1402                String modeString;
1403                switch (mode) {
1404                    case Cipher.ENCRYPT_MODE:
1405                        modeString = "ENCRYPT_MODE";
1406                        break;
1407                    case Cipher.DECRYPT_MODE:
1408                        modeString = "DECRYPT_MODE";
1409                        break;
1410                    case Cipher.WRAP_MODE:
1411                        modeString = "WRAP_MODE";
1412                        break;
1413                    case Cipher.UNWRAP_MODE:
1414                        modeString = "UNWRAP_MODE";
1415                        break;
1416                    default:
1417                        throw new AssertionError("Unknown Cipher.*_MODE " + mode);
1418                }
1419                fail("Should have had InvalidKeyException for " + modeString
1420                     + " for " + certificate);
1421            } catch (InvalidKeyException expected) {
1422            }
1423        }
1424    }
1425
1426    private Certificate certificateWithKeyUsage(int keyUsage) throws Exception {
1427        // note the rare usage of non-zero keyUsage
1428        return new TestKeyStore.Builder()
1429                .aliasPrefix("rsa-dsa-ec")
1430                .keyUsage(keyUsage)
1431                .build()
1432                .getPrivateKey("RSA", "RSA").getCertificate();
1433    }
1434
1435    /*
1436     * Test vectors generated with this private key:
1437     *
1438     * -----BEGIN RSA PRIVATE KEY-----
1439     * MIIEpAIBAAKCAQEA4Ec+irjyKE/rnnQv+XSPoRjtmGM8kvUq63ouvg075gMpvnZq
1440     * 0Q62pRXQ0s/ZvqeTDwwwZTeJn3lYzT6FsB+IGFJNMSWEqUslHjYltUFB7b/uGYgI
1441     * 4buX/Hy0m56qr2jpyY19DtxTu8D6ADQ1bWMF+7zDxwAUBThqu8hzyw8+90JfPTPf
1442     * ezFa4DbSoLZq/UdQOxab8247UWJRW3Ff2oPeryxYrrmr+zCXw8yd2dvl7ylsF2E5
1443     * Ao6KZx5jBW1F9AGI0sQTNJCEXeUsJTTpxrJHjAe9rpKII7YtBmx3cPn2Pz26JH9T
1444     * CER0e+eqqF2FO4vSRKzsPePImrRkU6tNJMOsaQIDAQABAoIBADd4R3al8XaY9ayW
1445     * DfuDobZ1ZOZIvQWXz4q4CHGG8macJ6nsvdSA8Bl6gNBzCebGqW+SUzHlf4tKxvTU
1446     * XtpFojJpwJ/EKMB6Tm7fc4oV3sl/q9Lyu0ehTyDqcvz+TDbgGtp3vRN82NTaELsW
1447     * LpSkZilx8XX5hfoYjwVsuX7igW9Dq503R2Ekhs2owWGWwwgYqZXshdOEZ3kSZ7O/
1448     * IfJzcQppJYYldoQcW2cSwS1L0govMpmtt8E12l6VFavadufK8qO+gFUdBzt4vxFi
1449     * xIrSt/R0OgI47k0lL31efmUzzK5kzLOTYAdaL9HgNOw65c6cQIzL8OJeQRQCFoez
1450     * 3UdUroECgYEA9UGIS8Nzeyki1BGe9F4t7izUy7dfRVBaFXqlAJ+Zxzot8HJKxGAk
1451     * MGMy6omBd2NFRl3G3x4KbxQK/ztzluaomUrF2qloc0cv43dJ0U6z4HXmKdvrNYMz
1452     * im82SdCiZUp6Qv2atr+krE1IHTkLsimwZL3DEcwb4bYxidp8QM3s8rECgYEA6hp0
1453     * LduIHO23KIyH442GjdekCdFaQ/RF1Td6C1cx3b/KLa8oqOE81cCvzsM0fXSjniNa
1454     * PNljPydN4rlPkt9DgzkR2enxz1jyfeLgj/RZZMcg0+whOdx8r8kSlTzeyy81Wi4s
1455     * NaUPrXVMs7IxZkJLo7bjESoriYw4xcFe2yOGkzkCgYBRgo8exv2ZYCmQG68dfjN7
1456     * pfCvJ+mE6tiVrOYr199O5FoiQInyzBUa880XP84EdLywTzhqLNzA4ANrokGfVFeS
1457     * YtRxAL6TGYSj76Bb7PFBV03AebOpXEqD5sQ/MhTW3zLVEt4ZgIXlMeYWuD/X3Z0f
1458     * TiYHwzM9B8VdEH0dOJNYcQKBgQDbT7UPUN6O21P/NMgJMYigUShn2izKBIl3WeWH
1459     * wkQBDa+GZNWegIPRbBZHiTAfZ6nweAYNg0oq29NnV1toqKhCwrAqibPzH8zsiiL+
1460     * OVeVxcbHQitOXXSh6ajzDndZufwtY5wfFWc+hOk6XvFQb0MVODw41Fy9GxQEj0ch
1461     * 3IIyYQKBgQDYEUWTr0FfthLb8ZI3ENVNB0hiBadqO0MZSWjA3/HxHvD2GkozfV/T
1462     * dBu8lkDkR7i2tsR8OsEgQ1fTsMVbqShr2nP2KSlvX6kUbYl2NX08dR51FIaWpAt0
1463     * aFyCzjCQLWOdck/yTV4ulAfuNO3tLjtN9lqpvP623yjQe6aQPxZXaA==
1464     * -----END RSA PRIVATE KEY-----
1465     *
1466     */
1467
1468    private static final BigInteger RSA_2048_modulus = new BigInteger(new byte[] {
1469        (byte) 0x00, (byte) 0xe0, (byte) 0x47, (byte) 0x3e, (byte) 0x8a, (byte) 0xb8, (byte) 0xf2, (byte) 0x28,
1470        (byte) 0x4f, (byte) 0xeb, (byte) 0x9e, (byte) 0x74, (byte) 0x2f, (byte) 0xf9, (byte) 0x74, (byte) 0x8f,
1471        (byte) 0xa1, (byte) 0x18, (byte) 0xed, (byte) 0x98, (byte) 0x63, (byte) 0x3c, (byte) 0x92, (byte) 0xf5,
1472        (byte) 0x2a, (byte) 0xeb, (byte) 0x7a, (byte) 0x2e, (byte) 0xbe, (byte) 0x0d, (byte) 0x3b, (byte) 0xe6,
1473        (byte) 0x03, (byte) 0x29, (byte) 0xbe, (byte) 0x76, (byte) 0x6a, (byte) 0xd1, (byte) 0x0e, (byte) 0xb6,
1474        (byte) 0xa5, (byte) 0x15, (byte) 0xd0, (byte) 0xd2, (byte) 0xcf, (byte) 0xd9, (byte) 0xbe, (byte) 0xa7,
1475        (byte) 0x93, (byte) 0x0f, (byte) 0x0c, (byte) 0x30, (byte) 0x65, (byte) 0x37, (byte) 0x89, (byte) 0x9f,
1476        (byte) 0x79, (byte) 0x58, (byte) 0xcd, (byte) 0x3e, (byte) 0x85, (byte) 0xb0, (byte) 0x1f, (byte) 0x88,
1477        (byte) 0x18, (byte) 0x52, (byte) 0x4d, (byte) 0x31, (byte) 0x25, (byte) 0x84, (byte) 0xa9, (byte) 0x4b,
1478        (byte) 0x25, (byte) 0x1e, (byte) 0x36, (byte) 0x25, (byte) 0xb5, (byte) 0x41, (byte) 0x41, (byte) 0xed,
1479        (byte) 0xbf, (byte) 0xee, (byte) 0x19, (byte) 0x88, (byte) 0x08, (byte) 0xe1, (byte) 0xbb, (byte) 0x97,
1480        (byte) 0xfc, (byte) 0x7c, (byte) 0xb4, (byte) 0x9b, (byte) 0x9e, (byte) 0xaa, (byte) 0xaf, (byte) 0x68,
1481        (byte) 0xe9, (byte) 0xc9, (byte) 0x8d, (byte) 0x7d, (byte) 0x0e, (byte) 0xdc, (byte) 0x53, (byte) 0xbb,
1482        (byte) 0xc0, (byte) 0xfa, (byte) 0x00, (byte) 0x34, (byte) 0x35, (byte) 0x6d, (byte) 0x63, (byte) 0x05,
1483        (byte) 0xfb, (byte) 0xbc, (byte) 0xc3, (byte) 0xc7, (byte) 0x00, (byte) 0x14, (byte) 0x05, (byte) 0x38,
1484        (byte) 0x6a, (byte) 0xbb, (byte) 0xc8, (byte) 0x73, (byte) 0xcb, (byte) 0x0f, (byte) 0x3e, (byte) 0xf7,
1485        (byte) 0x42, (byte) 0x5f, (byte) 0x3d, (byte) 0x33, (byte) 0xdf, (byte) 0x7b, (byte) 0x31, (byte) 0x5a,
1486        (byte) 0xe0, (byte) 0x36, (byte) 0xd2, (byte) 0xa0, (byte) 0xb6, (byte) 0x6a, (byte) 0xfd, (byte) 0x47,
1487        (byte) 0x50, (byte) 0x3b, (byte) 0x16, (byte) 0x9b, (byte) 0xf3, (byte) 0x6e, (byte) 0x3b, (byte) 0x51,
1488        (byte) 0x62, (byte) 0x51, (byte) 0x5b, (byte) 0x71, (byte) 0x5f, (byte) 0xda, (byte) 0x83, (byte) 0xde,
1489        (byte) 0xaf, (byte) 0x2c, (byte) 0x58, (byte) 0xae, (byte) 0xb9, (byte) 0xab, (byte) 0xfb, (byte) 0x30,
1490        (byte) 0x97, (byte) 0xc3, (byte) 0xcc, (byte) 0x9d, (byte) 0xd9, (byte) 0xdb, (byte) 0xe5, (byte) 0xef,
1491        (byte) 0x29, (byte) 0x6c, (byte) 0x17, (byte) 0x61, (byte) 0x39, (byte) 0x02, (byte) 0x8e, (byte) 0x8a,
1492        (byte) 0x67, (byte) 0x1e, (byte) 0x63, (byte) 0x05, (byte) 0x6d, (byte) 0x45, (byte) 0xf4, (byte) 0x01,
1493        (byte) 0x88, (byte) 0xd2, (byte) 0xc4, (byte) 0x13, (byte) 0x34, (byte) 0x90, (byte) 0x84, (byte) 0x5d,
1494        (byte) 0xe5, (byte) 0x2c, (byte) 0x25, (byte) 0x34, (byte) 0xe9, (byte) 0xc6, (byte) 0xb2, (byte) 0x47,
1495        (byte) 0x8c, (byte) 0x07, (byte) 0xbd, (byte) 0xae, (byte) 0x92, (byte) 0x88, (byte) 0x23, (byte) 0xb6,
1496        (byte) 0x2d, (byte) 0x06, (byte) 0x6c, (byte) 0x77, (byte) 0x70, (byte) 0xf9, (byte) 0xf6, (byte) 0x3f,
1497        (byte) 0x3d, (byte) 0xba, (byte) 0x24, (byte) 0x7f, (byte) 0x53, (byte) 0x08, (byte) 0x44, (byte) 0x74,
1498        (byte) 0x7b, (byte) 0xe7, (byte) 0xaa, (byte) 0xa8, (byte) 0x5d, (byte) 0x85, (byte) 0x3b, (byte) 0x8b,
1499        (byte) 0xd2, (byte) 0x44, (byte) 0xac, (byte) 0xec, (byte) 0x3d, (byte) 0xe3, (byte) 0xc8, (byte) 0x9a,
1500        (byte) 0xb4, (byte) 0x64, (byte) 0x53, (byte) 0xab, (byte) 0x4d, (byte) 0x24, (byte) 0xc3, (byte) 0xac,
1501        (byte) 0x69,
1502    });
1503
1504    private static final BigInteger RSA_2048_privateExponent = new BigInteger(new byte[] {
1505        (byte) 0x37, (byte) 0x78, (byte) 0x47, (byte) 0x76, (byte) 0xa5, (byte) 0xf1, (byte) 0x76, (byte) 0x98,
1506        (byte) 0xf5, (byte) 0xac, (byte) 0x96, (byte) 0x0d, (byte) 0xfb, (byte) 0x83, (byte) 0xa1, (byte) 0xb6,
1507        (byte) 0x75, (byte) 0x64, (byte) 0xe6, (byte) 0x48, (byte) 0xbd, (byte) 0x05, (byte) 0x97, (byte) 0xcf,
1508        (byte) 0x8a, (byte) 0xb8, (byte) 0x08, (byte) 0x71, (byte) 0x86, (byte) 0xf2, (byte) 0x66, (byte) 0x9c,
1509        (byte) 0x27, (byte) 0xa9, (byte) 0xec, (byte) 0xbd, (byte) 0xd4, (byte) 0x80, (byte) 0xf0, (byte) 0x19,
1510        (byte) 0x7a, (byte) 0x80, (byte) 0xd0, (byte) 0x73, (byte) 0x09, (byte) 0xe6, (byte) 0xc6, (byte) 0xa9,
1511        (byte) 0x6f, (byte) 0x92, (byte) 0x53, (byte) 0x31, (byte) 0xe5, (byte) 0x7f, (byte) 0x8b, (byte) 0x4a,
1512        (byte) 0xc6, (byte) 0xf4, (byte) 0xd4, (byte) 0x5e, (byte) 0xda, (byte) 0x45, (byte) 0xa2, (byte) 0x32,
1513        (byte) 0x69, (byte) 0xc0, (byte) 0x9f, (byte) 0xc4, (byte) 0x28, (byte) 0xc0, (byte) 0x7a, (byte) 0x4e,
1514        (byte) 0x6e, (byte) 0xdf, (byte) 0x73, (byte) 0x8a, (byte) 0x15, (byte) 0xde, (byte) 0xc9, (byte) 0x7f,
1515        (byte) 0xab, (byte) 0xd2, (byte) 0xf2, (byte) 0xbb, (byte) 0x47, (byte) 0xa1, (byte) 0x4f, (byte) 0x20,
1516        (byte) 0xea, (byte) 0x72, (byte) 0xfc, (byte) 0xfe, (byte) 0x4c, (byte) 0x36, (byte) 0xe0, (byte) 0x1a,
1517        (byte) 0xda, (byte) 0x77, (byte) 0xbd, (byte) 0x13, (byte) 0x7c, (byte) 0xd8, (byte) 0xd4, (byte) 0xda,
1518        (byte) 0x10, (byte) 0xbb, (byte) 0x16, (byte) 0x2e, (byte) 0x94, (byte) 0xa4, (byte) 0x66, (byte) 0x29,
1519        (byte) 0x71, (byte) 0xf1, (byte) 0x75, (byte) 0xf9, (byte) 0x85, (byte) 0xfa, (byte) 0x18, (byte) 0x8f,
1520        (byte) 0x05, (byte) 0x6c, (byte) 0xb9, (byte) 0x7e, (byte) 0xe2, (byte) 0x81, (byte) 0x6f, (byte) 0x43,
1521        (byte) 0xab, (byte) 0x9d, (byte) 0x37, (byte) 0x47, (byte) 0x61, (byte) 0x24, (byte) 0x86, (byte) 0xcd,
1522        (byte) 0xa8, (byte) 0xc1, (byte) 0x61, (byte) 0x96, (byte) 0xc3, (byte) 0x08, (byte) 0x18, (byte) 0xa9,
1523        (byte) 0x95, (byte) 0xec, (byte) 0x85, (byte) 0xd3, (byte) 0x84, (byte) 0x67, (byte) 0x79, (byte) 0x12,
1524        (byte) 0x67, (byte) 0xb3, (byte) 0xbf, (byte) 0x21, (byte) 0xf2, (byte) 0x73, (byte) 0x71, (byte) 0x0a,
1525        (byte) 0x69, (byte) 0x25, (byte) 0x86, (byte) 0x25, (byte) 0x76, (byte) 0x84, (byte) 0x1c, (byte) 0x5b,
1526        (byte) 0x67, (byte) 0x12, (byte) 0xc1, (byte) 0x2d, (byte) 0x4b, (byte) 0xd2, (byte) 0x0a, (byte) 0x2f,
1527        (byte) 0x32, (byte) 0x99, (byte) 0xad, (byte) 0xb7, (byte) 0xc1, (byte) 0x35, (byte) 0xda, (byte) 0x5e,
1528        (byte) 0x95, (byte) 0x15, (byte) 0xab, (byte) 0xda, (byte) 0x76, (byte) 0xe7, (byte) 0xca, (byte) 0xf2,
1529        (byte) 0xa3, (byte) 0xbe, (byte) 0x80, (byte) 0x55, (byte) 0x1d, (byte) 0x07, (byte) 0x3b, (byte) 0x78,
1530        (byte) 0xbf, (byte) 0x11, (byte) 0x62, (byte) 0xc4, (byte) 0x8a, (byte) 0xd2, (byte) 0xb7, (byte) 0xf4,
1531        (byte) 0x74, (byte) 0x3a, (byte) 0x02, (byte) 0x38, (byte) 0xee, (byte) 0x4d, (byte) 0x25, (byte) 0x2f,
1532        (byte) 0x7d, (byte) 0x5e, (byte) 0x7e, (byte) 0x65, (byte) 0x33, (byte) 0xcc, (byte) 0xae, (byte) 0x64,
1533        (byte) 0xcc, (byte) 0xb3, (byte) 0x93, (byte) 0x60, (byte) 0x07, (byte) 0x5a, (byte) 0x2f, (byte) 0xd1,
1534        (byte) 0xe0, (byte) 0x34, (byte) 0xec, (byte) 0x3a, (byte) 0xe5, (byte) 0xce, (byte) 0x9c, (byte) 0x40,
1535        (byte) 0x8c, (byte) 0xcb, (byte) 0xf0, (byte) 0xe2, (byte) 0x5e, (byte) 0x41, (byte) 0x14, (byte) 0x02,
1536        (byte) 0x16, (byte) 0x87, (byte) 0xb3, (byte) 0xdd, (byte) 0x47, (byte) 0x54, (byte) 0xae, (byte) 0x81,
1537    });
1538
1539    private static final BigInteger RSA_2048_publicExponent = new BigInteger(new byte[] {
1540        (byte) 0x01, (byte) 0x00, (byte) 0x01,
1541    });
1542
1543    private static final BigInteger RSA_2048_primeP = new BigInteger(new byte[] {
1544        (byte) 0x00, (byte) 0xf5, (byte) 0x41, (byte) 0x88, (byte) 0x4b, (byte) 0xc3, (byte) 0x73, (byte) 0x7b,
1545        (byte) 0x29, (byte) 0x22, (byte) 0xd4, (byte) 0x11, (byte) 0x9e, (byte) 0xf4, (byte) 0x5e, (byte) 0x2d,
1546        (byte) 0xee, (byte) 0x2c, (byte) 0xd4, (byte) 0xcb, (byte) 0xb7, (byte) 0x5f, (byte) 0x45, (byte) 0x50,
1547        (byte) 0x5a, (byte) 0x15, (byte) 0x7a, (byte) 0xa5, (byte) 0x00, (byte) 0x9f, (byte) 0x99, (byte) 0xc7,
1548        (byte) 0x3a, (byte) 0x2d, (byte) 0xf0, (byte) 0x72, (byte) 0x4a, (byte) 0xc4, (byte) 0x60, (byte) 0x24,
1549        (byte) 0x30, (byte) 0x63, (byte) 0x32, (byte) 0xea, (byte) 0x89, (byte) 0x81, (byte) 0x77, (byte) 0x63,
1550        (byte) 0x45, (byte) 0x46, (byte) 0x5d, (byte) 0xc6, (byte) 0xdf, (byte) 0x1e, (byte) 0x0a, (byte) 0x6f,
1551        (byte) 0x14, (byte) 0x0a, (byte) 0xff, (byte) 0x3b, (byte) 0x73, (byte) 0x96, (byte) 0xe6, (byte) 0xa8,
1552        (byte) 0x99, (byte) 0x4a, (byte) 0xc5, (byte) 0xda, (byte) 0xa9, (byte) 0x68, (byte) 0x73, (byte) 0x47,
1553        (byte) 0x2f, (byte) 0xe3, (byte) 0x77, (byte) 0x49, (byte) 0xd1, (byte) 0x4e, (byte) 0xb3, (byte) 0xe0,
1554        (byte) 0x75, (byte) 0xe6, (byte) 0x29, (byte) 0xdb, (byte) 0xeb, (byte) 0x35, (byte) 0x83, (byte) 0x33,
1555        (byte) 0x8a, (byte) 0x6f, (byte) 0x36, (byte) 0x49, (byte) 0xd0, (byte) 0xa2, (byte) 0x65, (byte) 0x4a,
1556        (byte) 0x7a, (byte) 0x42, (byte) 0xfd, (byte) 0x9a, (byte) 0xb6, (byte) 0xbf, (byte) 0xa4, (byte) 0xac,
1557        (byte) 0x4d, (byte) 0x48, (byte) 0x1d, (byte) 0x39, (byte) 0x0b, (byte) 0xb2, (byte) 0x29, (byte) 0xb0,
1558        (byte) 0x64, (byte) 0xbd, (byte) 0xc3, (byte) 0x11, (byte) 0xcc, (byte) 0x1b, (byte) 0xe1, (byte) 0xb6,
1559        (byte) 0x31, (byte) 0x89, (byte) 0xda, (byte) 0x7c, (byte) 0x40, (byte) 0xcd, (byte) 0xec, (byte) 0xf2,
1560        (byte) 0xb1,
1561    });
1562
1563    private static final BigInteger RSA_2048_primeQ = new BigInteger(new byte[] {
1564        (byte) 0x00, (byte) 0xea, (byte) 0x1a, (byte) 0x74, (byte) 0x2d, (byte) 0xdb, (byte) 0x88, (byte) 0x1c,
1565        (byte) 0xed, (byte) 0xb7, (byte) 0x28, (byte) 0x8c, (byte) 0x87, (byte) 0xe3, (byte) 0x8d, (byte) 0x86,
1566        (byte) 0x8d, (byte) 0xd7, (byte) 0xa4, (byte) 0x09, (byte) 0xd1, (byte) 0x5a, (byte) 0x43, (byte) 0xf4,
1567        (byte) 0x45, (byte) 0xd5, (byte) 0x37, (byte) 0x7a, (byte) 0x0b, (byte) 0x57, (byte) 0x31, (byte) 0xdd,
1568        (byte) 0xbf, (byte) 0xca, (byte) 0x2d, (byte) 0xaf, (byte) 0x28, (byte) 0xa8, (byte) 0xe1, (byte) 0x3c,
1569        (byte) 0xd5, (byte) 0xc0, (byte) 0xaf, (byte) 0xce, (byte) 0xc3, (byte) 0x34, (byte) 0x7d, (byte) 0x74,
1570        (byte) 0xa3, (byte) 0x9e, (byte) 0x23, (byte) 0x5a, (byte) 0x3c, (byte) 0xd9, (byte) 0x63, (byte) 0x3f,
1571        (byte) 0x27, (byte) 0x4d, (byte) 0xe2, (byte) 0xb9, (byte) 0x4f, (byte) 0x92, (byte) 0xdf, (byte) 0x43,
1572        (byte) 0x83, (byte) 0x39, (byte) 0x11, (byte) 0xd9, (byte) 0xe9, (byte) 0xf1, (byte) 0xcf, (byte) 0x58,
1573        (byte) 0xf2, (byte) 0x7d, (byte) 0xe2, (byte) 0xe0, (byte) 0x8f, (byte) 0xf4, (byte) 0x59, (byte) 0x64,
1574        (byte) 0xc7, (byte) 0x20, (byte) 0xd3, (byte) 0xec, (byte) 0x21, (byte) 0x39, (byte) 0xdc, (byte) 0x7c,
1575        (byte) 0xaf, (byte) 0xc9, (byte) 0x12, (byte) 0x95, (byte) 0x3c, (byte) 0xde, (byte) 0xcb, (byte) 0x2f,
1576        (byte) 0x35, (byte) 0x5a, (byte) 0x2e, (byte) 0x2c, (byte) 0x35, (byte) 0xa5, (byte) 0x0f, (byte) 0xad,
1577        (byte) 0x75, (byte) 0x4c, (byte) 0xb3, (byte) 0xb2, (byte) 0x31, (byte) 0x66, (byte) 0x42, (byte) 0x4b,
1578        (byte) 0xa3, (byte) 0xb6, (byte) 0xe3, (byte) 0x11, (byte) 0x2a, (byte) 0x2b, (byte) 0x89, (byte) 0x8c,
1579        (byte) 0x38, (byte) 0xc5, (byte) 0xc1, (byte) 0x5e, (byte) 0xdb, (byte) 0x23, (byte) 0x86, (byte) 0x93,
1580        (byte) 0x39,
1581    });
1582
1583    /**
1584     * Test data is PKCS#1 padded "Android.\n" which can be generated by:
1585     * echo "Android." | openssl rsautl -inkey rsa.key -sign | openssl rsautl -inkey rsa.key -raw -verify | recode ../x1
1586     */
1587    private static final byte[] RSA_2048_Vector1 = new byte[] {
1588        (byte) 0x00, (byte) 0x01, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1589        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1590        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1591        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1592        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1593        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1594        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1595        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1596        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1597        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1598        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1599        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1600        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1601        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1602        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1603        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1604        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1605        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1606        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1607        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1608        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1609        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1610        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1611        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1612        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1613        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1614        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1615        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1616        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1617        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1618        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1619        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1620        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1621        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1622        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1623        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1624        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1625        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1626        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1627        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1628        (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
1629        (byte) 0x00, (byte) 0x41, (byte) 0x6E, (byte) 0x64, (byte) 0x72, (byte) 0x6F,
1630        (byte) 0x69, (byte) 0x64, (byte) 0x2E, (byte) 0x0A,
1631    };
1632
1633    /**
1634     * This vector is simply "Android.\n" which is too short.
1635     */
1636    private static final byte[] TooShort_Vector = new byte[] {
1637        (byte) 0x41, (byte) 0x6E, (byte) 0x64, (byte) 0x72, (byte) 0x6F, (byte) 0x69,
1638        (byte) 0x64, (byte) 0x2E, (byte) 0x0A,
1639    };
1640
1641    /**
1642     * This vector is simply "Android.\n" padded with zeros.
1643     */
1644    private static final byte[] TooShort_Vector_Zero_Padded = new byte[] {
1645        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1646        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1647        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1648        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1649        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1650        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1651        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1652        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1653        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1654        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1655        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1656        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1657        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1658        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1659        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1660        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1661        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1662        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1663        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1664        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1665        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1666        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1667        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1668        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1669        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1670        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1671        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1672        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1673        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1674        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1675        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1676        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1677        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1678        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1679        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1680        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1681        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1682        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1683        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1684        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1685        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
1686        (byte) 0x00, (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f,
1687        (byte) 0x69, (byte) 0x64, (byte) 0x2e, (byte) 0x0a,
1688    };
1689
1690    /**
1691     * openssl rsautl -raw -sign -inkey rsa.key | recode ../x1 | sed 's/0x/(byte) 0x/g'
1692     */
1693    private static final byte[] RSA_Vector1_Encrypt_Private = new byte[] {
1694        (byte) 0x35, (byte) 0x43, (byte) 0x38, (byte) 0x44, (byte) 0xAD, (byte) 0x3F,
1695        (byte) 0x97, (byte) 0x02, (byte) 0xFB, (byte) 0x59, (byte) 0x1F, (byte) 0x4A,
1696        (byte) 0x2B, (byte) 0xB9, (byte) 0x06, (byte) 0xEC, (byte) 0x66, (byte) 0xE6,
1697        (byte) 0xD2, (byte) 0xC5, (byte) 0x8B, (byte) 0x7B, (byte) 0xE3, (byte) 0x18,
1698        (byte) 0xBF, (byte) 0x07, (byte) 0xD6, (byte) 0x01, (byte) 0xF9, (byte) 0xD9,
1699        (byte) 0x89, (byte) 0xC4, (byte) 0xDB, (byte) 0x00, (byte) 0x68, (byte) 0xFF,
1700        (byte) 0x9B, (byte) 0x43, (byte) 0x90, (byte) 0xF2, (byte) 0xDB, (byte) 0x83,
1701        (byte) 0xF4, (byte) 0x7E, (byte) 0xC6, (byte) 0x81, (byte) 0x01, (byte) 0x3A,
1702        (byte) 0x0B, (byte) 0xE5, (byte) 0xED, (byte) 0x08, (byte) 0x73, (byte) 0x3E,
1703        (byte) 0xE1, (byte) 0x3F, (byte) 0xDF, (byte) 0x1F, (byte) 0x07, (byte) 0x6D,
1704        (byte) 0x22, (byte) 0x8D, (byte) 0xCC, (byte) 0x4E, (byte) 0xE3, (byte) 0x9A,
1705        (byte) 0xBC, (byte) 0xCC, (byte) 0x8F, (byte) 0x9E, (byte) 0x9B, (byte) 0x02,
1706        (byte) 0x48, (byte) 0x00, (byte) 0xAC, (byte) 0x9F, (byte) 0xA4, (byte) 0x8F,
1707        (byte) 0x87, (byte) 0xA1, (byte) 0xA8, (byte) 0xE6, (byte) 0x9D, (byte) 0xCD,
1708        (byte) 0x8B, (byte) 0x05, (byte) 0xE9, (byte) 0xD2, (byte) 0x05, (byte) 0x8D,
1709        (byte) 0xC9, (byte) 0x95, (byte) 0x16, (byte) 0xD0, (byte) 0xCD, (byte) 0x43,
1710        (byte) 0x25, (byte) 0x8A, (byte) 0x11, (byte) 0x46, (byte) 0xD7, (byte) 0x74,
1711        (byte) 0x4C, (byte) 0xCF, (byte) 0x58, (byte) 0xF9, (byte) 0xA1, (byte) 0x30,
1712        (byte) 0x84, (byte) 0x52, (byte) 0xC9, (byte) 0x01, (byte) 0x5F, (byte) 0x24,
1713        (byte) 0x4C, (byte) 0xB1, (byte) 0x9F, (byte) 0x7D, (byte) 0x12, (byte) 0x38,
1714        (byte) 0x27, (byte) 0x0F, (byte) 0x5E, (byte) 0xFF, (byte) 0xE0, (byte) 0x55,
1715        (byte) 0x8B, (byte) 0xA3, (byte) 0xAD, (byte) 0x60, (byte) 0x35, (byte) 0x83,
1716        (byte) 0x58, (byte) 0xAF, (byte) 0x99, (byte) 0xDE, (byte) 0x3F, (byte) 0x5D,
1717        (byte) 0x80, (byte) 0x80, (byte) 0xFF, (byte) 0x9B, (byte) 0xDE, (byte) 0x5C,
1718        (byte) 0xAB, (byte) 0x97, (byte) 0x43, (byte) 0x64, (byte) 0xD9, (byte) 0x9F,
1719        (byte) 0xFB, (byte) 0x67, (byte) 0x65, (byte) 0xA5, (byte) 0x99, (byte) 0xE7,
1720        (byte) 0xE6, (byte) 0xEB, (byte) 0x05, (byte) 0x95, (byte) 0xFC, (byte) 0x46,
1721        (byte) 0x28, (byte) 0x4B, (byte) 0xD8, (byte) 0x8C, (byte) 0xF5, (byte) 0x0A,
1722        (byte) 0xEB, (byte) 0x1F, (byte) 0x30, (byte) 0xEA, (byte) 0xE7, (byte) 0x67,
1723        (byte) 0x11, (byte) 0x25, (byte) 0xF0, (byte) 0x44, (byte) 0x75, (byte) 0x74,
1724        (byte) 0x94, (byte) 0x06, (byte) 0x78, (byte) 0xD0, (byte) 0x21, (byte) 0xF4,
1725        (byte) 0x3F, (byte) 0xC8, (byte) 0xC4, (byte) 0x4A, (byte) 0x57, (byte) 0xBE,
1726        (byte) 0x02, (byte) 0x3C, (byte) 0x93, (byte) 0xF6, (byte) 0x95, (byte) 0xFB,
1727        (byte) 0xD1, (byte) 0x77, (byte) 0x8B, (byte) 0x43, (byte) 0xF0, (byte) 0xB9,
1728        (byte) 0x7D, (byte) 0xE0, (byte) 0x32, (byte) 0xE1, (byte) 0x72, (byte) 0xB5,
1729        (byte) 0x62, (byte) 0x3F, (byte) 0x86, (byte) 0xC3, (byte) 0xD4, (byte) 0x5F,
1730        (byte) 0x5E, (byte) 0x54, (byte) 0x1B, (byte) 0x5B, (byte) 0xE6, (byte) 0x74,
1731        (byte) 0xA1, (byte) 0x0B, (byte) 0xE5, (byte) 0x18, (byte) 0xD2, (byte) 0x4F,
1732        (byte) 0x93, (byte) 0xF3, (byte) 0x09, (byte) 0x58, (byte) 0xCE, (byte) 0xF0,
1733        (byte) 0xA3, (byte) 0x61, (byte) 0xE4, (byte) 0x6E, (byte) 0x46, (byte) 0x45,
1734        (byte) 0x89, (byte) 0x50, (byte) 0xBD, (byte) 0x03, (byte) 0x3F, (byte) 0x38,
1735        (byte) 0xDA, (byte) 0x5D, (byte) 0xD0, (byte) 0x1B, (byte) 0x1F, (byte) 0xB1,
1736        (byte) 0xEE, (byte) 0x89, (byte) 0x59, (byte) 0xC5,
1737    };
1738
1739    private static final byte[] RSA_Vector1_ZeroPadded_Encrypted = new byte[] {
1740        (byte) 0x60, (byte) 0x4a, (byte) 0x12, (byte) 0xa3, (byte) 0xa7, (byte) 0x4a,
1741        (byte) 0xa4, (byte) 0xbf, (byte) 0x6c, (byte) 0x36, (byte) 0xad, (byte) 0x66,
1742        (byte) 0xdf, (byte) 0xce, (byte) 0xf1, (byte) 0xe4, (byte) 0x0f, (byte) 0xd4,
1743        (byte) 0x54, (byte) 0x5f, (byte) 0x03, (byte) 0x15, (byte) 0x4b, (byte) 0x9e,
1744        (byte) 0xeb, (byte) 0xfe, (byte) 0x9e, (byte) 0x24, (byte) 0xce, (byte) 0x8e,
1745        (byte) 0xc3, (byte) 0x36, (byte) 0xa5, (byte) 0x76, (byte) 0xf6, (byte) 0x54,
1746        (byte) 0xb7, (byte) 0x84, (byte) 0x48, (byte) 0x2f, (byte) 0xd4, (byte) 0x45,
1747        (byte) 0x74, (byte) 0x48, (byte) 0x5f, (byte) 0x08, (byte) 0x4e, (byte) 0x9c,
1748        (byte) 0x89, (byte) 0xcc, (byte) 0x34, (byte) 0x40, (byte) 0xb1, (byte) 0x5f,
1749        (byte) 0xa7, (byte) 0x0e, (byte) 0x11, (byte) 0x4b, (byte) 0xb5, (byte) 0x94,
1750        (byte) 0xbe, (byte) 0x14, (byte) 0xaa, (byte) 0xaa, (byte) 0xe0, (byte) 0x38,
1751        (byte) 0x1c, (byte) 0xce, (byte) 0x40, (byte) 0x61, (byte) 0xfc, (byte) 0x08,
1752        (byte) 0xcb, (byte) 0x14, (byte) 0x2b, (byte) 0xa6, (byte) 0x54, (byte) 0xdf,
1753        (byte) 0x05, (byte) 0x5c, (byte) 0x9b, (byte) 0x4f, (byte) 0x14, (byte) 0x93,
1754        (byte) 0xb0, (byte) 0x70, (byte) 0xd9, (byte) 0x32, (byte) 0xdc, (byte) 0x24,
1755        (byte) 0xe0, (byte) 0xae, (byte) 0x48, (byte) 0xfc, (byte) 0x53, (byte) 0xee,
1756        (byte) 0x7c, (byte) 0x9f, (byte) 0x69, (byte) 0x34, (byte) 0xf4, (byte) 0x76,
1757        (byte) 0xee, (byte) 0x67, (byte) 0xb2, (byte) 0xa7, (byte) 0x33, (byte) 0x1c,
1758        (byte) 0x47, (byte) 0xff, (byte) 0x5c, (byte) 0xf0, (byte) 0xb8, (byte) 0x04,
1759        (byte) 0x2c, (byte) 0xfd, (byte) 0xe2, (byte) 0xb1, (byte) 0x4a, (byte) 0x0a,
1760        (byte) 0x69, (byte) 0x1c, (byte) 0x80, (byte) 0x2b, (byte) 0xb4, (byte) 0x50,
1761        (byte) 0x65, (byte) 0x5c, (byte) 0x76, (byte) 0x78, (byte) 0x9a, (byte) 0x0c,
1762        (byte) 0x05, (byte) 0x62, (byte) 0xf0, (byte) 0xc4, (byte) 0x1c, (byte) 0x38,
1763        (byte) 0x15, (byte) 0xd0, (byte) 0xe2, (byte) 0x5a, (byte) 0x3d, (byte) 0xb6,
1764        (byte) 0xe0, (byte) 0x88, (byte) 0x85, (byte) 0xd1, (byte) 0x4f, (byte) 0x7e,
1765        (byte) 0xfc, (byte) 0x77, (byte) 0x0d, (byte) 0x2a, (byte) 0x45, (byte) 0xd5,
1766        (byte) 0xf8, (byte) 0x3c, (byte) 0x7b, (byte) 0x2d, (byte) 0x1b, (byte) 0x82,
1767        (byte) 0xfe, (byte) 0x58, (byte) 0x22, (byte) 0x47, (byte) 0x06, (byte) 0x58,
1768        (byte) 0x8b, (byte) 0x4f, (byte) 0xfb, (byte) 0x9b, (byte) 0x1c, (byte) 0x70,
1769        (byte) 0x36, (byte) 0x12, (byte) 0x04, (byte) 0x17, (byte) 0x47, (byte) 0x8a,
1770        (byte) 0x0a, (byte) 0xec, (byte) 0x12, (byte) 0x3b, (byte) 0xf8, (byte) 0xd2,
1771        (byte) 0xdc, (byte) 0x3c, (byte) 0xc8, (byte) 0x46, (byte) 0xc6, (byte) 0x51,
1772        (byte) 0x06, (byte) 0x06, (byte) 0xcb, (byte) 0x84, (byte) 0x67, (byte) 0xb5,
1773        (byte) 0x68, (byte) 0xd9, (byte) 0x9c, (byte) 0xd4, (byte) 0x16, (byte) 0x5c,
1774        (byte) 0xb4, (byte) 0xe2, (byte) 0x55, (byte) 0xe6, (byte) 0x3a, (byte) 0x73,
1775        (byte) 0x01, (byte) 0x1d, (byte) 0x6f, (byte) 0x30, (byte) 0x31, (byte) 0x59,
1776        (byte) 0x8b, (byte) 0x2f, (byte) 0x4c, (byte) 0xe7, (byte) 0x86, (byte) 0x4c,
1777        (byte) 0x39, (byte) 0x4e, (byte) 0x67, (byte) 0x3b, (byte) 0x22, (byte) 0x9b,
1778        (byte) 0x85, (byte) 0x5a, (byte) 0xc3, (byte) 0x29, (byte) 0xaf, (byte) 0x8c,
1779        (byte) 0x7c, (byte) 0x59, (byte) 0x4a, (byte) 0x24, (byte) 0xfa, (byte) 0xba,
1780        (byte) 0x55, (byte) 0x40, (byte) 0x13, (byte) 0x64, (byte) 0xd8, (byte) 0xcb,
1781        (byte) 0x4b, (byte) 0x98, (byte) 0x3f, (byte) 0xae, (byte) 0x20, (byte) 0xfd,
1782        (byte) 0x8a, (byte) 0x50, (byte) 0x73, (byte) 0xe4,
1783    };
1784
1785    public void testRSA_ECB_NoPadding_Private_OnlyDoFinal_Success() throws Exception {
1786        for (String provider : RSA_PROVIDERS) {
1787            testRSA_ECB_NoPadding_Private_OnlyDoFinal_Success(provider);
1788        }
1789    }
1790
1791    private void testRSA_ECB_NoPadding_Private_OnlyDoFinal_Success(String provider) throws Exception {
1792        KeyFactory kf = KeyFactory.getInstance("RSA");
1793        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
1794                RSA_2048_privateExponent);
1795
1796        final PrivateKey privKey = kf.generatePrivate(keySpec);
1797
1798        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
1799
1800        /*
1801         * You're actually decrypting with private keys, but there is no
1802         * distinction made here. It's all keyed off of what kind of key you're
1803         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
1804         */
1805        c.init(Cipher.ENCRYPT_MODE, privKey);
1806        byte[] encrypted = c.doFinal(RSA_2048_Vector1);
1807        assertTrue("Encrypted should match expected",
1808                Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted));
1809
1810        c.init(Cipher.DECRYPT_MODE, privKey);
1811        encrypted = c.doFinal(RSA_2048_Vector1);
1812        assertTrue("Encrypted should match expected",
1813                Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted));
1814    }
1815
1816    public void testRSA_ECB_NoPadding_Private_UpdateThenEmptyDoFinal_Success() throws Exception {
1817        for (String provider : RSA_PROVIDERS) {
1818            testRSA_ECB_NoPadding_Private_UpdateThenEmptyDoFinal_Success(provider);
1819        }
1820    }
1821
1822    private void testRSA_ECB_NoPadding_Private_UpdateThenEmptyDoFinal_Success(String provider) throws Exception {
1823        KeyFactory kf = KeyFactory.getInstance("RSA");
1824        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
1825                RSA_2048_privateExponent);
1826
1827        final PrivateKey privKey = kf.generatePrivate(keySpec);
1828
1829        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
1830
1831        /*
1832         * You're actually decrypting with private keys, but there is no
1833         * distinction made here. It's all keyed off of what kind of key you're
1834         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
1835         */
1836        c.init(Cipher.ENCRYPT_MODE, privKey);
1837        c.update(RSA_2048_Vector1);
1838        byte[] encrypted = c.doFinal();
1839        assertTrue("Encrypted should match expected",
1840                Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted));
1841
1842        c.init(Cipher.DECRYPT_MODE, privKey);
1843        c.update(RSA_2048_Vector1);
1844        encrypted = c.doFinal();
1845        assertTrue("Encrypted should match expected",
1846                Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted));
1847    }
1848
1849    public void testRSA_ECB_NoPadding_Private_SingleByteUpdateThenEmptyDoFinal_Success()
1850            throws Exception {
1851        for (String provider : RSA_PROVIDERS) {
1852            testRSA_ECB_NoPadding_Private_SingleByteUpdateThenEmptyDoFinal_Success(provider);
1853        }
1854    }
1855
1856    private void testRSA_ECB_NoPadding_Private_SingleByteUpdateThenEmptyDoFinal_Success(String provider)
1857            throws Exception {
1858        KeyFactory kf = KeyFactory.getInstance("RSA");
1859        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
1860                RSA_2048_privateExponent);
1861
1862        final PrivateKey privKey = kf.generatePrivate(keySpec);
1863
1864        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
1865
1866        /*
1867         * You're actually decrypting with private keys, but there is no
1868         * distinction made here. It's all keyed off of what kind of key you're
1869         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
1870         */
1871        c.init(Cipher.ENCRYPT_MODE, privKey);
1872        int i;
1873        for (i = 0; i < RSA_2048_Vector1.length / 2; i++) {
1874            c.update(RSA_2048_Vector1, i, 1);
1875        }
1876        byte[] encrypted = c.doFinal(RSA_2048_Vector1, i, RSA_2048_Vector1.length - i);
1877        assertTrue("Encrypted should match expected",
1878                Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted));
1879
1880        c.init(Cipher.DECRYPT_MODE, privKey);
1881        for (i = 0; i < RSA_2048_Vector1.length / 2; i++) {
1882            c.update(RSA_2048_Vector1, i, 1);
1883        }
1884        encrypted = c.doFinal(RSA_2048_Vector1, i, RSA_2048_Vector1.length - i);
1885        assertTrue("Encrypted should match expected",
1886                Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted));
1887    }
1888
1889    public void testRSA_ECB_NoPadding_Private_OnlyDoFinalWithOffset_Success() throws Exception {
1890        for (String provider : RSA_PROVIDERS) {
1891            testRSA_ECB_NoPadding_Private_OnlyDoFinalWithOffset_Success(provider);
1892        }
1893    }
1894
1895    private void testRSA_ECB_NoPadding_Private_OnlyDoFinalWithOffset_Success(String provider) throws Exception {
1896        KeyFactory kf = KeyFactory.getInstance("RSA");
1897        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
1898                RSA_2048_privateExponent);
1899        final PrivateKey privKey = kf.generatePrivate(keySpec);
1900
1901        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
1902
1903        /*
1904         * You're actually decrypting with private keys, but there is no
1905         * distinction made here. It's all keyed off of what kind of key you're
1906         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
1907         */
1908        c.init(Cipher.ENCRYPT_MODE, privKey);
1909        byte[] encrypted = new byte[RSA_Vector1_Encrypt_Private.length];
1910        final int encryptLen = c
1911                .doFinal(RSA_2048_Vector1, 0, RSA_2048_Vector1.length, encrypted, 0);
1912        assertEquals("Encrypted size should match expected", RSA_Vector1_Encrypt_Private.length,
1913                encryptLen);
1914        assertTrue("Encrypted should match expected",
1915                Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted));
1916
1917        c.init(Cipher.DECRYPT_MODE, privKey);
1918        final int decryptLen = c
1919                .doFinal(RSA_2048_Vector1, 0, RSA_2048_Vector1.length, encrypted, 0);
1920        assertEquals("Encrypted size should match expected", RSA_Vector1_Encrypt_Private.length,
1921                decryptLen);
1922        assertTrue("Encrypted should match expected",
1923                Arrays.equals(RSA_Vector1_Encrypt_Private, encrypted));
1924    }
1925
1926    public void testRSA_ECB_NoPadding_Public_OnlyDoFinal_Success() throws Exception {
1927        for (String provider : RSA_PROVIDERS) {
1928            testRSA_ECB_NoPadding_Public_OnlyDoFinal_Success(provider);
1929        }
1930    }
1931
1932    private void testRSA_ECB_NoPadding_Public_OnlyDoFinal_Success(String provider) throws Exception {
1933        KeyFactory kf = KeyFactory.getInstance("RSA");
1934        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
1935
1936        final PublicKey privKey = kf.generatePublic(keySpec);
1937
1938        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
1939
1940        /*
1941         * You're actually encrypting with public keys, but there is no
1942         * distinction made here. It's all keyed off of what kind of key you're
1943         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
1944         */
1945        c.init(Cipher.ENCRYPT_MODE, privKey);
1946        byte[] encrypted = c.doFinal(RSA_Vector1_Encrypt_Private);
1947        assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted);
1948
1949        c.init(Cipher.DECRYPT_MODE, privKey);
1950        encrypted = c.doFinal(RSA_Vector1_Encrypt_Private);
1951        assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, RSA_2048_Vector1, encrypted);
1952    }
1953
1954    public void testRSA_ECB_NoPadding_Public_OnlyDoFinalWithOffset_Success() throws Exception {
1955        for (String provider : RSA_PROVIDERS) {
1956            testRSA_ECB_NoPadding_Public_OnlyDoFinalWithOffset_Success(provider);
1957        }
1958    }
1959
1960    private void testRSA_ECB_NoPadding_Public_OnlyDoFinalWithOffset_Success(String provider) throws Exception {
1961        KeyFactory kf = KeyFactory.getInstance("RSA");
1962        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
1963
1964        final PublicKey pubKey = kf.generatePublic(keySpec);
1965
1966        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
1967
1968        /*
1969         * You're actually encrypting with public keys, but there is no
1970         * distinction made here. It's all keyed off of what kind of key you're
1971         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
1972         */
1973        c.init(Cipher.ENCRYPT_MODE, pubKey);
1974        byte[] encrypted = new byte[RSA_2048_Vector1.length];
1975        final int encryptLen = c.doFinal(RSA_Vector1_Encrypt_Private, 0,
1976                RSA_Vector1_Encrypt_Private.length, encrypted, 0);
1977        assertEquals("Encrypted size should match expected", RSA_2048_Vector1.length, encryptLen);
1978        assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted);
1979
1980        c.init(Cipher.DECRYPT_MODE, pubKey);
1981        int decryptLen = c.doFinal(RSA_Vector1_Encrypt_Private, 0,
1982                RSA_Vector1_Encrypt_Private.length, encrypted, 0);
1983        if (provider.equals("BC")) {
1984            // BC strips the leading 0 for us on decrypt even when NoPadding is specified...
1985            decryptLen++;
1986            encrypted = Arrays.copyOf(encrypted, encrypted.length - 1);
1987        }
1988        assertEquals("Encrypted size should match expected", RSA_2048_Vector1.length, decryptLen);
1989        assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, RSA_2048_Vector1, encrypted);
1990    }
1991
1992    public void testRSA_ECB_NoPadding_Public_UpdateThenEmptyDoFinal_Success() throws Exception {
1993        for (String provider : RSA_PROVIDERS) {
1994            testRSA_ECB_NoPadding_Public_UpdateThenEmptyDoFinal_Success(provider);
1995        }
1996    }
1997
1998    private void testRSA_ECB_NoPadding_Public_UpdateThenEmptyDoFinal_Success(String provider) throws Exception {
1999        KeyFactory kf = KeyFactory.getInstance("RSA");
2000        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
2001
2002        final PublicKey privKey = kf.generatePublic(keySpec);
2003
2004        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2005
2006        /*
2007         * You're actually encrypting with public keys, but there is no
2008         * distinction made here. It's all keyed off of what kind of key you're
2009         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
2010         */
2011        c.init(Cipher.ENCRYPT_MODE, privKey);
2012        c.update(RSA_Vector1_Encrypt_Private);
2013        byte[] encrypted = c.doFinal();
2014        assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted);
2015
2016        c.init(Cipher.DECRYPT_MODE, privKey);
2017        c.update(RSA_Vector1_Encrypt_Private);
2018        encrypted = c.doFinal();
2019        assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, RSA_2048_Vector1, encrypted);
2020    }
2021
2022    public void testRSA_ECB_NoPadding_Public_SingleByteUpdateThenEmptyDoFinal_Success()
2023            throws Exception {
2024        for (String provider : RSA_PROVIDERS) {
2025            testRSA_ECB_NoPadding_Public_SingleByteUpdateThenEmptyDoFinal_Success(provider);
2026        }
2027    }
2028
2029    private void testRSA_ECB_NoPadding_Public_SingleByteUpdateThenEmptyDoFinal_Success(String provider)
2030            throws Exception {
2031        KeyFactory kf = KeyFactory.getInstance("RSA");
2032        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
2033
2034        final PublicKey privKey = kf.generatePublic(keySpec);
2035
2036        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2037
2038        /*
2039         * You're actually encrypting with public keys, but there is no
2040         * distinction made here. It's all keyed off of what kind of key you're
2041         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
2042         */
2043        c.init(Cipher.ENCRYPT_MODE, privKey);
2044        int i;
2045        for (i = 0; i < RSA_Vector1_Encrypt_Private.length / 2; i++) {
2046            c.update(RSA_Vector1_Encrypt_Private, i, 1);
2047        }
2048        byte[] encrypted = c.doFinal(RSA_Vector1_Encrypt_Private, i, RSA_2048_Vector1.length - i);
2049        assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE, RSA_2048_Vector1, encrypted);
2050
2051        c.init(Cipher.DECRYPT_MODE, privKey);
2052        for (i = 0; i < RSA_Vector1_Encrypt_Private.length / 2; i++) {
2053            c.update(RSA_Vector1_Encrypt_Private, i, 1);
2054        }
2055        encrypted = c.doFinal(RSA_Vector1_Encrypt_Private, i, RSA_2048_Vector1.length - i);
2056        assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE, RSA_2048_Vector1, encrypted);
2057    }
2058
2059    public void testRSA_ECB_NoPadding_Public_TooSmall_Success() throws Exception {
2060        for (String provider : RSA_PROVIDERS) {
2061            testRSA_ECB_NoPadding_Public_TooSmall_Success(provider);
2062        }
2063    }
2064
2065    private void testRSA_ECB_NoPadding_Public_TooSmall_Success(String provider) throws Exception {
2066        KeyFactory kf = KeyFactory.getInstance("RSA");
2067        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(RSA_2048_modulus, RSA_2048_publicExponent);
2068
2069        final PublicKey privKey = kf.generatePublic(keySpec);
2070
2071        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2072
2073        /*
2074         * You're actually encrypting with public keys, but there is no
2075         * distinction made here. It's all keyed off of what kind of key you're
2076         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
2077         */
2078        c.init(Cipher.ENCRYPT_MODE, privKey);
2079        byte[] encrypted = c.doFinal(TooShort_Vector);
2080        assertTrue("Encrypted should match expected",
2081                Arrays.equals(RSA_Vector1_ZeroPadded_Encrypted, encrypted));
2082
2083        c.init(Cipher.DECRYPT_MODE, privKey);
2084        encrypted = c.doFinal(TooShort_Vector);
2085        assertTrue("Encrypted should match expected",
2086                Arrays.equals(RSA_Vector1_ZeroPadded_Encrypted, encrypted));
2087    }
2088
2089    public void testRSA_ECB_NoPadding_Private_TooSmall_Success() throws Exception {
2090        for (String provider : RSA_PROVIDERS) {
2091            testRSA_ECB_NoPadding_Private_TooSmall_Success(provider);
2092        }
2093    }
2094
2095    private void testRSA_ECB_NoPadding_Private_TooSmall_Success(String provider) throws Exception {
2096        KeyFactory kf = KeyFactory.getInstance("RSA");
2097        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
2098                RSA_2048_privateExponent);
2099
2100        final PrivateKey privKey = kf.generatePrivate(keySpec);
2101
2102        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2103
2104        /*
2105         * You're actually encrypting with public keys, but there is no
2106         * distinction made here. It's all keyed off of what kind of key you're
2107         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
2108         */
2109        c.init(Cipher.ENCRYPT_MODE, privKey);
2110        byte[] encrypted = c.doFinal(RSA_Vector1_ZeroPadded_Encrypted);
2111        assertEncryptedEqualsNoPadding(provider, Cipher.ENCRYPT_MODE,
2112                                       TooShort_Vector_Zero_Padded, encrypted);
2113
2114        c.init(Cipher.DECRYPT_MODE, privKey);
2115        encrypted = c.doFinal(RSA_Vector1_ZeroPadded_Encrypted);
2116        assertEncryptedEqualsNoPadding(provider, Cipher.DECRYPT_MODE,
2117                                       TooShort_Vector_Zero_Padded, encrypted);
2118    }
2119
2120    private static void assertEncryptedEqualsNoPadding(String provider, int mode,
2121                                                       byte[] expected, byte[] actual) {
2122        if (provider.equals("BC") && mode == Cipher.DECRYPT_MODE) {
2123            // BouncyCastle does us the favor of stripping leading zeroes in DECRYPT_MODE
2124            int nonZeroOffset = 0;
2125            for (byte b : expected) {
2126                if (b != 0) {
2127                    break;
2128                }
2129                nonZeroOffset++;
2130            }
2131            expected = Arrays.copyOfRange(expected, nonZeroOffset, expected.length);
2132        }
2133        assertEquals("Encrypted should match expected",
2134                     Arrays.toString(expected), Arrays.toString(actual));
2135    }
2136
2137    public void testRSA_ECB_NoPadding_Private_CombinedUpdateAndDoFinal_TooBig_Failure()
2138            throws Exception {
2139        for (String provider : RSA_PROVIDERS) {
2140            testRSA_ECB_NoPadding_Private_CombinedUpdateAndDoFinal_TooBig_Failure(provider);
2141        }
2142    }
2143
2144    private void testRSA_ECB_NoPadding_Private_CombinedUpdateAndDoFinal_TooBig_Failure(String provider)
2145            throws Exception {
2146        KeyFactory kf = KeyFactory.getInstance("RSA");
2147        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
2148                RSA_2048_privateExponent);
2149
2150        final PrivateKey privKey = kf.generatePrivate(keySpec);
2151
2152        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2153
2154        /*
2155         * You're actually encrypting with public keys, but there is no
2156         * distinction made here. It's all keyed off of what kind of key you're
2157         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
2158         */
2159        c.init(Cipher.ENCRYPT_MODE, privKey);
2160        c.update(RSA_Vector1_ZeroPadded_Encrypted);
2161
2162        try {
2163            c.doFinal(RSA_Vector1_ZeroPadded_Encrypted);
2164            fail("Should have error when block size is too big.");
2165        } catch (IllegalBlockSizeException success) {
2166            assertFalse(provider, "BC".equals(provider));
2167        } catch (ArrayIndexOutOfBoundsException success) {
2168            assertEquals("BC", provider);
2169        }
2170    }
2171
2172    public void testRSA_ECB_NoPadding_Private_UpdateInAndOutPlusDoFinal_TooBig_Failure()
2173            throws Exception {
2174        for (String provider : RSA_PROVIDERS) {
2175            testRSA_ECB_NoPadding_Private_UpdateInAndOutPlusDoFinal_TooBig_Failure(provider);
2176        }
2177    }
2178
2179    private void testRSA_ECB_NoPadding_Private_UpdateInAndOutPlusDoFinal_TooBig_Failure(String provider)
2180            throws Exception {
2181        KeyFactory kf = KeyFactory.getInstance("RSA");
2182        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
2183                RSA_2048_privateExponent);
2184
2185        final PrivateKey privKey = kf.generatePrivate(keySpec);
2186
2187        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2188
2189        /*
2190         * You're actually encrypting with public keys, but there is no
2191         * distinction made here. It's all keyed off of what kind of key you're
2192         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
2193         */
2194        c.init(Cipher.ENCRYPT_MODE, privKey);
2195
2196        byte[] output = new byte[RSA_2048_Vector1.length];
2197        c.update(RSA_Vector1_ZeroPadded_Encrypted, 0, RSA_Vector1_ZeroPadded_Encrypted.length,
2198                output);
2199
2200        try {
2201            c.doFinal(RSA_Vector1_ZeroPadded_Encrypted);
2202            fail("Should have error when block size is too big.");
2203        } catch (IllegalBlockSizeException success) {
2204            assertFalse(provider, "BC".equals(provider));
2205        } catch (ArrayIndexOutOfBoundsException success) {
2206            assertEquals("BC", provider);
2207        }
2208    }
2209
2210    public void testRSA_ECB_NoPadding_Private_OnlyDoFinal_TooBig_Failure() throws Exception {
2211        for (String provider : RSA_PROVIDERS) {
2212            testRSA_ECB_NoPadding_Private_OnlyDoFinal_TooBig_Failure(provider);
2213        }
2214    }
2215
2216    private void testRSA_ECB_NoPadding_Private_OnlyDoFinal_TooBig_Failure(String provider) throws Exception {
2217        KeyFactory kf = KeyFactory.getInstance("RSA");
2218        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(RSA_2048_modulus,
2219                RSA_2048_privateExponent);
2220
2221        final PrivateKey privKey = kf.generatePrivate(keySpec);
2222
2223        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2224
2225        /*
2226         * You're actually encrypting with public keys, but there is no
2227         * distinction made here. It's all keyed off of what kind of key you're
2228         * using. ENCRYPT_MODE and DECRYPT_MODE are the same.
2229         */
2230        c.init(Cipher.ENCRYPT_MODE, privKey);
2231
2232        byte[] tooBig_Vector = new byte[RSA_Vector1_ZeroPadded_Encrypted.length * 2];
2233        System.arraycopy(RSA_Vector1_ZeroPadded_Encrypted, 0, tooBig_Vector, 0,
2234                RSA_Vector1_ZeroPadded_Encrypted.length);
2235        System.arraycopy(RSA_Vector1_ZeroPadded_Encrypted, 0, tooBig_Vector,
2236                RSA_Vector1_ZeroPadded_Encrypted.length, RSA_Vector1_ZeroPadded_Encrypted.length);
2237
2238        try {
2239            c.doFinal(tooBig_Vector);
2240            fail("Should have error when block size is too big.");
2241        } catch (IllegalBlockSizeException success) {
2242            assertFalse(provider, "BC".equals(provider));
2243        } catch (ArrayIndexOutOfBoundsException success) {
2244            assertEquals("BC", provider);
2245        }
2246    }
2247
2248    public void testRSA_ECB_NoPadding_GetBlockSize_Success() throws Exception {
2249        for (String provider : RSA_PROVIDERS) {
2250            testRSA_ECB_NoPadding_GetBlockSize_Success(provider);
2251        }
2252    }
2253
2254    private void testRSA_ECB_NoPadding_GetBlockSize_Success(String provider) throws Exception {
2255        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2256        if (StandardNames.IS_RI) {
2257            assertEquals(0, c.getBlockSize());
2258        } else {
2259            try {
2260                c.getBlockSize();
2261                fail();
2262            } catch (IllegalStateException expected) {
2263            }
2264        }
2265
2266        KeyFactory kf = KeyFactory.getInstance("RSA");
2267        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
2268                RSA_2048_publicExponent);
2269        final PublicKey pubKey = kf.generatePublic(pubKeySpec);
2270        c.init(Cipher.ENCRYPT_MODE, pubKey);
2271        assertEquals(getExpectedBlockSize("RSA", Cipher.ENCRYPT_MODE, provider), c.getBlockSize());
2272    }
2273
2274    public void testRSA_ECB_NoPadding_GetOutputSize_NoInit_Failure() throws Exception {
2275        for (String provider : RSA_PROVIDERS) {
2276            testRSA_ECB_NoPadding_GetOutputSize_NoInit_Failure(provider);
2277        }
2278    }
2279
2280    private void testRSA_ECB_NoPadding_GetOutputSize_NoInit_Failure(String provider) throws Exception {
2281        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2282        try {
2283            c.getOutputSize(RSA_2048_Vector1.length);
2284            fail("Should throw IllegalStateException if getOutputSize is called before init");
2285        } catch (IllegalStateException success) {
2286        }
2287    }
2288
2289    public void testRSA_ECB_NoPadding_GetOutputSize_Success() throws Exception {
2290        for (String provider : RSA_PROVIDERS) {
2291            testRSA_ECB_NoPadding_GetOutputSize_Success(provider);
2292        }
2293    }
2294
2295    private void testRSA_ECB_NoPadding_GetOutputSize_Success(String provider) throws Exception {
2296        KeyFactory kf = KeyFactory.getInstance("RSA");
2297        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
2298                RSA_2048_publicExponent);
2299        final PublicKey pubKey = kf.generatePublic(pubKeySpec);
2300
2301        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2302        c.init(Cipher.ENCRYPT_MODE, pubKey);
2303
2304        final int modulusInBytes = RSA_2048_modulus.bitLength() / 8;
2305        assertEquals(modulusInBytes, c.getOutputSize(RSA_2048_Vector1.length));
2306        assertEquals(modulusInBytes, c.getOutputSize(RSA_2048_Vector1.length * 2));
2307        assertEquals(modulusInBytes, c.getOutputSize(0));
2308    }
2309
2310    public void testRSA_ECB_NoPadding_GetIV_Success() throws Exception {
2311        for (String provider : RSA_PROVIDERS) {
2312            testRSA_ECB_NoPadding_GetIV_Success(provider);
2313        }
2314    }
2315
2316    private void testRSA_ECB_NoPadding_GetIV_Success(String provider) throws Exception {
2317        KeyFactory kf = KeyFactory.getInstance("RSA");
2318        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
2319                RSA_2048_publicExponent);
2320        final PublicKey pubKey = kf.generatePublic(pubKeySpec);
2321
2322        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2323        assertNull("ECB mode has no IV and should be null", c.getIV());
2324
2325        c.init(Cipher.ENCRYPT_MODE, pubKey);
2326
2327        assertNull("ECB mode has no IV and should be null", c.getIV());
2328    }
2329
2330    public void testRSA_ECB_NoPadding_GetParameters_NoneProvided_Success() throws Exception {
2331        for (String provider : RSA_PROVIDERS) {
2332            testRSA_ECB_NoPadding_GetParameters_NoneProvided_Success(provider);
2333        }
2334    }
2335
2336    private void testRSA_ECB_NoPadding_GetParameters_NoneProvided_Success(String provider) throws Exception {
2337        KeyFactory kf = KeyFactory.getInstance("RSA");
2338        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(RSA_2048_modulus,
2339                RSA_2048_publicExponent);
2340        final PublicKey pubKey = kf.generatePublic(pubKeySpec);
2341
2342        Cipher c = Cipher.getInstance("RSA/ECB/NoPadding", provider);
2343        assertNull("Parameters should be null", c.getParameters());
2344    }
2345
2346    /*
2347     * Test vector generation:
2348     * openssl rand -hex 16
2349     * echo '3d4f8970b1f27537f40a39298a41555f' | sed 's/\(..\)/(byte) 0x\1, /g'
2350     */
2351    private static final byte[] AES_128_KEY = new byte[] {
2352            (byte) 0x3d, (byte) 0x4f, (byte) 0x89, (byte) 0x70, (byte) 0xb1, (byte) 0xf2,
2353            (byte) 0x75, (byte) 0x37, (byte) 0xf4, (byte) 0x0a, (byte) 0x39, (byte) 0x29,
2354            (byte) 0x8a, (byte) 0x41, (byte) 0x55, (byte) 0x5f,
2355    };
2356
2357    /*
2358     * Test key generation:
2359     * openssl rand -hex 24
2360     * echo '5a7a3d7e40b64ed996f7afa15f97fd595e27db6af428e342' | sed 's/\(..\)/(byte) 0x\1, /g'
2361     */
2362    private static final byte[] AES_192_KEY = new byte[] {
2363            (byte) 0x5a, (byte) 0x7a, (byte) 0x3d, (byte) 0x7e, (byte) 0x40, (byte) 0xb6,
2364            (byte) 0x4e, (byte) 0xd9, (byte) 0x96, (byte) 0xf7, (byte) 0xaf, (byte) 0xa1,
2365            (byte) 0x5f, (byte) 0x97, (byte) 0xfd, (byte) 0x59, (byte) 0x5e, (byte) 0x27,
2366            (byte) 0xdb, (byte) 0x6a, (byte) 0xf4, (byte) 0x28, (byte) 0xe3, (byte) 0x42,
2367    };
2368
2369    /*
2370     * Test key generation:
2371     * openssl rand -hex 32
2372     * echo 'ec53c6d51d2c4973585fb0b8e51cd2e39915ff07a1837872715d6121bf861935' | sed 's/\(..\)/(byte) 0x\1, /g'
2373     */
2374    private static final byte[] AES_256_KEY = new byte[] {
2375            (byte) 0xec, (byte) 0x53, (byte) 0xc6, (byte) 0xd5, (byte) 0x1d, (byte) 0x2c,
2376            (byte) 0x49, (byte) 0x73, (byte) 0x58, (byte) 0x5f, (byte) 0xb0, (byte) 0xb8,
2377            (byte) 0xe5, (byte) 0x1c, (byte) 0xd2, (byte) 0xe3, (byte) 0x99, (byte) 0x15,
2378            (byte) 0xff, (byte) 0x07, (byte) 0xa1, (byte) 0x83, (byte) 0x78, (byte) 0x72,
2379            (byte) 0x71, (byte) 0x5d, (byte) 0x61, (byte) 0x21, (byte) 0xbf, (byte) 0x86,
2380            (byte) 0x19, (byte) 0x35,
2381    };
2382
2383    private static final byte[][] AES_KEYS = new byte[][] {
2384            AES_128_KEY, AES_192_KEY, AES_256_KEY,
2385    };
2386
2387    private static final String[] AES_MODES = new String[] {
2388            "AES/ECB",
2389            "AES/CBC",
2390            "AES/CFB",
2391            "AES/CTR",
2392            "AES/OFB",
2393    };
2394
2395    /*
2396     * Test vector creation:
2397     * echo -n 'Hello, world!' | recode ../x1 | sed 's/0x/(byte) 0x/g'
2398     */
2399    private static final byte[] AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext = new byte[] {
2400            (byte) 0x48, (byte) 0x65, (byte) 0x6C, (byte) 0x6C, (byte) 0x6F, (byte) 0x2C,
2401            (byte) 0x20, (byte) 0x77, (byte) 0x6F, (byte) 0x72, (byte) 0x6C, (byte) 0x64,
2402            (byte) 0x21,
2403    };
2404
2405    /*
2406     * Test vector creation:
2407     * openssl enc -aes-128-ecb -K 3d4f8970b1f27537f40a39298a41555f -in blah|openssl enc -aes-128-ecb -K 3d4f8970b1f27537f40a39298a41555f -nopad -d|recode ../x1 | sed 's/0x/(byte) 0x/g'
2408     */
2409    private static final byte[] AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded = new byte[] {
2410            (byte) 0x48, (byte) 0x65, (byte) 0x6C, (byte) 0x6C, (byte) 0x6F, (byte) 0x2C,
2411            (byte) 0x20, (byte) 0x77, (byte) 0x6F, (byte) 0x72, (byte) 0x6C, (byte) 0x64,
2412            (byte) 0x21, (byte) 0x03, (byte) 0x03, (byte) 0x03
2413    };
2414
2415    /*
2416     * Test vector generation:
2417     * openssl enc -aes-128-ecb -K 3d4f8970b1f27537f40a39298a41555f -in blah|recode ../x1 | sed 's/0x/(byte) 0x/g'
2418     */
2419    private static final byte[] AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted = new byte[] {
2420            (byte) 0x65, (byte) 0x3E, (byte) 0x86, (byte) 0xFB, (byte) 0x05, (byte) 0x5A,
2421            (byte) 0x52, (byte) 0xEA, (byte) 0xDD, (byte) 0x08, (byte) 0xE7, (byte) 0x48,
2422            (byte) 0x33, (byte) 0x01, (byte) 0xFC, (byte) 0x5A,
2423    };
2424
2425    /*
2426     * Test key generation:
2427     * openssl rand -hex 16
2428     * echo 'ceaa31952dfd3d0f5af4b2042ba06094' | sed 's/\(..\)/(byte) 0x\1, /g'
2429     */
2430    private static final byte[] AES_256_CBC_PKCS5Padding_TestVector_1_IV = new byte[] {
2431            (byte) 0xce, (byte) 0xaa, (byte) 0x31, (byte) 0x95, (byte) 0x2d, (byte) 0xfd,
2432            (byte) 0x3d, (byte) 0x0f, (byte) 0x5a, (byte) 0xf4, (byte) 0xb2, (byte) 0x04,
2433            (byte) 0x2b, (byte) 0xa0, (byte) 0x60, (byte) 0x94,
2434    };
2435
2436    /*
2437     * Test vector generation:
2438     * echo -n 'I only regret that I have but one test to write.' | recode ../x1 | sed 's/0x/(byte) 0x/g'
2439     */
2440    private static final byte[] AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext = new byte[] {
2441            (byte) 0x49, (byte) 0x20, (byte) 0x6F, (byte) 0x6E, (byte) 0x6C, (byte) 0x79,
2442            (byte) 0x20, (byte) 0x72, (byte) 0x65, (byte) 0x67, (byte) 0x72, (byte) 0x65,
2443            (byte) 0x74, (byte) 0x20, (byte) 0x74, (byte) 0x68, (byte) 0x61, (byte) 0x74,
2444            (byte) 0x20, (byte) 0x49, (byte) 0x20, (byte) 0x68, (byte) 0x61, (byte) 0x76,
2445            (byte) 0x65, (byte) 0x20, (byte) 0x62, (byte) 0x75, (byte) 0x74, (byte) 0x20,
2446            (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x20, (byte) 0x74, (byte) 0x65,
2447            (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x74, (byte) 0x6F, (byte) 0x20,
2448            (byte) 0x77, (byte) 0x72, (byte) 0x69, (byte) 0x74, (byte) 0x65, (byte) 0x2E
2449    };
2450
2451    /*
2452     * Test vector generation:
2453     * echo -n 'I only regret that I have but one test to write.' | openssl enc -aes-256-cbc -K ec53c6d51d2c4973585fb0b8e51cd2e39915ff07a1837872715d6121bf861935 -iv ceaa31952dfd3d0f5af4b2042ba06094 | openssl enc -aes-256-cbc -K ec53c6d51d2c4973585fb0b8e51cd2e39915ff07a1837872715d6121bf861935 -iv ceaa31952dfd3d0f5af4b2042ba06094 -d -nopad | recode ../x1 | sed 's/0x/(byte) 0x/g'
2454     */
2455    private static final byte[] AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext_Padded = new byte[] {
2456            (byte) 0x49, (byte) 0x20, (byte) 0x6F, (byte) 0x6E, (byte) 0x6C, (byte) 0x79,
2457            (byte) 0x20, (byte) 0x72, (byte) 0x65, (byte) 0x67, (byte) 0x72, (byte) 0x65,
2458            (byte) 0x74, (byte) 0x20, (byte) 0x74, (byte) 0x68, (byte) 0x61, (byte) 0x74,
2459            (byte) 0x20, (byte) 0x49, (byte) 0x20, (byte) 0x68, (byte) 0x61, (byte) 0x76,
2460            (byte) 0x65, (byte) 0x20, (byte) 0x62, (byte) 0x75, (byte) 0x74, (byte) 0x20,
2461            (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x20, (byte) 0x74, (byte) 0x65,
2462            (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x74, (byte) 0x6F, (byte) 0x20,
2463            (byte) 0x77, (byte) 0x72, (byte) 0x69, (byte) 0x74, (byte) 0x65, (byte) 0x2E,
2464            (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10,
2465            (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10,
2466            (byte) 0x10, (byte) 0x10, (byte) 0x10, (byte) 0x10
2467    };
2468
2469    /*
2470     * Test vector generation:
2471     * echo -n 'I only regret that I have but one test to write.' | openssl enc -aes-256-cbc -K ec53c6d51d2c4973585fb0b8e51cd2e39915ff07a1837872715d6121bf861935 -iv ceaa31952dfd3d0f5af4b2042ba06094 | recode ../x1 | sed 's/0x/(byte) 0x/g'
2472     */
2473    private static final byte[] AES_256_CBC_PKCS5Padding_TestVector_1_Ciphertext = new byte[] {
2474            (byte) 0x90, (byte) 0x65, (byte) 0xDD, (byte) 0xAF, (byte) 0x7A, (byte) 0xCE,
2475            (byte) 0xAE, (byte) 0xBF, (byte) 0xE8, (byte) 0xF6, (byte) 0x9E, (byte) 0xDB,
2476            (byte) 0xEA, (byte) 0x65, (byte) 0x28, (byte) 0xC4, (byte) 0x9A, (byte) 0x28,
2477            (byte) 0xEA, (byte) 0xA3, (byte) 0x95, (byte) 0x2E, (byte) 0xFF, (byte) 0xF1,
2478            (byte) 0xA0, (byte) 0xCA, (byte) 0xC2, (byte) 0xA4, (byte) 0x65, (byte) 0xCD,
2479            (byte) 0xBF, (byte) 0xCE, (byte) 0x9E, (byte) 0xF1, (byte) 0x57, (byte) 0xF6,
2480            (byte) 0x32, (byte) 0x2E, (byte) 0x8F, (byte) 0x93, (byte) 0x2E, (byte) 0xAE,
2481            (byte) 0x41, (byte) 0x33, (byte) 0x54, (byte) 0xD0, (byte) 0xEF, (byte) 0x8C,
2482            (byte) 0x52, (byte) 0x14, (byte) 0xAC, (byte) 0x2D, (byte) 0xD5, (byte) 0xA4,
2483            (byte) 0xF9, (byte) 0x20, (byte) 0x77, (byte) 0x25, (byte) 0x91, (byte) 0x3F,
2484            (byte) 0xD1, (byte) 0xB9, (byte) 0x00, (byte) 0x3E
2485    };
2486
2487    private static class CipherTestParam {
2488        public final String transformation;
2489
2490        public final byte[] key;
2491
2492        public final byte[] iv;
2493
2494        public final byte[] plaintext;
2495
2496        public final byte[] ciphertext;
2497
2498        public final byte[] plaintextPadded;
2499
2500        public CipherTestParam(String transformation, byte[] key, byte[] iv, byte[] plaintext,
2501                byte[] plaintextPadded, byte[] ciphertext) {
2502            this.transformation = transformation;
2503            this.key = key;
2504            this.iv = iv;
2505            this.plaintext = plaintext;
2506            this.plaintextPadded = plaintextPadded;
2507            this.ciphertext = ciphertext;
2508        }
2509    }
2510
2511    private static List<CipherTestParam> CIPHER_TEST_PARAMS = new ArrayList<CipherTestParam>();
2512    static {
2513        CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/ECB/PKCS5Padding", AES_128_KEY,
2514                null,
2515                AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext,
2516                AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded,
2517                AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted));
2518        // PKCS#5 is assumed to be equivalent to PKCS#7 -- same test vectors are thus used for both.
2519        CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/ECB/PKCS7Padding", AES_128_KEY,
2520                null,
2521                AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext,
2522                AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded,
2523                AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted));
2524        if (IS_UNLIMITED) {
2525            CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/CBC/PKCS5Padding", AES_256_KEY,
2526                    AES_256_CBC_PKCS5Padding_TestVector_1_IV,
2527                    AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext,
2528                    AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext_Padded,
2529                    AES_256_CBC_PKCS5Padding_TestVector_1_Ciphertext));
2530            CIPHER_TEST_PARAMS.add(new CipherTestParam("AES/CBC/PKCS7Padding", AES_256_KEY,
2531                    AES_256_CBC_PKCS5Padding_TestVector_1_IV,
2532                    AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext,
2533                    AES_256_CBC_PKCS5Padding_TestVector_1_Plaintext_Padded,
2534                    AES_256_CBC_PKCS5Padding_TestVector_1_Ciphertext));
2535        }
2536    }
2537
2538    public void testCipher_Success() throws Exception {
2539        for (String provider : AES_PROVIDERS) {
2540            testCipher_Success(provider);
2541        }
2542    }
2543
2544    private void testCipher_Success(String provider) throws Exception {
2545        final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();
2546        PrintStream out = new PrintStream(errBuffer);
2547        for (CipherTestParam p : CIPHER_TEST_PARAMS) {
2548            try {
2549                checkCipher(p, provider);
2550            } catch (Exception e) {
2551                out.append("Error encountered checking " + p.transformation + ", keySize="
2552                        + (p.key.length * 8)
2553                        + " with provider " + provider + "\n");
2554
2555                e.printStackTrace(out);
2556            }
2557        }
2558        out.flush();
2559        if (errBuffer.size() > 0) {
2560            throw new Exception("Errors encountered:\n\n" + errBuffer.toString() + "\n\n");
2561        }
2562    }
2563
2564    private void checkCipher(CipherTestParam p, String provider) throws Exception {
2565        SecretKey key = new SecretKeySpec(p.key, "AES");
2566        Cipher c = Cipher.getInstance(p.transformation, provider);
2567        AlgorithmParameterSpec spec = null;
2568        if (p.iv != null) {
2569            spec = new IvParameterSpec(p.iv);
2570        }
2571        c.init(Cipher.ENCRYPT_MODE, key, spec);
2572
2573        final byte[] actualCiphertext = c.doFinal(p.plaintext);
2574        assertEquals(Arrays.toString(p.ciphertext), Arrays.toString(actualCiphertext));
2575
2576        byte[] emptyCipherText = c.doFinal();
2577        assertNotNull(emptyCipherText);
2578
2579        c.init(Cipher.DECRYPT_MODE, key, spec);
2580
2581        try {
2582            c.updateAAD(new byte[8]);
2583            fail("Cipher should not support AAD");
2584        } catch (UnsupportedOperationException expected) {
2585        }
2586
2587        byte[] emptyPlainText = c.doFinal(emptyCipherText);
2588        assertEquals(Arrays.toString(new byte[0]), Arrays.toString(emptyPlainText));
2589
2590        // empty decrypt
2591        {
2592            if (StandardNames.IS_RI) {
2593                assertEquals(Arrays.toString(new byte[0]),
2594                             Arrays.toString(c.doFinal()));
2595
2596                c.update(new byte[0]);
2597                assertEquals(Arrays.toString(new byte[0]),
2598                             Arrays.toString(c.doFinal()));
2599            } else if (provider.equals("BC")) {
2600                try {
2601                    c.doFinal();
2602                    fail();
2603                } catch (IllegalBlockSizeException expected) {
2604                }
2605                try {
2606                    c.update(new byte[0]);
2607                    c.doFinal();
2608                    fail();
2609                } catch (IllegalBlockSizeException expected) {
2610                }
2611            } else if (provider.equals("AndroidOpenSSL")) {
2612                assertNull(c.doFinal());
2613
2614                c.update(new byte[0]);
2615                assertNull(c.doFinal());
2616            } else {
2617                throw new AssertionError("Define your behavior here for " + provider);
2618            }
2619        }
2620
2621        // .doFinal(input)
2622        {
2623            final byte[] actualPlaintext = c.doFinal(p.ciphertext);
2624            assertEquals(Arrays.toString(p.plaintext), Arrays.toString(actualPlaintext));
2625        }
2626
2627        // .doFinal(input, offset, len, output)
2628        {
2629            final byte[] largerThanCiphertext = new byte[p.ciphertext.length + 5];
2630            System.arraycopy(p.ciphertext, 0, largerThanCiphertext, 5, p.ciphertext.length);
2631
2632            final byte[] actualPlaintext = new byte[c.getOutputSize(p.ciphertext.length)];
2633            assertEquals(p.plaintext.length,
2634                    c.doFinal(largerThanCiphertext, 5, p.ciphertext.length, actualPlaintext));
2635            assertEquals(Arrays.toString(p.plaintext),
2636                    Arrays.toString(Arrays.copyOfRange(actualPlaintext, 0, p.plaintext.length)));
2637        }
2638
2639        // .doFinal(input, offset, len, output, offset)
2640        {
2641            final byte[] largerThanCiphertext = new byte[p.ciphertext.length + 10];
2642            System.arraycopy(p.ciphertext, 0, largerThanCiphertext, 5, p.ciphertext.length);
2643
2644            final byte[] actualPlaintext = new byte[c.getOutputSize(p.ciphertext.length) + 2];
2645            assertEquals(p.plaintext.length,
2646                    c.doFinal(largerThanCiphertext, 5, p.ciphertext.length, actualPlaintext, 1));
2647            assertEquals(Arrays.toString(p.plaintext),
2648                    Arrays.toString(Arrays.copyOfRange(actualPlaintext, 1, p.plaintext.length + 1)));
2649        }
2650
2651        Cipher cNoPad = Cipher.getInstance(
2652                getCipherTransformationWithNoPadding(p.transformation), provider);
2653        cNoPad.init(Cipher.DECRYPT_MODE, key, spec);
2654
2655        final byte[] actualPlaintextPadded = cNoPad.doFinal(p.ciphertext);
2656        assertEquals(provider + ":" + cNoPad.getAlgorithm(), Arrays.toString(p.plaintextPadded),
2657                Arrays.toString(actualPlaintextPadded));
2658
2659        // Test wrapping a key. Every cipher should be able to wrap.
2660        {
2661            // Generate a small SecretKey for AES.
2662            KeyGenerator kg = KeyGenerator.getInstance("AES");
2663            kg.init(128);
2664            SecretKey sk = kg.generateKey();
2665
2666            // Wrap it
2667            c.init(Cipher.WRAP_MODE, key, spec);
2668            byte[] cipherText = c.wrap(sk);
2669
2670            // Unwrap it
2671            c.init(Cipher.UNWRAP_MODE, key, spec);
2672            Key decryptedKey = c.unwrap(cipherText, sk.getAlgorithm(), Cipher.SECRET_KEY);
2673
2674            assertEquals(
2675                    "sk.getAlgorithm()=" + sk.getAlgorithm() + " decryptedKey.getAlgorithm()="
2676                            + decryptedKey.getAlgorithm() + " encryptKey.getEncoded()="
2677                            + Arrays.toString(sk.getEncoded()) + " decryptedKey.getEncoded()="
2678                            + Arrays.toString(decryptedKey.getEncoded()), sk, decryptedKey);
2679        }
2680    }
2681
2682    /**
2683     * Gets the Cipher transformation with the same algorithm and mode as the provided one but
2684     * which uses no padding.
2685     */
2686    private static String getCipherTransformationWithNoPadding(String transformation) {
2687        // The transformation is assumed to be in the Algorithm/Mode/Padding format.
2688        int paddingModeDelimiterIndex = transformation.lastIndexOf('/');
2689        if (paddingModeDelimiterIndex == -1) {
2690            fail("No padding mode delimiter: " + transformation);
2691        }
2692        String paddingMode = transformation.substring(paddingModeDelimiterIndex + 1);
2693        if (!paddingMode.toLowerCase().endsWith("padding")) {
2694            fail("No padding mode specified:" + transformation);
2695        }
2696        return transformation.substring(0, paddingModeDelimiterIndex) + "/NoPadding";
2697    }
2698
2699    public void testCipher_updateAAD_BeforeInit_Failure() throws Exception {
2700        Cipher c = Cipher.getInstance("AES/ECB/NoPadding");
2701
2702        try {
2703            c.updateAAD((byte[]) null);
2704            fail("should not be able to call updateAAD before Cipher is initialized");
2705        } catch (IllegalArgumentException expected) {
2706        }
2707
2708        try {
2709            c.updateAAD((ByteBuffer) null);
2710            fail("should not be able to call updateAAD before Cipher is initialized");
2711        } catch (IllegalStateException expected) {
2712        }
2713
2714        try {
2715            c.updateAAD(new byte[8]);
2716            fail("should not be able to call updateAAD before Cipher is initialized");
2717        } catch (IllegalStateException expected) {
2718        }
2719
2720        try {
2721            c.updateAAD(null, 0, 8);
2722            fail("should not be able to call updateAAD before Cipher is initialized");
2723        } catch (IllegalStateException expected) {
2724        }
2725
2726        ByteBuffer bb = ByteBuffer.allocate(8);
2727        try {
2728            c.updateAAD(bb);
2729            fail("should not be able to call updateAAD before Cipher is initialized");
2730        } catch (IllegalStateException expected) {
2731        }
2732    }
2733
2734    public void testCipher_updateAAD_AfterInit_Failure() throws Exception {
2735        Cipher c = Cipher.getInstance("AES/ECB/NoPadding");
2736        c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[128 / 8], "AES"));
2737
2738        try {
2739            c.updateAAD((byte[]) null);
2740            fail("should not be able to call updateAAD with null input");
2741        } catch (IllegalArgumentException expected) {
2742        }
2743
2744        try {
2745            c.updateAAD((ByteBuffer) null);
2746            fail("should not be able to call updateAAD with null input");
2747        } catch (IllegalArgumentException expected) {
2748        }
2749
2750        try {
2751            c.updateAAD(null, 0, 8);
2752            fail("should not be able to call updateAAD with null input");
2753        } catch (IllegalArgumentException expected) {
2754        }
2755
2756        try {
2757            c.updateAAD(new byte[8], -1, 7);
2758            fail("should not be able to call updateAAD with invalid offset");
2759        } catch (IllegalArgumentException expected) {
2760        }
2761
2762        try {
2763            c.updateAAD(new byte[8], 0, -1);
2764            fail("should not be able to call updateAAD with negative length");
2765        } catch (IllegalArgumentException expected) {
2766        }
2767
2768        try {
2769            c.updateAAD(new byte[8], 0, 8 + 1);
2770            fail("should not be able to call updateAAD with too large length");
2771        } catch (IllegalArgumentException expected) {
2772        }
2773    }
2774
2775    public void testCipher_ShortBlock_Failure() throws Exception {
2776        for (String provider : AES_PROVIDERS) {
2777            testCipher_ShortBlock_Failure(provider);
2778        }
2779    }
2780
2781    private void testCipher_ShortBlock_Failure(String provider) throws Exception {
2782        final ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();
2783        PrintStream out = new PrintStream(errBuffer);
2784        for (CipherTestParam p : CIPHER_TEST_PARAMS) {
2785            try {
2786                checkCipher_ShortBlock_Failure(p, provider);
2787            } catch (Exception e) {
2788                out.append("Error encountered checking " + p.transformation + ", keySize="
2789                        + (p.key.length * 8)
2790                        + " with provider " + provider + "\n");
2791                e.printStackTrace(out);
2792            }
2793        }
2794        out.flush();
2795        if (errBuffer.size() > 0) {
2796            throw new Exception("Errors encountered:\n\n" + errBuffer.toString() + "\n\n");
2797        }
2798    }
2799
2800    private void checkCipher_ShortBlock_Failure(CipherTestParam p, String provider) throws Exception {
2801        SecretKey key = new SecretKeySpec(p.key, "AES");
2802        Cipher c = Cipher.getInstance(
2803                getCipherTransformationWithNoPadding(p.transformation), provider);
2804        if (c.getBlockSize() == 0) {
2805            return;
2806        }
2807
2808        c.init(Cipher.ENCRYPT_MODE, key);
2809        try {
2810            c.doFinal(new byte[] { 0x01, 0x02, 0x03 });
2811            fail("Should throw IllegalBlockSizeException on wrong-sized block; provider="
2812                    + provider);
2813        } catch (IllegalBlockSizeException expected) {
2814        }
2815    }
2816
2817    public void testAES_ECB_PKCS5Padding_ShortBuffer_Failure() throws Exception {
2818        for (String provider : AES_PROVIDERS) {
2819            testAES_ECB_PKCS5Padding_ShortBuffer_Failure(provider);
2820        }
2821    }
2822
2823    private void testAES_ECB_PKCS5Padding_ShortBuffer_Failure(String provider) throws Exception {
2824        SecretKey key = new SecretKeySpec(AES_128_KEY, "AES");
2825        Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding", provider);
2826        c.init(Cipher.ENCRYPT_MODE, key);
2827
2828        final byte[] fragmentOutput = c.update(AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext);
2829        if (fragmentOutput != null) {
2830            assertEquals(0, fragmentOutput.length);
2831        }
2832
2833        // Provide null buffer.
2834        {
2835            try {
2836                c.doFinal(null, 0);
2837                fail("Should throw NullPointerException on null output buffer");
2838            } catch (NullPointerException expected) {
2839            } catch (IllegalArgumentException expected) {
2840            }
2841        }
2842
2843        // Provide short buffer.
2844        {
2845            final byte[] output = new byte[c.getBlockSize() - 1];
2846            try {
2847                c.doFinal(output, 0);
2848                fail("Should throw ShortBufferException on short output buffer");
2849            } catch (ShortBufferException expected) {
2850            }
2851        }
2852
2853        // Start 1 byte into output buffer.
2854        {
2855            final byte[] output = new byte[c.getBlockSize()];
2856            try {
2857                c.doFinal(output, 1);
2858                fail("Should throw ShortBufferException on short output buffer");
2859            } catch (ShortBufferException expected) {
2860            }
2861        }
2862
2863        // Should keep data for real output buffer
2864        {
2865            final byte[] output = new byte[c.getBlockSize()];
2866            assertEquals(AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted.length, c.doFinal(output, 0));
2867            assertTrue(Arrays.equals(AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted, output));
2868        }
2869    }
2870
2871    public void testAES_ECB_NoPadding_IncrementalUpdate_Success() throws Exception {
2872        for (String provider : AES_PROVIDERS) {
2873            testAES_ECB_NoPadding_IncrementalUpdate_Success(provider);
2874        }
2875    }
2876
2877    private void testAES_ECB_NoPadding_IncrementalUpdate_Success(String provider) throws Exception {
2878        SecretKey key = new SecretKeySpec(AES_128_KEY, "AES");
2879        Cipher c = Cipher.getInstance("AES/ECB/NoPadding", provider);
2880        assertEquals(provider, c.getProvider().getName());
2881        c.init(Cipher.ENCRYPT_MODE, key);
2882
2883        for (int i = 0; i < AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded.length - 1; i++) {
2884            final byte[] outputFragment = c.update(AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded, i, 1);
2885            if (outputFragment != null) {
2886                assertEquals(0, outputFragment.length);
2887            }
2888        }
2889
2890        final byte[] output = c.doFinal(AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded,
2891                AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded.length - 1, 1);
2892        assertNotNull(provider, output);
2893        assertEquals(provider, AES_128_ECB_PKCS5Padding_TestVector_1_Plaintext_Padded.length,
2894                output.length);
2895
2896        assertTrue(provider, Arrays.equals(AES_128_ECB_PKCS5Padding_TestVector_1_Encrypted, output));
2897    }
2898
2899    private static final byte[] AES_IV_ZEROES = new byte[] {
2900            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
2901            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
2902            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
2903    };
2904
2905    public void testAES_ECB_NoPadding_IvParameters_Failure() throws Exception {
2906        for (String provider : AES_PROVIDERS) {
2907            testAES_ECB_NoPadding_IvParameters_Failure(provider);
2908        }
2909    }
2910
2911    private void testAES_ECB_NoPadding_IvParameters_Failure(String provider) throws Exception {
2912        SecretKey key = new SecretKeySpec(AES_128_KEY, "AES");
2913        Cipher c = Cipher.getInstance("AES/ECB/NoPadding", provider);
2914
2915        AlgorithmParameterSpec spec = new IvParameterSpec(AES_IV_ZEROES);
2916        try {
2917            c.init(Cipher.ENCRYPT_MODE, key, spec);
2918            fail("Should not accept an IV in ECB mode; provider=" + provider);
2919        } catch (InvalidAlgorithmParameterException expected) {
2920        }
2921    }
2922
2923    public void testRC4_MultipleKeySizes() throws Exception {
2924        final int SMALLEST_KEY_SIZE = 40;
2925        final int LARGEST_KEY_SIZE = 1024;
2926
2927        /* Make an array of keys for our tests */
2928        SecretKey[] keys = new SecretKey[LARGEST_KEY_SIZE - SMALLEST_KEY_SIZE];
2929        {
2930            KeyGenerator kg = KeyGenerator.getInstance("ARC4");
2931            for (int keysize = SMALLEST_KEY_SIZE; keysize < LARGEST_KEY_SIZE; keysize++) {
2932                final int index = keysize - SMALLEST_KEY_SIZE;
2933                kg.init(keysize);
2934                keys[index] = kg.generateKey();
2935            }
2936        }
2937
2938        /*
2939         * Use this to compare the output of the first provider against
2940         * subsequent providers.
2941         */
2942        String[] expected = new String[LARGEST_KEY_SIZE - SMALLEST_KEY_SIZE];
2943
2944        /* Find all providers that provide ARC4. We must have at least one! */
2945        Map<String, String> filter = new HashMap<String, String>();
2946        filter.put("Cipher.ARC4", "");
2947        Provider[] providers = Security.getProviders(filter);
2948        assertTrue("There must be security providers of Cipher.ARC4", providers.length > 0);
2949
2950        /* Keep track of this for later error messages */
2951        String firstProvider = providers[0].getName();
2952
2953        for (Provider p : providers) {
2954            Cipher c = Cipher.getInstance("ARC4", p);
2955
2956            for (int keysize = SMALLEST_KEY_SIZE; keysize < LARGEST_KEY_SIZE; keysize++) {
2957                final int index = keysize - SMALLEST_KEY_SIZE;
2958                final SecretKey sk = keys[index];
2959
2960                /*
2961                 * Test that encryption works. Donig this in a loop also has the
2962                 * benefit of testing that re-initialization works for this
2963                 * cipher.
2964                 */
2965                c.init(Cipher.ENCRYPT_MODE, sk);
2966                byte[] cipherText = c.doFinal(ORIGINAL_PLAIN_TEXT);
2967                assertNotNull(cipherText);
2968
2969                /*
2970                 * Compare providers against eachother to make sure they're all
2971                 * in agreement. This helps when you add a brand new provider.
2972                 */
2973                if (expected[index] == null) {
2974                    expected[index] = Arrays.toString(cipherText);
2975                } else {
2976                    assertEquals(firstProvider + " should output the same as " + p.getName()
2977                            + " for key size " + keysize, expected[index],
2978                            Arrays.toString(cipherText));
2979                }
2980
2981                c.init(Cipher.DECRYPT_MODE, sk);
2982                byte[] actualPlaintext = c.doFinal(cipherText);
2983                assertEquals("Key size: " + keysize, Arrays.toString(ORIGINAL_PLAIN_TEXT),
2984                        Arrays.toString(actualPlaintext));
2985            }
2986        }
2987    }
2988}
2989