1/*
2 * Copyright (c) 2007, 2015, 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
24import java.security.AlgorithmParameters;
25import java.util.Arrays;
26import javax.crypto.SecretKey;
27import javax.crypto.Cipher;
28import javax.crypto.KeyGenerator;
29import javax.crypto.SealedObject;
30
31/*
32 * @test
33 * @bug 8048596
34 * @summary Check if the seal/unseal feature works properly in AEAD/GCM mode.
35 */
36public class SealedObjectTest {
37
38    private static final String AES = "AES";
39    private static final String TRANSFORMATION = "AES/GCM/NoPadding";
40    private static final String PROVIDER = "SunJCE";
41    private static final int KEY_LENGTH = 128;
42
43    public static void main(String[] args) throws Exception {
44        doTest();
45    }
46
47    /*
48     * Run the test:
49     * - init a cipher with AES/GCM/NoPadding transformation
50     * - seal an object
51     * - check if we can't seal it again with the same key/IV
52     * - unseal the object using different methods of SealedObject class
53     * - check if the original and sealed objects are equal
54     */
55    static void doTest() throws Exception {
56        // init a secret Key
57        KeyGenerator kg = KeyGenerator.getInstance(AES, PROVIDER);
58        kg.init(KEY_LENGTH);
59        SecretKey key = kg.generateKey();
60
61        // initialization
62        Cipher cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);
63        cipher.init(Cipher.ENCRYPT_MODE, key);
64        AlgorithmParameters params = cipher.getParameters();
65
66        // seal an object
67        SealedObject so = new SealedObject(key, cipher);
68        try {
69            // check if we can't seal it again with the same key/IV
70            so = new SealedObject(key, cipher);
71            throw new RuntimeException(
72                    "FAILED: expected IllegalStateException hasn't "
73                            + "been thrown");
74        } catch (IllegalStateException ise) {
75            System.out.println("Expected exception when seal it again with"
76                    + " the same key/IV: " + ise);
77        }
78
79        // unseal the object using getObject(Cipher) and compare
80        cipher.init(Cipher.DECRYPT_MODE, key, params);
81        SecretKey unsealedKey = (SecretKey) so.getObject(cipher);
82        assertKeysSame(unsealedKey, key, "SealedObject.getObject(Cipher)");
83
84        // unseal the object using getObject(Key) and compare
85        unsealedKey = (SecretKey) so.getObject(key);
86        assertKeysSame(unsealedKey, key, "SealedObject.getObject(Key)");
87
88        // unseal the object using getObject(Key, String) and compare
89        unsealedKey = (SecretKey) so.getObject(key, PROVIDER);
90
91        assertKeysSame(unsealedKey, key,
92                "SealedObject.getObject(Key, String)");
93    }
94
95    /**
96     * Compare two SecretKey objects.
97     *
98     * @param key1 first key
99     * @param key2 second key
100     * @param meth method that was used for unsealing the SecretKey object
101     * @return true if key1 and key2 are the same, false otherwise.
102     */
103    static void assertKeysSame(SecretKey key1, SecretKey key2, String meth) {
104        if (!Arrays.equals(key1.getEncoded(), key2.getEncoded())) {
105            throw new RuntimeException(
106                    "FAILED: original and unsealed objects aren't the same for "
107                            + meth);
108        }
109    }
110}
111