1 /* 2 * Copyright (c) 2003, 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 4894151 27 * @summary encryption/decryption test for OAEP 28 * @author Andreas Sterbenz 29 */ 30 31 import java.util.*; 32 33 import java.security.*; 34 35 import javax.crypto.*; 36 37 public class TestOAEP { 38 39 private static Provider cp; 40 41 private static PrivateKey privateKey; 42 43 private static PublicKey publicKey; 44 45 private static Random random = new Random(); 46 47 public static void main(String[] args) throws Exception { 48 long start = System.currentTimeMillis(); 49 cp = Security.getProvider("SunJCE"); 50 System.out.println("Testing provider " + cp.getName() + "..."); 51 Provider kfp = Security.getProvider("SunRsaSign"); 52 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", kfp); 53 kpg.initialize(768); 54 KeyPair kp = kpg.generateKeyPair(); 55 privateKey = kp.getPrivate(); 56 publicKey = kp.getPublic(); 57 58 Cipher.getInstance("RSA/ECB/OAEPwithMD5andMGF1Padding"); 59 Cipher.getInstance("RSA/ECB/OAEPwithSHA1andMGF1Padding"); 60 Cipher.getInstance("RSA/ECB/OAEPwithSHA-1andMGF1Padding"); 61 Cipher.getInstance("RSA/ECB/OAEPwithSHA-224andMGF1Padding"); 62 Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding"); 63 Cipher.getInstance("RSA/ECB/OAEPwithSHA-384andMGF1Padding"); 64 Cipher.getInstance("RSA/ECB/OAEPwithSHA-512andMGF1Padding"); 65 66 // basic test using MD5 67 testEncryptDecrypt("MD5", 0); 68 testEncryptDecrypt("MD5", 16); 69 testEncryptDecrypt("MD5", 62); 70 try { 71 testEncryptDecrypt("MD5", 63); 72 throw new Exception("Unexpectedly completed call"); 73 } catch (IllegalBlockSizeException e) { 74 // ok 75 System.out.println(e); 76 } 77 78 // basic test using SHA-1 79 testEncryptDecrypt("SHA1", 0); 80 testEncryptDecrypt("SHA1", 16); 81 testEncryptDecrypt("SHA1", 54); 82 try { 83 testEncryptDecrypt("SHA1", 55); 84 throw new Exception("Unexpectedly completed call"); 85 } catch (IllegalBlockSizeException e) { 86 // ok 87 System.out.println(e); 88 } 89 // tests alias works 90 testEncryptDecrypt("SHA-1", 16); 91 92 // basic test using SHA-224 93 testEncryptDecrypt("SHA-224", 0); 94 testEncryptDecrypt("SHA-224", 16); 95 testEncryptDecrypt("SHA-224", 38); 96 try { 97 testEncryptDecrypt("SHA-224", 39); 98 throw new Exception("Unexpectedly completed call"); 99 } catch (IllegalBlockSizeException e) { 100 // ok 101 System.out.println(e); 102 } 103 104 // basic test using SHA-256 105 testEncryptDecrypt("SHA-256", 0); 106 testEncryptDecrypt("SHA-256", 16); 107 testEncryptDecrypt("SHA-256", 30); 108 try { 109 testEncryptDecrypt("SHA-256", 31); 110 throw new Exception("Unexpectedly completed call"); 111 } catch (IllegalBlockSizeException e) { 112 // ok 113 System.out.println(e); 114 } 115 116 // 768 bit key too short for OAEP with 64 byte digest 117 try { 118 testEncryptDecrypt("SHA-512", 1); 119 throw new Exception("Unexpectedly completed call"); 120 } catch (InvalidKeyException e) { 121 // ok 122 System.out.println(e); 123 } 124 125 Cipher c; 126 byte[] enc; 127 byte[] data = new byte[16]; 128 random.nextBytes(data); 129 130 try { 131 c = Cipher.getInstance("RSA/ECB/OAEPwithFOOandMGF1Padding", cp); 132 throw new Exception("Unexpectedly completed call"); 133 } catch (NoSuchPaddingException e) { 134 // ok 135 System.out.println(e); 136 } 137 138 c = Cipher.getInstance("RSA/ECB/OAEPwithMD5andMGF1Padding", cp); 139 // cannot "sign" using OAEP 140 try { 141 c.init(Cipher.ENCRYPT_MODE, privateKey); 142 throw new Exception("Unexpectedly completed call"); 143 } catch (InvalidKeyException e) { 144 // ok 145 System.out.println(e); 146 } 147 148 // cannot "verify" using OAEP 149 try { 150 c.init(Cipher.DECRYPT_MODE, publicKey); 151 throw new Exception("Unexpectedly completed call"); 152 } catch (InvalidKeyException e) { 153 // ok 154 System.out.println(e); 155 } 156 157 // decryption failure 158 c.init(Cipher.DECRYPT_MODE, privateKey); 159 try { 160 c.doFinal(data); 161 throw new Exception("Unexpectedly completed call"); 162 } catch (BadPaddingException e) { 163 // ok 164 System.out.println(e); 165 } 166 167 // wrong hash length 168 c.init(Cipher.ENCRYPT_MODE, publicKey); 169 enc = c.doFinal(data); 170 c = Cipher.getInstance("RSA/ECB/OAEPwithSHA1andMGF1Padding", cp); 171 c.init(Cipher.DECRYPT_MODE, privateKey); 172 try { 173 c.doFinal(enc); 174 throw new Exception("Unexpectedly completed call"); 175 } catch (BadPaddingException e) { 176 // ok 177 System.out.println(e); 178 } 179 180 /* MD2 not supported with OAEP 181 // wrong hash value 182 c = Cipher.getInstance("RSA/ECB/OAEPwithMD2andMGF1Padding", cp); 183 c.init(Cipher.DECRYPT_MODE, privateKey); 184 try { 185 c.doFinal(enc); 186 throw new Exception("Unexpectedly completed call"); 187 } catch (BadPaddingException e) { 188 // ok 189 System.out.println(e); 190 } 191 */ 192 193 // wrong padding type 194 c = Cipher.getInstance("RSA/ECB/PKCS1Padding", cp); 195 c.init(Cipher.ENCRYPT_MODE, publicKey); 196 enc = c.doFinal(data); 197 c = Cipher.getInstance("RSA/ECB/OAEPwithSHA1andMGF1Padding", cp); 198 c.init(Cipher.DECRYPT_MODE, privateKey); 199 try { 200 c.doFinal(enc); 201 throw new Exception("Unexpectedly completed call"); 202 } catch (BadPaddingException e) { 203 // ok 204 System.out.println(e); 205 } 206 207 long stop = System.currentTimeMillis(); 208 System.out.println("Done (" + (stop - start) + " ms)."); 209 } 210 211 // NOTE: OAEP can process up to (modLen - 2*digestLen - 2) bytes of data 212 private static void testEncryptDecrypt(String hashAlg, int dataLength) throws Exception { 213 System.out.println("Testing OAEP with hash " + hashAlg + ", " + dataLength + " bytes"); 214 Cipher c = Cipher.getInstance("RSA/ECB/OAEPwith" + hashAlg + "andMGF1Padding", cp); 215 c.init(Cipher.ENCRYPT_MODE, publicKey); 216 byte[] data = new byte[dataLength]; 217 byte[] enc = c.doFinal(data); 218 c.init(Cipher.DECRYPT_MODE, privateKey); 219 byte[] dec = c.doFinal(enc); 220 if (Arrays.equals(data, dec) == false) { 221 throw new Exception("Data does not match"); 222 } 223 } 224 }