CTR.java revision 11822:110f7f35760f
1189251Ssam/*
2189251Ssam * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3214734Srpaulo * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4189251Ssam *
5252726Srpaulo * This code is free software; you can redistribute it and/or modify it
6252726Srpaulo * under the terms of the GNU General Public License version 2 only, as
7189251Ssam * published by the Free Software Foundation.
8189251Ssam *
9189251Ssam * This code is distributed in the hope that it will be useful, but WITHOUT
10189251Ssam * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11189251Ssam * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12189251Ssam * version 2 for more details (a copy is included in the LICENSE file that
13189251Ssam * accompanied this code).
14189251Ssam *
15189251Ssam * You should have received a copy of the GNU General Public License version
16189251Ssam * 2 along with this work; if not, write to the Free Software Foundation,
17189251Ssam * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18189251Ssam *
19189251Ssam * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20189251Ssam * or visit www.oracle.com if you need additional information or have any
21189251Ssam * questions.
22189251Ssam */
23189251Ssam
24189251Ssamimport java.security.InvalidAlgorithmParameterException;
25189251Ssamimport java.security.InvalidKeyException;
26189251Ssamimport java.security.NoSuchAlgorithmException;
27189251Ssamimport java.security.NoSuchProviderException;
28189251Ssamimport java.security.spec.AlgorithmParameterSpec;
29189251Ssamimport java.util.Arrays;
30214734Srpauloimport java.util.Random;
31189251Ssamimport javax.crypto.BadPaddingException;
32214734Srpauloimport javax.crypto.Cipher;
33189251Ssamimport javax.crypto.IllegalBlockSizeException;
34189251Ssamimport javax.crypto.KeyGenerator;
35189251Ssamimport javax.crypto.NoSuchPaddingException;
36189251Ssamimport javax.crypto.SecretKey;
37189251Ssamimport javax.crypto.ShortBufferException;
38189251Ssamimport javax.crypto.spec.IvParameterSpec;
39189251Ssam
40214734Srpaulo
41189251Ssam/**
42214734Srpaulo * @test
43189251Ssam * @bug 8043836
44214734Srpaulo * @summary Test AES ciphers with 4 different modes with NoPadding. Check if
45214734Srpaulo *          data before encryption and after decryption is the same.
46189251Ssam * @key randomness
47189251Ssam */
48189251Ssam
49189251Ssampublic class CTR {
50189251Ssam
51214734Srpaulo    private static final String ALGORITHM = "AES";
52189251Ssam
53214734Srpaulo    private static final String PROVIDER = "SunJCE";
54214734Srpaulo
55189251Ssam    private static final String[] MODES = {"CTR","CFB24","OFB32","GCM"};
56189251Ssam
57189251Ssam    private static final String PADDING = "NoPadding";
58189251Ssam
59189251Ssam
60189251Ssam    private static final int KEY_LENGTH = 128;
61189251Ssam
62189251Ssam    public static void main(String argv[]) throws Exception {
63189251Ssam        CTR test = new CTR();
64189251Ssam        for (String mode : MODES) {
65189251Ssam            test.runTest(ALGORITHM, mode, PADDING);
66189251Ssam        }
67189251Ssam    }
68189251Ssam
69189251Ssam
70189251Ssam    public void runTest(String algo, String mo, String pad) throws Exception {
71189251Ssam        Cipher ci = null;
72189251Ssam        byte[] iv = null;
73189251Ssam        AlgorithmParameterSpec aps = null;
74189251Ssam        SecretKey key = null;
75189251Ssam
76189251Ssam        try {
77214734Srpaulo            Random rdm = new Random();
78189251Ssam            byte[] plainText;
79214734Srpaulo
80214734Srpaulo            ci = Cipher.getInstance(algo + "/" + mo + "/" + pad, PROVIDER);
81189251Ssam            KeyGenerator kg = KeyGenerator.getInstance(algo, PROVIDER);
82189251Ssam            kg.init(KEY_LENGTH);
83189251Ssam            key = kg.generateKey();
84189251Ssam
85189251Ssam            for (int i = 0; i < 15; i++) {
86189251Ssam                plainText = new byte[1600 + i + 1];
87189251Ssam                rdm.nextBytes(plainText);
88189251Ssam
89189251Ssam                if (!mo.equalsIgnoreCase("GCM")) {
90189251Ssam                    ci.init(Cipher.ENCRYPT_MODE, key, aps);
91189251Ssam                } else {
92189251Ssam                    ci.init(Cipher.ENCRYPT_MODE, key);
93189251Ssam                }
94189251Ssam
95189251Ssam                byte[] cipherText = new byte[ci.getOutputSize(plainText.length)];
96189251Ssam                int offset = ci.update(plainText, 0, plainText.length,
97189251Ssam                        cipherText, 0);
98189251Ssam
99189251Ssam                ci.doFinal(cipherText, offset);
100189251Ssam
101189251Ssam                if (!mo.equalsIgnoreCase("ECB")) {
102189251Ssam                    iv = ci.getIV();
103189251Ssam                    aps = new IvParameterSpec(iv);
104189251Ssam                } else {
105189251Ssam                    aps = null;
106189251Ssam                }
107189251Ssam
108189251Ssam                if (!mo.equalsIgnoreCase("GCM")) {
109189251Ssam                    ci.init(Cipher.DECRYPT_MODE, key, aps);
110189251Ssam                } else {
111189251Ssam                    ci.init(Cipher.DECRYPT_MODE, key, ci.getParameters());
112189251Ssam                }
113189251Ssam
114189251Ssam                byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)];
115189251Ssam                int len = ci.doFinal(cipherText, 0, cipherText.length,
116189251Ssam                        recoveredText);
117189251Ssam                byte[] tmp = new byte[len];
118189251Ssam
119189251Ssam                for (int j = 0; j < len; j++) {
120189251Ssam                    tmp[j] = recoveredText[j];
121189251Ssam                }
122189251Ssam                Arrays.toString(plainText);
123189251Ssam                if (!java.util.Arrays.equals(plainText, tmp)) {
124189251Ssam                    System.out.println("Original: ");
125189251Ssam                    dumpBytes(plainText);
126189251Ssam                    System.out.println("Recovered: ");
127189251Ssam                    dumpBytes(tmp);
128189251Ssam                    throw new RuntimeException("Original text is not equal with recovered text, with mode:" + mo);
129189251Ssam                }
130189251Ssam            }
131189251Ssam        } catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException
132189251Ssam                | InvalidKeyException | InvalidAlgorithmParameterException
133189251Ssam                | ShortBufferException | IllegalBlockSizeException
134189251Ssam                | BadPaddingException e) {
135189251Ssam            System.out.println("Test failed!");
136189251Ssam            throw e;
137252726Srpaulo        }
138252726Srpaulo    }
139189251Ssam
140189251Ssam    private void dumpBytes(byte[] bytes){
141189251Ssam        for (byte b : bytes){
142189251Ssam            System.out.print(Integer.toHexString(b));
143189251Ssam        }
144189251Ssam        System.out.println();
145189251Ssam    }
146189251Ssam}
147189251Ssam