1 /*
   2  * Copyright (c) 2014, 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     7088989
  27  * @summary Ensure the RSA ciphers and signatures works correctly
  28  */
  29 
  30 import java.io.*;
  31 import java.security.*;
  32 import java.security.spec.*;
  33 import java.util.*;
  34 import java.math.*;
  35 import javax.crypto.*;
  36 
  37 public class TestRSA extends UcryptoTest {
  38 
  39     // KAT
  40     private static final byte PLAINTEXT[] = Arrays.copyOf
  41         (new String("Known plaintext message utilized" +
  42                     "for RSA Encryption &  Decryption" +
  43                     "block, SHA1, SHA256, SHA384  and" +
  44                     "SHA512 RSA Signature KAT tests.").getBytes(), 128);
  45 
  46     private static final byte MOD[] = {
  47         (byte)0xd5, (byte)0x84, (byte)0x95, (byte)0x07, (byte)0xf4, (byte)0xd0,
  48         (byte)0x1f, (byte)0x82, (byte)0xf3, (byte)0x79, (byte)0xf4, (byte)0x99,
  49         (byte)0x48, (byte)0x10, (byte)0xe1, (byte)0x71, (byte)0xa5, (byte)0x62,
  50         (byte)0x22, (byte)0xa3, (byte)0x4b, (byte)0x00, (byte)0xe3, (byte)0x5b,
  51         (byte)0x3a, (byte)0xcc, (byte)0x10, (byte)0x83, (byte)0xe0, (byte)0xaf,
  52         (byte)0x61, (byte)0x13, (byte)0x54, (byte)0x6a, (byte)0xa2, (byte)0x6a,
  53         (byte)0x2c, (byte)0x5e, (byte)0xb3, (byte)0xcc, (byte)0xa3, (byte)0x71,
  54         (byte)0x9a, (byte)0xb2, (byte)0x3e, (byte)0x78, (byte)0xec, (byte)0xb5,
  55         (byte)0x0e, (byte)0x6e, (byte)0x31, (byte)0x3b, (byte)0x77, (byte)0x1f,
  56         (byte)0x6e, (byte)0x94, (byte)0x41, (byte)0x60, (byte)0xd5, (byte)0x6e,
  57         (byte)0xd9, (byte)0xc6, (byte)0xf9, (byte)0x29, (byte)0xc3, (byte)0x40,
  58         (byte)0x36, (byte)0x25, (byte)0xdb, (byte)0xea, (byte)0x0b, (byte)0x07,
  59         (byte)0xae, (byte)0x76, (byte)0xfd, (byte)0x99, (byte)0x29, (byte)0xf4,
  60         (byte)0x22, (byte)0xc1, (byte)0x1a, (byte)0x8f, (byte)0x05, (byte)0xfe,
  61         (byte)0x98, (byte)0x09, (byte)0x07, (byte)0x05, (byte)0xc2, (byte)0x0f,
  62         (byte)0x0b, (byte)0x11, (byte)0x83, (byte)0x39, (byte)0xca, (byte)0xc7,
  63         (byte)0x43, (byte)0x63, (byte)0xff, (byte)0x33, (byte)0x80, (byte)0xe7,
  64         (byte)0xc3, (byte)0x78, (byte)0xae, (byte)0xf1, (byte)0x73, (byte)0x52,
  65         (byte)0x98, (byte)0x1d, (byte)0xde, (byte)0x5c, (byte)0x53, (byte)0x6e,
  66         (byte)0x01, (byte)0x73, (byte)0x0d, (byte)0x12, (byte)0x7e, (byte)0x77,
  67         (byte)0x03, (byte)0xf1, (byte)0xef, (byte)0x1b, (byte)0xc8, (byte)0xa8,
  68         (byte)0x0f, (byte)0x97
  69     };
  70 
  71     private static final byte PUB_EXP[] = {(byte)0x01, (byte)0x00, (byte)0x01};
  72 
  73     private static final byte PRIV_EXP[] = {
  74         (byte)0x85, (byte)0x27, (byte)0x47, (byte)0x61, (byte)0x4c, (byte)0xd4,
  75         (byte)0xb5, (byte)0xb2, (byte)0x0e, (byte)0x70, (byte)0x91, (byte)0x8f,
  76         (byte)0x3d, (byte)0x97, (byte)0xf9, (byte)0x5f, (byte)0xcc, (byte)0x09,
  77         (byte)0x65, (byte)0x1c, (byte)0x7c, (byte)0x5b, (byte)0xb3, (byte)0x6d,
  78         (byte)0x63, (byte)0x3f, (byte)0x7b, (byte)0x55, (byte)0x22, (byte)0xbb,
  79         (byte)0x7c, (byte)0x48, (byte)0x77, (byte)0xae, (byte)0x80, (byte)0x56,
  80         (byte)0xc2, (byte)0x10, (byte)0xd5, (byte)0x03, (byte)0xdb, (byte)0x31,
  81         (byte)0xaf, (byte)0x8d, (byte)0x54, (byte)0xd4, (byte)0x48, (byte)0x99,
  82         (byte)0xa8, (byte)0xc4, (byte)0x23, (byte)0x43, (byte)0xb8, (byte)0x48,
  83         (byte)0x0b, (byte)0xc7, (byte)0xbc, (byte)0xf5, (byte)0xcc, (byte)0x64,
  84         (byte)0x72, (byte)0xbf, (byte)0x59, (byte)0x06, (byte)0x04, (byte)0x1c,
  85         (byte)0x32, (byte)0xf5, (byte)0x14, (byte)0x2e, (byte)0x6e, (byte)0xe2,
  86         (byte)0x0f, (byte)0x5c, (byte)0xde, (byte)0x36, (byte)0x3c, (byte)0x6e,
  87         (byte)0x7c, (byte)0x4d, (byte)0xcc, (byte)0xd3, (byte)0x00, (byte)0x6e,
  88         (byte)0xe5, (byte)0x45, (byte)0x46, (byte)0xef, (byte)0x4d, (byte)0x25,
  89         (byte)0x46, (byte)0x6d, (byte)0x7f, (byte)0xed, (byte)0xbb, (byte)0x4f,
  90         (byte)0x4d, (byte)0x9f, (byte)0xda, (byte)0x87, (byte)0x47, (byte)0x8f,
  91         (byte)0x74, (byte)0x44, (byte)0xb7, (byte)0xbe, (byte)0x9d, (byte)0xf5,
  92         (byte)0xdd, (byte)0xd2, (byte)0x4c, (byte)0xa5, (byte)0xab, (byte)0x74,
  93         (byte)0xe5, (byte)0x29, (byte)0xa1, (byte)0xd2, (byte)0x45, (byte)0x3b,
  94         (byte)0x33, (byte)0xde, (byte)0xd5, (byte)0xae, (byte)0xf7, (byte)0x03,
  95         (byte)0x10, (byte)0x21
  96     };
  97 
  98     private static final byte PRIME_P[] = {
  99         (byte)0xf9, (byte)0x74, (byte)0x8f, (byte)0x16, (byte)0x02, (byte)0x6b,
 100         (byte)0xa0, (byte)0xee, (byte)0x7f, (byte)0x28, (byte)0x97, (byte)0x91,
 101         (byte)0xdc, (byte)0xec, (byte)0xc0, (byte)0x7c, (byte)0x49, (byte)0xc2,
 102         (byte)0x85, (byte)0x76, (byte)0xee, (byte)0x66, (byte)0x74, (byte)0x2d,
 103         (byte)0x1a, (byte)0xb8, (byte)0xf7, (byte)0x2f, (byte)0x11, (byte)0x5b,
 104         (byte)0x36, (byte)0xd8, (byte)0x46, (byte)0x33, (byte)0x3b, (byte)0xd8,
 105         (byte)0xf3, (byte)0x2d, (byte)0xa1, (byte)0x03, (byte)0x83, (byte)0x2b,
 106         (byte)0xec, (byte)0x35, (byte)0x43, (byte)0x32, (byte)0xff, (byte)0xdd,
 107         (byte)0x81, (byte)0x7c, (byte)0xfd, (byte)0x65, (byte)0x13, (byte)0x04,
 108         (byte)0x7c, (byte)0xfc, (byte)0x03, (byte)0x97, (byte)0xf0, (byte)0xd5,
 109         (byte)0x62, (byte)0xdc, (byte)0x0d, (byte)0xbf
 110     };
 111 
 112     private static final byte PRIME_Q[] = {
 113         (byte)0xdb, (byte)0x1e, (byte)0xa7, (byte)0x3d, (byte)0xe7, (byte)0xfa,
 114         (byte)0x8b, (byte)0x04, (byte)0x83, (byte)0x48, (byte)0xf3, (byte)0xa5,
 115         (byte)0x31, (byte)0x9d, (byte)0x35, (byte)0x5e, (byte)0x4d, (byte)0x54,
 116         (byte)0x77, (byte)0xcc, (byte)0x84, (byte)0x09, (byte)0xf3, (byte)0x11,
 117         (byte)0x0d, (byte)0x54, (byte)0xed, (byte)0x85, (byte)0x39, (byte)0xa9,
 118         (byte)0xca, (byte)0xa8, (byte)0xea, (byte)0xae, (byte)0x19, (byte)0x9c,
 119         (byte)0x75, (byte)0xdb, (byte)0x88, (byte)0xb8, (byte)0x04, (byte)0x8d,
 120         (byte)0x54, (byte)0xc6, (byte)0xa4, (byte)0x80, (byte)0xf8, (byte)0x93,
 121         (byte)0xf0, (byte)0xdb, (byte)0x19, (byte)0xef, (byte)0xd7, (byte)0x87,
 122         (byte)0x8a, (byte)0x8f, (byte)0x5a, (byte)0x09, (byte)0x2e, (byte)0x54,
 123         (byte)0xf3, (byte)0x45, (byte)0x24, (byte)0x29
 124     };
 125 
 126     private static final byte EXP_P[] = {
 127         (byte)0x6a, (byte)0xd1, (byte)0x25, (byte)0x80, (byte)0x18, (byte)0x33,
 128         (byte)0x3c, (byte)0x2b, (byte)0x44, (byte)0x19, (byte)0xfe, (byte)0xa5,
 129         (byte)0x40, (byte)0x03, (byte)0xc4, (byte)0xfc, (byte)0xb3, (byte)0x9c,
 130         (byte)0xef, (byte)0x07, (byte)0x99, (byte)0x58, (byte)0x17, (byte)0xc1,
 131         (byte)0x44, (byte)0xa3, (byte)0x15, (byte)0x7d, (byte)0x7b, (byte)0x22,
 132         (byte)0x22, (byte)0xdf, (byte)0x03, (byte)0x58, (byte)0x66, (byte)0xf5,
 133         (byte)0x24, (byte)0x54, (byte)0x52, (byte)0x91, (byte)0x2d, (byte)0x76,
 134         (byte)0xfe, (byte)0x63, (byte)0x64, (byte)0x4e, (byte)0x0f, (byte)0x50,
 135         (byte)0x2b, (byte)0x65, (byte)0x79, (byte)0x1f, (byte)0xf1, (byte)0xbf,
 136         (byte)0xc7, (byte)0x41, (byte)0x26, (byte)0xcc, (byte)0xc6, (byte)0x1c,
 137         (byte)0xa9, (byte)0x83, (byte)0x6f, (byte)0x03
 138     };
 139 
 140     private static final byte EXP_Q[] = {
 141         (byte)0x12, (byte)0x84, (byte)0x1a, (byte)0x99, (byte)0xce, (byte)0x9a,
 142         (byte)0x8b, (byte)0x58, (byte)0xcc, (byte)0x47, (byte)0x43, (byte)0xdf,
 143         (byte)0x77, (byte)0xbb, (byte)0xd3, (byte)0x20, (byte)0xae, (byte)0xe4,
 144         (byte)0x2e, (byte)0x63, (byte)0x67, (byte)0xdc, (byte)0xf7, (byte)0x5f,
 145         (byte)0x3f, (byte)0x83, (byte)0x27, (byte)0xb7, (byte)0x14, (byte)0x52,
 146         (byte)0x56, (byte)0xbf, (byte)0xc3, (byte)0x65, (byte)0x06, (byte)0xe1,
 147         (byte)0x03, (byte)0xcc, (byte)0x93, (byte)0x57, (byte)0x09, (byte)0x7b,
 148         (byte)0x6f, (byte)0xe8, (byte)0x81, (byte)0x4a, (byte)0x2c, (byte)0xb7,
 149         (byte)0x43, (byte)0xa9, (byte)0x20, (byte)0x1d, (byte)0xf6, (byte)0x56,
 150         (byte)0x8b, (byte)0xcc, (byte)0xe5, (byte)0x4c, (byte)0xd5, (byte)0x4f,
 151         (byte)0x74, (byte)0x67, (byte)0x29, (byte)0x51
 152     };
 153 
 154     private static final byte CRT_COEFF[] = {
 155         (byte)0x23, (byte)0xab, (byte)0xf4, (byte)0x03, (byte)0x2f, (byte)0x29,
 156         (byte)0x95, (byte)0x74, (byte)0xac, (byte)0x1a, (byte)0x33, (byte)0x96,
 157         (byte)0x62, (byte)0xed, (byte)0xf7, (byte)0xf6, (byte)0xae, (byte)0x07,
 158         (byte)0x2a, (byte)0x2e, (byte)0xe8, (byte)0xab, (byte)0xfb, (byte)0x1e,
 159         (byte)0xb9, (byte)0xb2, (byte)0x88, (byte)0x1e, (byte)0x85, (byte)0x05,
 160         (byte)0x42, (byte)0x64, (byte)0x03, (byte)0xb2, (byte)0x8b, (byte)0xc1,
 161         (byte)0x81, (byte)0x75, (byte)0xd7, (byte)0xba, (byte)0xaa, (byte)0xd4,
 162         (byte)0x31, (byte)0x3c, (byte)0x8a, (byte)0x96, (byte)0x23, (byte)0x9d,
 163         (byte)0x3f, (byte)0x06, (byte)0x3e, (byte)0x44, (byte)0xa9, (byte)0x62,
 164         (byte)0x2f, (byte)0x61, (byte)0x5a, (byte)0x51, (byte)0x82, (byte)0x2c,
 165         (byte)0x04, (byte)0x85, (byte)0x73, (byte)0xd1
 166     };
 167 
 168     private static KeyPair genRSAKey(int keyLength) throws Exception {
 169         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
 170         kpg.initialize(keyLength);
 171         return kpg.generateKeyPair();
 172     }
 173 
 174     private static KeyPair genPredefinedRSAKeyPair() throws Exception {
 175         KeyFactory kf = KeyFactory.getInstance("RSA");
 176         BigInteger mod = new BigInteger(MOD);
 177         BigInteger pub = new BigInteger(PUB_EXP);
 178 
 179         PrivateKey privKey = kf.generatePrivate
 180             (new RSAPrivateCrtKeySpec
 181              (mod, pub, new BigInteger(PRIV_EXP),
 182               new BigInteger(PRIME_P), new BigInteger(PRIME_Q),
 183               new BigInteger(EXP_P), new BigInteger(EXP_Q),
 184               new BigInteger(CRT_COEFF)));
 185         PublicKey pubKey = kf.generatePublic(new RSAPublicKeySpec(mod, pub));
 186         return new KeyPair(pubKey, privKey);
 187     }
 188 
 189     private static final String CIP_ALGOS[] = {
 190         "RSA/ECB/NoPadding",
 191         "RSA/ECB/PKCS1Padding"
 192     };
 193     private static final int INPUT_SIZE_REDUCTION[] = {
 194         0,
 195         11,
 196     };
 197     private static final String SIG_ALGOS[] = {
 198         "MD5WithRSA",
 199         "SHA1WithRSA",
 200         "SHA256WithRSA",
 201         "SHA384WithRSA",
 202         "SHA512WithRSA"
 203     };
 204 
 205     private static KeyPair kp[] = null;
 206 
 207     public static void main(String argv[]) throws Exception {
 208         main(new TestRSA(), null);
 209     }
 210 
 211     public void doTest(Provider prov) throws Exception {
 212         // first test w/ predefine KeyPair
 213         KeyPair pkp = genPredefinedRSAKeyPair();
 214         System.out.println("Test against Predefined RSA Key Pair");
 215         testCipher(pkp, 128, true, prov);
 216         testSignature(pkp, true, prov);
 217 
 218         for (int i = 0; i < 10; i++) {
 219             // then test w/ various key lengths
 220             int keyLens[] = { 1024, 2048 };
 221             kp = new KeyPair[keyLens.length];
 222 
 223             testCipher(keyLens, false, prov);
 224             testSignature(keyLens, false, prov);
 225         }
 226     }
 227 
 228 
 229     private static void testCipher(KeyPair kp, int inputSizeInBytes,
 230                                    boolean checkInterop, Provider prov)
 231         throws Exception {
 232         Cipher c1, c2;
 233         for (int i = 0; i < CIP_ALGOS.length; i++) {
 234             String algo = CIP_ALGOS[i];
 235             try {
 236                 c1 = Cipher.getInstance(algo, prov);
 237             } catch (NoSuchAlgorithmException nsae) {
 238                 System.out.println("Skip unsupported Cipher algo: " + algo);
 239                 continue;
 240             }
 241 
 242             if (checkInterop) {
 243                 c2 = Cipher.getInstance(algo, "SunJCE");
 244             } else {
 245                 c2 = Cipher.getInstance(algo, prov);
 246             }
 247             byte[] data = Arrays.copyOf
 248                  (PLAINTEXT, inputSizeInBytes - INPUT_SIZE_REDUCTION[i]);
 249 
 250             testEncryption(c1, c2, kp, data);
 251         }
 252     }
 253 
 254     private static void testCipher(int keyLens[], boolean checkInterop,
 255                                    Provider prov)
 256         throws Exception {
 257         // RSA CipherText will always differ due to the random nonce in padding
 258         // so we check whether both
 259         // 1) Java Encrypt/C Decrypt
 260         // 2) C Encrypt/Java Decrypt
 261         // works
 262         Cipher c1, c2;
 263         for (int i = 0; i < CIP_ALGOS.length; i++) {
 264             String algo = CIP_ALGOS[i];
 265             try {
 266                 c1 = Cipher.getInstance(algo, prov);
 267             } catch (NoSuchAlgorithmException nsae) {
 268                 System.out.println("Skip unsupported Cipher algo: " + algo);
 269                 continue;
 270             }
 271 
 272             if (checkInterop) {
 273                 c2 = Cipher.getInstance(algo, "SunJCE");
 274             } else {
 275                 c2 = Cipher.getInstance(algo, prov);
 276             }
 277 
 278             for (int h = 0; h < keyLens.length; h++) {
 279                 // Defer key pair generation until now when it'll soon be used.
 280                 if (kp[h] == null) {
 281                     kp[h] = genRSAKey(keyLens[h]);
 282                 }
 283                 System.out.println("\tTesting Cipher " + algo + " w/ KeySize " + keyLens[h]);
 284                 byte[] data = Arrays.copyOf
 285                     (PLAINTEXT, keyLens[h]/8 - INPUT_SIZE_REDUCTION[i]);
 286                 testEncryption(c1, c2, kp[h], data);
 287             }
 288         }
 289     }
 290 
 291     private static void testEncryption(Cipher c1, Cipher c2, KeyPair kp, byte[] data)
 292         throws Exception {
 293         // C1 Encrypt + C2 Decrypt
 294         byte[] out1 = null;
 295         byte[] recoveredText = null;
 296         try {
 297             c1.init(Cipher.ENCRYPT_MODE, kp.getPublic());
 298             out1 = c1.doFinal(data);
 299             c2.init(Cipher.DECRYPT_MODE, kp.getPrivate());
 300             recoveredText = c2.doFinal(out1);
 301         } catch (Exception ex) {
 302             System.out.println("\tDEC ERROR: unexpected exception");
 303             ex.printStackTrace();
 304             throw ex;
 305         }
 306         if(!Arrays.equals(recoveredText, data)) {
 307             throw new RuntimeException("\tDEC ERROR: different PT bytes!");
 308         }
 309         // C2 Encrypt + C1 Decrypt
 310         byte[] cipherText = null;
 311         try {
 312             c2.init(Cipher.ENCRYPT_MODE, kp.getPublic());
 313             cipherText = c2.doFinal(data);
 314             c1.init(Cipher.DECRYPT_MODE, kp.getPrivate());
 315             try {
 316                 out1 = c1.doFinal(cipherText);
 317             } catch (Exception ex) {
 318                 System.out.println("\tENC ERROR: invalid encrypted output");
 319                 ex.printStackTrace();
 320                 throw ex;
 321             }
 322         } catch (Exception ex) {
 323             System.out.println("\tENC ERROR: unexpected exception");
 324             ex.printStackTrace();
 325             throw ex;
 326         }
 327         if (!Arrays.equals(out1, data)) {
 328             throw new RuntimeException("\tENC ERROR: Decrypted result DIFF!");
 329         }
 330         System.out.println("\t=> PASS");
 331     }
 332 
 333     private static void testSignature(KeyPair kp, boolean checkInterop,
 334                                       Provider prov) throws Exception {
 335         byte[] data = PLAINTEXT;
 336         Signature sig1, sig2;
 337         for (int i = 0; i < SIG_ALGOS.length; i++) {
 338             String algo = SIG_ALGOS[i];
 339             try {
 340                 sig1 = Signature.getInstance(algo, prov);
 341             } catch (NoSuchAlgorithmException nsae) {
 342                 System.out.println("Skip unsupported Signature algo: " + algo);
 343                 continue;
 344             }
 345 
 346             if (checkInterop) {
 347                 sig2 = Signature.getInstance(algo, "SunRsaSign");
 348             } else {
 349                 sig2 = Signature.getInstance(algo, prov);
 350             }
 351             testSigning(sig1, sig2, kp, data);
 352         }
 353     }
 354 
 355     private static void testSignature(int keyLens[], boolean checkInterop,
 356                                       Provider prov) throws Exception {
 357         byte[] data = PLAINTEXT;
 358         Signature sig1, sig2;
 359         for (int i = 0; i < SIG_ALGOS.length; i++) {
 360             String algo = SIG_ALGOS[i];
 361             try {
 362                 sig1 = Signature.getInstance(algo, prov);
 363             } catch (NoSuchAlgorithmException nsae) {
 364                 System.out.println("Skip unsupported Signature algo: " + algo);
 365                 continue;
 366             }
 367 
 368             if (checkInterop) {
 369                 sig2 = Signature.getInstance(algo, "SunRsaSign");
 370             } else {
 371                 sig2 = Signature.getInstance(algo, prov);
 372             }
 373 
 374             for (int h = 0; h < keyLens.length; h++) {
 375                 // Defer key pair generation until now when it'll soon be used.
 376                 if (kp[h] == null) {
 377                     kp[h] = genRSAKey(keyLens[h]);
 378                 }
 379                 System.out.println("\tTesting Signature " + algo + " w/ KeySize " + keyLens[h]);
 380 
 381                 testSigning(sig1, sig2, kp[h], data);
 382             }
 383         }
 384     }
 385 
 386     private static void testSigning(Signature sig1, Signature sig2, KeyPair kp, byte[] data)
 387             throws Exception {
 388         boolean sameSig = false;
 389         byte[] out = null;
 390         try {
 391             sig1.initSign(kp.getPrivate());
 392             sig1.update(data);
 393             out = sig1.sign();
 394         } catch (Exception ex) {
 395             System.out.println("\tSIGN ERROR: unexpected exception!");
 396             ex.printStackTrace();
 397         }
 398 
 399         sig2.initSign(kp.getPrivate());
 400         sig2.update(data);
 401         byte[] out2 = sig2.sign();
 402         if (!Arrays.equals(out2, out)) {
 403             throw new RuntimeException("\tSIGN ERROR: Signature DIFF!");
 404         }
 405 
 406         boolean verify = false;
 407         try {
 408             System.out.println("\tVERIFY1 using native out");
 409             sig1.initVerify(kp.getPublic());
 410             sig1.update(data);
 411             verify = sig1.verify(out);
 412             if (!verify) {
 413                 throw new RuntimeException("VERIFY1 FAIL!");
 414             }
 415         } catch (Exception ex) {
 416             System.out.println("\tVERIFY1 ERROR: unexpected exception!");
 417             ex.printStackTrace();
 418             throw ex;
 419         }
 420         System.out.println("\t=> PASS");
 421     }
 422 }