1/*
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @bug 6383200
27 * @summary PBE: need new algorithm support in password based encryption
28 */
29import java.security.*;
30import java.util.Arrays;
31import javax.crypto.*;
32import javax.crypto.spec.*;
33
34public class PBES2Test {
35
36    private static final String[] algos = {
37        "PBEWithHmacSHA1AndAES_128",
38        "PBEWithHmacSHA224AndAES_128",
39        "PBEWithHmacSHA256AndAES_128",
40        "PBEWithHmacSHA384AndAES_128",
41        "PBEWithHmacSHA512AndAES_128"
42    };
43    private static final byte[] ivBytes = {
44        0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
45        0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,
46    };
47
48    public static final void main(String[] args) throws Exception {
49        for (String algo : algos) {
50            test(algo, true);  // salt, ic, IV supplied by the application
51            test(algo, false); // salt, ic, IV generated by the implementation
52        }
53    }
54
55    private static final void test(String algo, boolean suppliedParams)
56        throws Exception {
57
58        System.out.println("***********************************************");
59        System.out.println(algo +
60            (suppliedParams ? "  [algorithm parameters are supplied]\n"
61                            : "  [algorithm parameters are generated]\n"));
62        int iterationCount = 1000;
63        byte[] salt = new byte[]{ 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 };
64
65        // Create PBE key
66        PBEKeySpec pbeKeySpec = new PBEKeySpec("mypassword".toCharArray());
67        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algo);
68        SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec);
69        byte[] pbeKeyBytes = pbeKey.getEncoded();
70        System.out.println("   key[" + pbeKeyBytes.length + "]: " +
71            String.format("0x%0" + (pbeKeyBytes.length * 2) + "x",
72                new java.math.BigInteger(1, pbeKeyBytes)));
73
74        // Create PBE cipher
75        System.out.println("Encrypting...");
76        Cipher pbeCipher = Cipher.getInstance(algo);
77        if (suppliedParams) {
78            pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey,
79                new PBEParameterSpec(salt, iterationCount,
80                    new IvParameterSpec(ivBytes)));
81        } else {
82            pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey);
83        }
84
85        // Encrypt
86        byte[] cleartext = "This is just an example".getBytes();
87        System.out.println("  text[" + cleartext.length + "]: " +
88            String.format("0x%0" + (cleartext.length * 2) + "x",
89                new java.math.BigInteger(1, cleartext)));
90
91        byte[] ciphertext = pbeCipher.doFinal(cleartext);
92        System.out.println("c'text[" + ciphertext.length + "]: " +
93            String.format("0x%0" + (ciphertext.length * 2) + "x",
94                new java.math.BigInteger(1, ciphertext)));
95
96        AlgorithmParameters aps = pbeCipher.getParameters();
97
98        byte[] iv;
99        if (suppliedParams) {
100            iv = ivBytes;
101        } else {
102            PBEParameterSpec pbeSpec =
103                aps.getParameterSpec(PBEParameterSpec.class);
104            salt = pbeSpec.getSalt();
105            iterationCount = pbeSpec.getIterationCount();
106            IvParameterSpec ivSpec =
107                (IvParameterSpec) pbeSpec.getParameterSpec();
108            iv = ivSpec.getIV();
109        }
110        System.out.println("  salt[" + salt.length + "]: " +
111            String.format("0x%0" + (salt.length * 2) + "x",
112                new java.math.BigInteger(1, salt)));
113        System.out.println("iterationCount=" + iterationCount);
114        System.out.println("    iv[" + iv.length + "]: " +
115            String.format("0x%0" + (iv.length * 2) + "x",
116                new java.math.BigInteger(1, iv)));
117
118        // Decrypt
119        System.out.println("Decrypting...");
120        Cipher pbeCipher2 = Cipher.getInstance(algo);
121        pbeCipher2.init(Cipher.DECRYPT_MODE, pbeKey, aps);
122        byte[] cleartext2 = pbeCipher2.doFinal(ciphertext);
123        System.out.println("  text[" + cleartext2.length + "]: " +
124            String.format("0x%0" + (cleartext2.length * 2) + "x",
125                new java.math.BigInteger(1, cleartext2)));
126
127        if (Arrays.equals(cleartext, cleartext2)) {
128            System.out.println(
129                "\nPass: decrypted ciphertext matches the original text\n");
130        } else {
131            throw new Exception(
132                "Fail: decrypted ciphertext does NOT match the original text");
133        }
134    }
135}
136