1 /* 2 * Copyright (c) 2020, 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 import java.security.KeyPair; 24 import java.security.KeyPairGenerator; 25 import java.security.PrivateKey; 26 import java.security.PublicKey; 27 import java.security.SecureRandom; 28 import java.security.Signature; 29 import java.security.spec.EdDSAParameterSpec; 30 import java.util.Arrays; 31 import jdk.test.lib.Convert; 32 33 /* 34 * @test 35 * @bug 8209632 36 * @summary Test EdDSAParameterSpec. 37 * @library /test/lib 38 * @build jdk.test.lib.Convert 39 * @run main EdDSAParamSpec 40 */ 41 public class EdDSAParamSpec { 42 43 private static final String EDDSA = "EdDSA"; 44 private static final String ED25519 = "Ed25519"; 45 private static final String ED448 = "Ed448"; 46 private static final String PROVIDER = "SunEC"; 47 private static final byte[] MSG = "TEST".getBytes(); 48 private static final SecureRandom RND = new SecureRandom(new byte[]{0x1}); 49 main(String[] args)50 public static void main(String[] args) throws Exception { 51 52 testParam(PROVIDER, EDDSA); 53 testParam(PROVIDER, ED25519); 54 testParam(PROVIDER, ED448); 55 } 56 57 /** 58 * Test Signature. 59 */ testParam(String provider, String name)60 private static void testParam(String provider, String name) 61 throws Exception { 62 63 KeyPair kp = genKeyPair(provider, name); 64 Signature sig = Signature.getInstance(name, provider); 65 EdDSAParameterSpec initParam 66 = new EdDSAParameterSpec(true, "testContext".getBytes()); 67 sig.setParameter(initParam); 68 byte[] origSign = sign(sig, kp.getPrivate(), MSG); 69 for (boolean preHash : new boolean[]{true, false}) { 70 System.out.printf("Testing signature for name: %s," 71 + " algorithm spec: (prehash:%s)%n", name, preHash); 72 verifyPublic(sig, kp.getPublic(), MSG, 73 new EdDSAParameterSpec(preHash), initParam, origSign); 74 // Test Case with Context size combined. 75 // As per rfc8032, value of context is maximum of 255 octet 76 byte[] maxCtx = new byte[255]; 77 RND.nextBytes(maxCtx); 78 for (byte[] context : new byte[][]{"others".getBytes(), maxCtx}) { 79 System.out.printf("Testing signature for name: %s," 80 + " algorithm spec: (prehash:%s, context:%s)%n", 81 name, preHash, Convert.byteArrayToHexString(context)); 82 EdDSAParameterSpec params 83 = new EdDSAParameterSpec(preHash, context); 84 verifyPublic(sig, kp.getPublic(), MSG, params, initParam, 85 origSign); 86 } 87 } 88 System.out.println("Passed."); 89 } 90 genKeyPair(String provider, String name)91 private static KeyPair genKeyPair(String provider, String name) 92 throws Exception { 93 94 KeyPairGenerator kpg = KeyPairGenerator.getInstance(name, provider); 95 return kpg.generateKeyPair(); 96 } 97 sign(Signature sig, PrivateKey priKey, byte[] msg)98 private static byte[] sign(Signature sig, PrivateKey priKey, byte[] msg) 99 throws Exception { 100 101 sig.initSign(priKey); 102 sig.update(msg); 103 return sig.sign(); 104 } 105 verify(Signature sig, PublicKey pubKey, byte[] msg, byte[] sign)106 private static boolean verify(Signature sig, PublicKey pubKey, byte[] msg, 107 byte[] sign) throws Exception { 108 109 sig.initVerify(pubKey); 110 sig.update(msg); 111 return sig.verify(sign); 112 } 113 verifyPublic(Signature sig, PublicKey pubKey, byte[] msg, EdDSAParameterSpec params, EdDSAParameterSpec initParam, byte[] origSign)114 private static void verifyPublic(Signature sig, PublicKey pubKey, 115 byte[] msg, EdDSAParameterSpec params, EdDSAParameterSpec initParam, 116 byte[] origSign) throws Exception { 117 118 sig.setParameter(params); 119 if (verify(sig, pubKey, msg, origSign)) { 120 byte[] context = params.getContext().isPresent() 121 ? params.getContext().get() : null; 122 byte[] initContext = initParam.getContext().isPresent() 123 ? initParam.getContext().get() : null; 124 boolean preHash = params.isPrehash(); 125 boolean initPreHash = initParam.isPrehash(); 126 // The signature should not get verified other than same parameter 127 // which is set through the signature instance. 128 if (!(equals(context, initContext) && equals(preHash, initPreHash))) { 129 throw new RuntimeException(String.format("Signature verification" 130 + " success with different param context(actual:%s, " 131 + "expected:%s), Prehash(actual:%s, expected:%s)", 132 Convert.byteArrayToHexString(context), 133 Convert.byteArrayToHexString(initContext), 134 preHash, initPreHash)); 135 } else { 136 System.out.println("Atleast a case matched"); 137 } 138 } 139 } 140 equals(Object actual, Object expected)141 private static boolean equals(Object actual, Object expected) { 142 143 if (actual == expected) { 144 return true; 145 } 146 if (actual == null || expected == null) { 147 return false; 148 } 149 boolean equals = actual.equals(expected); 150 if (!equals) { 151 throw new RuntimeException(String.format("Actual: %s, Expected: %s", 152 actual, expected)); 153 } 154 return equals; 155 } 156 equals(byte[] actual, byte[] expected)157 private static boolean equals(byte[] actual, byte[] expected) { 158 159 if (actual == expected) { 160 return true; 161 } 162 if (actual == null || expected == null) { 163 return false; 164 } 165 boolean equals = Arrays.equals(actual, expected); 166 if (!equals) { 167 throw new RuntimeException(String.format("Actual array: %s, " 168 + "Expected array:%s", Convert.byteArrayToHexString(actual), 169 Convert.byteArrayToHexString(expected))); 170 } 171 return equals; 172 } 173 174 } 175