Path: blob/master/test/jdk/sun/security/ec/ed/EdDSANegativeTest.java
41152 views
/*1* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.security.InvalidKeyException;24import java.security.InvalidParameterException;25import java.security.KeyFactory;26import java.security.KeyPair;27import java.security.KeyPairGenerator;28import java.security.NoSuchAlgorithmException;29import java.security.PrivateKey;30import java.security.PublicKey;31import java.security.Signature;32import java.security.interfaces.EdECPrivateKey;33import java.security.interfaces.EdECPublicKey;34import java.security.spec.EdDSAParameterSpec;35import java.util.Arrays;36import java.util.HexFormat;3738/*39* @test40* @bug 820963241* @summary Negative cases for EDDSA.42* @library /test/lib43* @run main EdDSANegativeTest44*/45public class EdDSANegativeTest {4647private static final String EDDSA = "EdDSA";48private static final String ED25519 = "Ed25519";49private static final String ED448 = "Ed448";50private static final String PROVIDER = "SunEC";51private static final String OTHER = "other";52private static final byte[] MSG = "TEST".getBytes();5354public static void main(String[] args) throws Exception {55byName();56byParam();57byInvalidKey();58byInvalidKeyType();59}6061private static void byName() throws Exception {6263for (String name : new String[]{null, "", "EDDSA", "eddsa", "EDdsa",64EDDSA, ED25519, "ed25519", "ED25519", ED448, "eD448", "ED448",65"ed448", OTHER}) {66try {67KeyPair kp = genKeyPair(name);68KeyFactory kf = KeyFactory.getInstance(name, PROVIDER);69EdECPrivateKey edPri70= (EdECPrivateKey) kf.translateKey(kp.getPrivate());71EdECPublicKey edPub72= (EdECPublicKey) kf.translateKey(kp.getPublic());73Signature sig = Signature.getInstance(name, PROVIDER);74byte[] computedSig = sign(sig, edPri, MSG);75if (!verify(sig, edPub, MSG, computedSig)) {76throw new RuntimeException("Signature verification failed");77}78if (name == null || "".equals(name)) {79throw new RuntimeException(80"Should not reach here for algo: " + name);81}82System.out.println("Passed: byName: " + name);83} catch (NullPointerException e) {84if (name != null) {85throw new RuntimeException(86"Unknown issue with algo name: " + name, e);87}88} catch (NoSuchAlgorithmException e) {89if (!("".equals(name) || OTHER.equals(name))) {90throw new RuntimeException(91"Unknown issue with algo name: " + name, e);92}93}94}95}9697private static void byParam() throws Exception {98testParam(EDDSA);99testParam(ED25519);100testParam(ED448);101}102103private static void byInvalidKey() throws Exception {104testInvalidKey(EDDSA);105testInvalidKey(ED25519);106testInvalidKey(ED448);107}108109private static void byInvalidKeyType() throws Exception {110testInvalidKeyType(EDDSA);111testInvalidKeyType(ED25519);112testInvalidKeyType(ED448);113}114115/**116* Test Signature.117*/118private static void testParam(String name) throws Exception {119120KeyPair kp = genKeyPair(name);121Signature sig = Signature.getInstance(name, PROVIDER);122// Set initial paramter to generate a signature123EdDSAParameterSpec initParam124= new EdDSAParameterSpec(true, "testContext".getBytes());125sig.setParameter(initParam);126byte[] computedSig = sign(sig, kp.getPrivate(), MSG);127// Signature should not get verified other than same parameter128// which is set through the signature instance.129for (boolean preHash : new boolean[]{true, false}) {130// Test case with prehash as parameter without context set.131verify(sig, kp.getPublic(), MSG, new EdDSAParameterSpec(preHash),132initParam, computedSig);133// Test Case with Context combined of different sizes.134// As per rfc8032, value of context is maximum of 255 octet135for (byte[] context : new byte[][]{{}, "other".getBytes(),136new byte[255], new byte[500]}) {137System.out.printf("Testing signature for name: %s, algorithm "138+ "spec: (prehash:%s, context:%s)%n", name, preHash,139HexFormat.of().withUpperCase().formatHex(context));140try {141verify(sig, kp.getPublic(), MSG,142new EdDSAParameterSpec(preHash, context),143initParam, computedSig);144} catch (InvalidParameterException e) {145if (context.length <= 255) {146throw new RuntimeException("Should not throw exception "147+ "when context size <= 255 octet: "148+ context.length);149}150}151}152}153}154155private static void testInvalidKey(String name) throws Exception {156KeyPair kp = genKeyPair(name);157KeyPair kp1 = genKeyPair(name);158Signature sig = Signature.getInstance(name, PROVIDER);159byte[] computedSig = sign(sig, kp.getPrivate(), MSG);160if (verify(sig, kp1.getPublic(), MSG, computedSig)) {161throw new RuntimeException("Signature verification failed "162+ "for unpaired key.");163}164System.out.println("Passed: testInvalidKey: " + name);165}166167private static void testInvalidKeyType(String name) throws Exception {168169KeyFactory kf = KeyFactory.getInstance(name, PROVIDER);170try {171kf.translateKey(new InvalidPrivateKey());172} catch (InvalidKeyException e) {173// Expected exception and not to be handled174}175try {176kf.translateKey(new InvalidPublicKey());177} catch (InvalidKeyException e) {178// Expected exception and not to be handled179}180System.out.println("Passed: testInvalidKeyType: " + name);181}182183private static KeyPair genKeyPair(String name) throws Exception {184KeyPairGenerator kpg = KeyPairGenerator.getInstance(name, PROVIDER);185return kpg.generateKeyPair();186}187188private static byte[] sign(Signature sig, PrivateKey priKey, byte[] msg)189throws Exception {190sig.initSign(priKey);191sig.update(msg);192return sig.sign();193}194195private static boolean verify(Signature sig, PublicKey pubKey, byte[] msg,196byte[] sign) throws Exception {197sig.initVerify(pubKey);198sig.update(msg);199return sig.verify(sign);200}201202private static void verify(Signature sig, PublicKey pubKey, byte[] msg,203EdDSAParameterSpec params, EdDSAParameterSpec initParam,204byte[] computedSig) throws Exception {205206sig.setParameter(params);207if (verify(sig, pubKey, msg, computedSig)) {208byte[] context = params.getContext().isPresent()209? params.getContext().get() : null;210byte[] initContext = initParam.getContext().isPresent()211? initParam.getContext().get() : null;212boolean preHash = params.isPrehash();213boolean initPreHash = initParam.isPrehash();214// The signature should not get verified with other parameters215// set through signature instance.216if (!(equals(context, initContext) && equals(preHash, initPreHash))) {217throw new RuntimeException(String.format("Signature verification"218+ " success with different param context(actual:%s, "219+ "expected:%s), Prehash(actual:%s, expected:%s)",220HexFormat.of().withUpperCase().formatHex(context),221HexFormat.of().withUpperCase().formatHex(initContext),222preHash, initPreHash));223} else {224System.out.println("Atleast a case matched");225}226}227}228229private static boolean equals(Object actual, Object expected) {230if (actual == expected) {231return true;232}233if (actual == null || expected == null) {234return false;235}236boolean equals = actual.equals(expected);237if (!equals) {238throw new RuntimeException(String.format("Actual: %s, Expected: %s",239actual, expected));240}241return equals;242}243244private static boolean equals(byte[] actual, byte[] expected) {245if (actual == expected) {246return true;247}248if (actual == null || expected == null) {249return false;250}251boolean equals = Arrays.equals(actual, expected);252if (!equals) {253throw new RuntimeException(String.format("Actual array: %s, "254+ "Expected array:%s", HexFormat.of().withUpperCase().formatHex(actual),255HexFormat.of().withUpperCase().formatHex(expected)));256}257return equals;258}259260private static class InvalidPrivateKey implements PrivateKey {261262@Override263public String getAlgorithm() {264return "test";265}266267@Override268public String getFormat() {269return "test";270}271272@Override273public byte[] getEncoded() {274return "test".getBytes();275}276277}278279private static class InvalidPublicKey implements PublicKey {280281@Override282public String getAlgorithm() {283return "test";284}285286@Override287public String getFormat() {288return "test";289}290291@Override292public byte[] getEncoded() {293return "test".getBytes();294}295296}297}298299300