/* * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.spec.NamedParameterSpec; import java.util.ArrayList; import java.util.List; /* * @test * @bug 8209632 * @summary Test behaviour of Signature instance by re-using it multiple times * in different way. * @run main EdDSAReuseTest */ public class EdDSAReuseTest { private static final String EDDSA = "EdDSA"; private static final String ED25519 = "Ed25519"; private static final String ED448 = "Ed448"; private static final String PROVIDER = System.getProperty("test.provider.name", "SunEC"); private static final String MSG = "TEST"; private static final int REUSE = 20; private static final int ONCE = 1; private static final int TENTH = 10; private static final int FIFTH = 5; public static void main(String[] args) throws Exception { for (boolean initKey : new boolean[]{true, false}) { // Sign and Verify with data update once test(PROVIDER, EDDSA, null, initKey, ONCE, ONCE); test(PROVIDER, ED25519, ED25519, initKey, ONCE, ONCE); test(PROVIDER, ED448, ED448, initKey, ONCE, ONCE); // Sign and Verify with data update 10 times test(PROVIDER, EDDSA, null, initKey, TENTH, TENTH); test(PROVIDER, ED25519, ED25519, initKey, TENTH, TENTH); test(PROVIDER, ED448, ED448, initKey, TENTH, TENTH); // Sign and Verify with data update unmatched number of times test(PROVIDER, EDDSA, null, initKey, TENTH, FIFTH); test(PROVIDER, ED25519, ED25519, initKey, TENTH, FIFTH); test(PROVIDER, ED448, ED448, initKey, TENTH, FIFTH); } } private static void test(String provider, String name, Object param, boolean initKey, int signUpdate, int verifyUpdate) throws Exception { System.out.printf("Case for signature name: %s, param: %s," + " initialize signature instance before each operation: %s%n", name, param, initKey); KeyPairGenerator kpg = KeyPairGenerator.getInstance(name, provider); if (param != null) { kpg.initialize(new NamedParameterSpec((String) param)); } KeyPair kp = kpg.generateKeyPair(); Signature sig = Signature.getInstance(name, provider); testAPI(sig, kp, initKey, signUpdate, verifyUpdate); System.out.println("Passed."); } private static void testAPI(Signature sig, KeyPair kp, boolean initKey, int signUpdate, int verifyUpdate) throws Exception { sig.initSign(kp.getPrivate()); List signatures = new ArrayList<>(); // Re-use the signature instance 20 times for (int i = 0; i < REUSE; i++) { signatures.add(sign(sig, kp.getPrivate(), MSG, initKey, signUpdate)); } System.out.printf("Generated signatures %s times%n", signatures.size()); sig.initVerify(kp.getPublic()); for (byte[] sign : signatures) { // Verification will pass when message update matches with // the same used for sign if (verify(sig, kp.getPublic(), MSG, sign, initKey, verifyUpdate) != (signUpdate == verifyUpdate)) { throw new RuntimeException( "Verification succed with unmatched message"); } } System.out.printf("Verified signatures %s times%n", signatures.size()); } private static byte[] sign(Signature sig, PrivateKey priKey, String msg, boolean initKey, int signUpdate) throws Exception { if (initKey) { sig.initSign(priKey); } for (int update = 0; update < signUpdate; update++) { sig.update(msg.getBytes()); } return sig.sign(); } private static boolean verify(Signature sig, PublicKey pubKey, String msg, byte[] sign, boolean initKey, int verifyUpdate) throws Exception { if (initKey) { sig.initVerify(pubKey); } for (int update = 0; update < verifyUpdate; update++) { sig.update(msg.getBytes()); } return sig.verify(sign); } }