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