1/*
2 * Copyright (c) 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.KeyFactory;
25import java.security.KeyPair;
26import java.security.KeyPairGenerator;
27import java.security.PrivateKey;
28import java.security.PublicKey;
29import java.security.interfaces.RSAKey;
30import java.security.interfaces.RSAPrivateKey;
31import java.security.interfaces.RSAPublicKey;
32import java.security.spec.RSAPrivateKeySpec;
33import java.security.spec.RSAPublicKeySpec;
34
35/**
36 * @test
37 * @bug 8044199
38 * @summary test if the private and public key size are the same as what is set
39 * through KeyPairGenerator.
40 * @run main KeySizeTest 512 10
41 * @run main KeySizeTest 768 10
42 * @run main KeySizeTest 1024 10
43 * @run main KeySizeTest 2048 5
44 * @run main KeySizeTest 4096 1
45 */
46public class KeySizeTest {
47
48    /**
49     * ALGORITHM name, fixed as RSA.
50     */
51    private static final String KEYALG = "RSA";
52
53    /**
54     * JDK default RSA Provider.
55     */
56    private static final String PROVIDER_NAME = "SunRsaSign";
57
58    public static void main(String[] args) throws Exception {
59        int iKeyPairSize = Integer.parseInt(args[0]);
60        int maxLoopCnt = Integer.parseInt(args[1]);
61
62        int failCount = 0;
63        KeyPairGenerator keyPairGen
64                = KeyPairGenerator.getInstance(KEYALG, PROVIDER_NAME);
65        keyPairGen.initialize(iKeyPairSize);
66        // Generate RSA keypair
67        KeyPair keyPair = keyPairGen.generateKeyPair();
68
69        // Get priavte and public keys
70        PrivateKey privateKey = keyPair.getPrivate();
71        PublicKey publicKey = keyPair.getPublic();
72        try {
73            if (!sizeTest(keyPair)) {
74                failCount++;
75            }
76        } catch (Exception ex) {
77            ex.printStackTrace(System.err);
78            failCount++;
79        }
80
81        for (int iCnt = 0; iCnt < maxLoopCnt; iCnt++) {
82
83            // Get keysize (modulus) of keys
84            KeyFactory keyFact = KeyFactory.getInstance(KEYALG, PROVIDER_NAME);
85
86            // Comparing binary length.
87            RSAPrivateKeySpec privateKeySpec
88                    = (RSAPrivateKeySpec) keyFact.getKeySpec(privateKey,
89                            RSAPrivateKeySpec.class);
90            int iPrivateKeySize = privateKeySpec.getModulus().bitLength();
91
92            RSAPublicKeySpec publicKeySpec
93                    = (RSAPublicKeySpec) keyFact.getKeySpec(publicKey,
94                            RSAPublicKeySpec.class);
95            int iPublicKeySize = publicKeySpec.getModulus().bitLength();
96
97            if ((iKeyPairSize != iPublicKeySize) || (iKeyPairSize != iPrivateKeySize)) {
98                System.err.println("iKeyPairSize : " + iKeyPairSize);
99                System.err.println("Generated a " + iPrivateKeySize
100                        + " bit RSA private key");
101                System.err.println("Generated a " + iPublicKeySize
102                        + " bit RSA public key");
103                failCount++;
104            }
105        }
106
107        if (failCount > 0) {
108            throw new RuntimeException("There are " + failCount + " tests failed.");
109        }
110    }
111
112    /**
113     * @param kpair test key pair.
114     * @return true if test passed. false if test failed.
115     */
116    private static boolean sizeTest(KeyPair kpair) {
117        RSAPrivateKey priv = (RSAPrivateKey) kpair.getPrivate();
118        RSAPublicKey pub = (RSAPublicKey) kpair.getPublic();
119
120        // test the getModulus method
121        if ((priv instanceof RSAKey) && (pub instanceof RSAKey)) {
122            if (!priv.getModulus().equals(pub.getModulus())) {
123                System.err.println("priv.getModulus() = " + priv.getModulus());
124                System.err.println("pub.getModulus() = " + pub.getModulus());
125                return false;
126            }
127        }
128        return true;
129    }
130}
131