9a9ac1d005
Reviewed-by: mullan, ascarpino, rhalade
177 lines
7.7 KiB
Java
177 lines
7.7 KiB
Java
/*
|
|
* 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 jdk.test.lib.Convert;
|
|
|
|
import java.security.*;
|
|
import java.security.spec.*;
|
|
import java.math.*;
|
|
import java.util.*;
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8172366
|
|
* @summary Known Answer Test for ECDSA signature
|
|
* @library /test/lib
|
|
* @build jdk.test.lib.Convert
|
|
* @run main/othervm SignatureKAT
|
|
*/
|
|
public class SignatureKAT {
|
|
|
|
private static String checkHex(String hex) {
|
|
// if hex length is odd, need to prepend 0
|
|
if (hex.length() % 2 != 0) {
|
|
hex = "0" + hex;
|
|
}
|
|
return hex;
|
|
}
|
|
|
|
private static class CurveData {
|
|
private String name;
|
|
private byte[] msgBytes;
|
|
private BigInteger priv;
|
|
private BigInteger pubX;
|
|
private BigInteger pubY;
|
|
|
|
private static BigInteger toBigInteger(String hex) {
|
|
byte[] bytes = HexFormat.of().parseHex(checkHex(hex));
|
|
return new BigInteger(1, bytes);
|
|
}
|
|
CurveData(String name, String msg, String priv, String pubX,
|
|
String pubY) {
|
|
this.name = name;
|
|
this.msgBytes = msg.getBytes();
|
|
this.priv = toBigInteger(priv);
|
|
this.pubX = toBigInteger(pubX);
|
|
this.pubY = toBigInteger(pubY);
|
|
}
|
|
}
|
|
|
|
private static class TestData {
|
|
private String sigName;
|
|
private CurveData cd;
|
|
private byte[] expSig;
|
|
|
|
TestData(String sigName, CurveData cd, String r, String s) {
|
|
this.sigName = sigName;
|
|
this.cd = cd;
|
|
if (r.length() != s.length() || r != checkHex(r) ||
|
|
s != checkHex(s)) {
|
|
throw new RuntimeException("Error: invalid r, s");
|
|
}
|
|
this.expSig = HexFormat.of().parseHex(r + s);
|
|
}
|
|
}
|
|
|
|
// These test values are from the examples shown in the page below:
|
|
// https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values
|
|
private static final CurveData P_256 = new CurveData(
|
|
"secp256r1", "Example of ECDSA with P-256",
|
|
"C477F9F65C22CCE20657FAA5B2D1D8122336F851A508A1ED04E479C34985BF96",
|
|
"B7E08AFDFE94BAD3F1DC8C734798BA1C62B3A0AD1E9EA2A38201CD0889BC7A19",
|
|
"3603F747959DBF7A4BB226E41928729063ADC7AE43529E61B563BBC606CC5E09"
|
|
);
|
|
|
|
private static final CurveData P_384 = new CurveData(
|
|
"secp384r1", "Example of ECDSA with P-384",
|
|
"F92C02ED629E4B48C0584B1C6CE3A3E3B4FAAE4AFC6ACB0455E73DFC392E6A0AE393A8565E6B9714D1224B57D83F8A08",
|
|
"3BF701BC9E9D36B4D5F1455343F09126F2564390F2B487365071243C61E6471FB9D2AB74657B82F9086489D9EF0F5CB5",
|
|
"D1A358EAFBF952E68D533855CCBDAA6FF75B137A5101443199325583552A6295FFE5382D00CFCDA30344A9B5B68DB855"
|
|
);
|
|
|
|
private static final CurveData P_521 = new CurveData(
|
|
"secp521r1", "Example of ECDSA with P-521",
|
|
"100085F47B8E1B8B11B7EB33028C0B2888E304BFC98501955B45BBA1478DC184EEEDF09B86A5F7C21994406072787205E69A63709FE35AA93BA333514B24F961722",
|
|
"98E91EEF9A68452822309C52FAB453F5F117C1DA8ED796B255E9AB8F6410CCA16E59DF403A6BDC6CA467A37056B1E54B3005D8AC030DECFEB68DF18B171885D5C4",
|
|
"164350C321AECFC1CCA1BA4364C9B15656150B4B78D6A48D7D28E7F31985EF17BE8554376B72900712C4B83AD668327231526E313F5F092999A4632FD50D946BC2E"
|
|
);
|
|
|
|
private static TestData[] TEST_DATUM = {
|
|
// secp256r1, secp384r1, and secp521r1 remain enabled
|
|
new TestData("SHA256withECDSAinP1363Format", P_256,
|
|
"2B42F576D07F4165FF65D1F3B1500F81E44C316F1F0B3EF57325B69ACA46104F",
|
|
"DC42C2122D6392CD3E3A993A89502A8198C1886FE69D262C4B329BDB6B63FAF1"),
|
|
new TestData("SHA3-256withECDSAinP1363Format", P_256,
|
|
"2B42F576D07F4165FF65D1F3B1500F81E44C316F1F0B3EF57325B69ACA46104F",
|
|
"0A861C2526900245C73BACB9ADAEC1A5ACB3BA1F7114A3C334FDCD5B7690DADD"),
|
|
new TestData("SHA384withECDSAinP1363Format", P_384,
|
|
"30EA514FC0D38D8208756F068113C7CADA9F66A3B40EA3B313D040D9B57DD41A332795D02CC7D507FCEF9FAF01A27088",
|
|
"CC808E504BE414F46C9027BCBF78ADF067A43922D6FCAA66C4476875FBB7B94EFD1F7D5DBE620BFB821C46D549683AD8"),
|
|
new TestData("SHA3-384withECDSAinP1363Format", P_384,
|
|
"30EA514FC0D38D8208756F068113C7CADA9F66A3B40EA3B313D040D9B57DD41A332795D02CC7D507FCEF9FAF01A27088",
|
|
"691B9D4969451A98036D53AA725458602125DE74881BBC333012CA4FA55BDE39D1BF16A6AAE3FE4992C567C6E7892337"),
|
|
new TestData("SHA512withECDSAinP1363Format", P_521,
|
|
"0140C8EDCA57108CE3F7E7A240DDD3AD74D81E2DE62451FC1D558FDC79269ADACD1C2526EEEEF32F8C0432A9D56E2B4A8A732891C37C9B96641A9254CCFE5DC3E2BA",
|
|
"00D72F15229D0096376DA6651D9985BFD7C07F8D49583B545DB3EAB20E0A2C1E8615BD9E298455BDEB6B61378E77AF1C54EEE2CE37B2C61F5C9A8232951CB988B5B1"),
|
|
new TestData("SHA3-512withECDSAinP1363Format", P_521,
|
|
"0140C8EDCA57108CE3F7E7A240DDD3AD74D81E2DE62451FC1D558FDC79269ADACD1C2526EEEEF32F8C0432A9D56E2B4A8A732891C37C9B96641A9254CCFE5DC3E2BA",
|
|
"00B25188492D58E808EDEBD7BF440ED20DB771CA7C618595D5398E1B1C0098E300D8C803EC69EC5F46C84FC61967A302D366C627FCFA56F87F241EF921B6E627ADBF"),
|
|
};
|
|
|
|
private static void runTest(TestData td) throws Exception {
|
|
System.out.println("Testing " + td.sigName + " with " + td.cd.name);
|
|
|
|
AlgorithmParameters params =
|
|
AlgorithmParameters.getInstance("EC",
|
|
System.getProperty("test.provider.name", "SunEC"));
|
|
params.init(new ECGenParameterSpec(td.cd.name));
|
|
ECParameterSpec ecParams =
|
|
params.getParameterSpec(ECParameterSpec.class);
|
|
|
|
KeyFactory kf = KeyFactory.getInstance("EC",
|
|
System.getProperty("test.provider.name", "SunEC"));
|
|
PrivateKey privKey = kf.generatePrivate
|
|
(new ECPrivateKeySpec(td.cd.priv, ecParams));
|
|
|
|
Signature sig = Signature.getInstance(td.sigName,
|
|
System.getProperty("test.provider.name", "SunEC"));
|
|
sig.initSign(privKey);
|
|
sig.update(td.cd.msgBytes);
|
|
// NOTE: there is no way to set the nonce value into current SunEC
|
|
// ECDSA signature, thus the output signature bytes likely won't
|
|
// match the expected signature bytes
|
|
byte[] ov = sig.sign();
|
|
|
|
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec
|
|
(new ECPoint(td.cd.pubX, td.cd.pubY), ecParams);
|
|
PublicKey pubKey = kf.generatePublic(pubKeySpec);
|
|
|
|
sig.initVerify(pubKey);
|
|
sig.update(td.cd.msgBytes);
|
|
if (!sig.verify(ov)) {
|
|
throw new RuntimeException("Error verifying actual sig bytes");
|
|
}
|
|
|
|
sig.update(td.cd.msgBytes);
|
|
if (!sig.verify(td.expSig)) {
|
|
throw new RuntimeException("Error verifying expected sig bytes");
|
|
}
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
for (TestData td : TEST_DATUM) {
|
|
runTest(td);
|
|
}
|
|
}
|
|
}
|