Path: blob/master/test/jdk/sun/security/ec/xec/TestXDH.java
41155 views
/*1* Copyright (c) 2018, 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*/2223/*24* @test25* @bug 8171277 820691526* @summary Test XDH key agreement27* @library /test/lib28* @build jdk.test.lib.Convert29* @run main TestXDH30*/3132import java.security.*;33import java.security.spec.*;34import javax.crypto.*;35import java.util.Arrays;36import java.util.HexFormat;3738import jdk.test.lib.Convert;39import jdk.test.lib.hexdump.ASN1Formatter;40import jdk.test.lib.hexdump.HexPrinter;4142public class TestXDH {4344public static void main(String[] args) throws Exception {4546runBasicTests();47runKAT();48runSmallOrderTest();49runNonCanonicalTest();50runCurveMixTest();51}5253private static void runBasicTests() throws Exception {54runBasicTest("XDH", null);55runBasicTest("XDH", 255);56runBasicTest("XDH", 448);57runBasicTest("XDH", "X25519");58runBasicTest("XDH", "X448");59runBasicTest("X25519", null);60runBasicTest("X448", null);61runBasicTest("1.3.101.110", null);62runBasicTest("1.3.101.111", null);63runBasicTest("OID.1.3.101.110", null);64runBasicTest("OID.1.3.101.111", null);65}6667private static void runBasicTest(String name, Object param)68throws Exception {6970KeyPairGenerator kpg = KeyPairGenerator.getInstance(name);71AlgorithmParameterSpec paramSpec = null;72if (param instanceof Integer) {73kpg.initialize((Integer) param);74} else if (param instanceof String) {75paramSpec = new NamedParameterSpec((String) param);76kpg.initialize(paramSpec);77}78KeyPair kp = kpg.generateKeyPair();7980KeyAgreement ka = KeyAgreement.getInstance(name);81ka.init(kp.getPrivate(), paramSpec);82ka.doPhase(kp.getPublic(), true);8384byte[] secret = ka.generateSecret();8586KeyFactory kf = KeyFactory.getInstance(name);87// Test with X509 and PKCS8 key specs88X509EncodedKeySpec pubSpec =89kf.getKeySpec(kp.getPublic(), X509EncodedKeySpec.class);90PKCS8EncodedKeySpec priSpec =91kf.getKeySpec(kp.getPrivate(), PKCS8EncodedKeySpec.class);9293PublicKey pubKey = kf.generatePublic(pubSpec);94PrivateKey priKey = kf.generatePrivate(priSpec);9596ka.init(priKey);97ka.doPhase(pubKey, true);98byte[] secret2 = ka.generateSecret();99if (!Arrays.equals(secret, secret2)) {100throw new RuntimeException("Arrays not equal");101}102103// make sure generateSecret() resets the state to after init()104try {105ka.generateSecret();106throw new RuntimeException("generateSecret does not reset state");107} catch (IllegalStateException ex) {108// do nothing---this is expected109}110ka.doPhase(pubKey, true);111ka.generateSecret();112113// test with XDH key specs114XECPublicKeySpec xdhPublic =115kf.getKeySpec(kp.getPublic(), XECPublicKeySpec.class);116XECPrivateKeySpec xdhPrivate =117kf.getKeySpec(kp.getPrivate(), XECPrivateKeySpec.class);118PublicKey pubKey2 = kf.generatePublic(xdhPublic);119PrivateKey priKey2 = kf.generatePrivate(xdhPrivate);120ka.init(priKey2);121ka.doPhase(pubKey2, true);122byte[] secret3 = ka.generateSecret();123if (!Arrays.equals(secret, secret3)) {124throw new RuntimeException("Arrays not equal");125}126}127128private static void runSmallOrderTest() throws Exception {129// Ensure that small-order points are rejected130131// X25519132// 0133testSmallOrder(134"X25519",135"77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",136"0000000000000000000000000000000000000000000000000000000000000000",137"0000000000000000000000000000000000000000000000000000000000000000");138// 1 and -1139testSmallOrder(140"X25519",141"77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",142"0100000000000000000000000000000000000000000000000000000000000000",143"0000000000000000000000000000000000000000000000000000000000000000");144testSmallOrder(145"X25519",146"77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",147"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",148"0000000000000000000000000000000000000000000000000000000000000000");149150// order 8 points151testSmallOrder(152"X25519",153"77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",154"5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157",155"0000000000000000000000000000000000000000000000000000000000000000");156testSmallOrder(157"X25519",158"77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",159"e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800",160"0000000000000000000000000000000000000000000000000000000000000000");161162// X448163// 0164testSmallOrder(165"X448",166"9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" +167"F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B",168"00000000000000000000000000000000000000000000000000000000000000" +169"00000000000000000000000000000000000000000000000000",170"00000000000000000000000000000000000000000000000000000000000000" +171"00000000000000000000000000000000000000000000000000");172// 1 and -1173testSmallOrder(174"X448",175"9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" +176"F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B",177"01000000000000000000000000000000000000000000000000000000000000" +178"00000000000000000000000000000000000000000000000000",179"00000000000000000000000000000000000000000000000000000000000000" +180"00000000000000000000000000000000000000000000000000");181testSmallOrder(182"X448",183"9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BAF" +184"574A9419744897391006382A6F127AB1D9AC2D8C0A598726B",185"fefffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff" +186"fffffffffffffffffffffffffffffffffffffffffffffffff",187"000000000000000000000000000000000000000000000000000000000000000" +188"0000000000000000000000000000000000000000000000000");189}190191private static void testSmallOrder(String name, String a_pri,192String b_pub, String result) throws Exception {193194try {195runDiffieHellmanTest(name, a_pri, b_pub, result);196} catch (InvalidKeyException ex) {197return;198}199200throw new RuntimeException("No exception on small-order point");201}202203private static void runNonCanonicalTest() throws Exception {204// Test non-canonical values205206// high bit of public key set207// X25519208runDiffieHellmanTest(209"X25519",210"77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",211"DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B8F",212"954e472439316f118ae158b65619eecff9e6bcf51ab29add66f3fd088681e233");213214runDiffieHellmanTest(215"3030020100300706032b656e05000422042077076d0a7318a57d3c16c1725" +216"1b26645df4c2f87ebc0992ab177fba51db92c2a",217"302c300706032b656e0500032100de9edb7d7b7dc1b4d35b61c2ece435373f" +218"8343c85b78674dadfc7e146f882b8f",219"954e472439316f118ae158b65619eecff9e6bcf51ab29add66f3fd088681e233");220221// large public key222223// X25519224// public key value is 2^255-2225runDiffieHellmanTest(226"X25519",227"77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",228"FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F",229"81a02a45014594332261085128959869fc0540c6b12380f51db4b41380de2c2c");230231runDiffieHellmanTest(232"3030020100300706032b656e05000422042077076d0a7318a57d3c16c17251" +233"b26645df4c2f87ebc0992ab177fba51db92c2a",234"302c300706032b656e0500032100FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +235"FFFFFFFFFFFFFFFFFFFFFFFFFFFF7F",236"81a02a45014594332261085128959869fc0540c6b12380f51db4b41380de2c2c");237238// X448239// public key value is 2^448-2240runDiffieHellmanTest(241"X448",242"9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" +243"F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B",244"FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +245"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",246"66e2e682b1f8e68c809f1bb3e406bd826921d9c1a5bfbfcbab7ae72feecee6" +247"3660eabd54934f3382061d17607f581a90bdac917a064959fb");248249runDiffieHellmanTest(250"3048020100300706032B656F0500043A04389A8F4925D1519F5775CF46B04B" +251"5800D4EE9EE8BAE8BC5565D498C28DD9C9BAF574A9419744897391006382A6" +252"F127AB1D9AC2D8C0A598726B",253"3044300706032B656F0500033900FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +254"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +255"FFFFFFFFFFFFFFFF",256"66e2e682b1f8e68c809f1bb3e406bd826921d9c1a5bfbfcbab7ae72feecee6" +257"3660eabd54934f3382061d17607f581a90bdac917a064959fb");258259}260261private static void runKAT() throws Exception {262// Test both sides of the key exchange using vectors in RFC 7748263264// X25519265// raw266runDiffieHellmanTest(267"X25519",268"77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",269"DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B4F",270"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");271272runDiffieHellmanTest(273"X25519",274"5DAB087E624A8A4B79E17F8B83800EE66F3BB1292618B6FD1C2F8B27FF88E0EB",275"8520F0098930A754748B7DDCB43EF75A0DBF3A0D26381AF4EBA4A98EAA9B4E6A",276"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");277278// encoded279runDiffieHellmanTest(280"3030020100300706032B656E05000422042077076D0A7318A57D3C16C17251" +281"B26645DF4C2F87EBC0992AB177FBA51DB92C2A",282"302C300706032B656E0500032100DE9EDB7D7B7DC1B4D35B61C2ECE435373F" +283"8343C85B78674DADFC7E146F882B4F",284"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");285286runDiffieHellmanTest(287"3030020100300706032B656E0500042204205DAB087E624A8A4B79E17F8B83" +288"800EE66F3BB1292618B6FD1C2F8B27FF88E0EB",289"302C300706032B656E05000321008520F0098930A754748B7DDCB43EF75A0D" +290"BF3A0D26381AF4EBA4A98EAA9B4E6A",291"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");292293// X448294//raw295runDiffieHellmanTest(296"X448",297"9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" +298"F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B",299"3EB7A829B0CD20F5BCFC0B599B6FECCF6DA4627107BDB0D4F345B43027D8B9" +300"72FC3E34FB4232A13CA706DCB57AEC3DAE07BDC1C67BF33609",301"07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" +302"56fd2464c335543936521c24403085d59a449a5037514a879d");303304runDiffieHellmanTest(305"X448",306"1C306A7AC2A0E2E0990B294470CBA339E6453772B075811D8FAD0D1D6927C1" +307"20BB5EE8972B0D3E21374C9C921B09D1B0366F10B65173992D",308"9B08F7CC31B7E3E67D22D5AEA121074A273BD2B83DE09C63FAA73D2C22C5D9" +309"BBC836647241D953D40C5B12DA88120D53177F80E532C41FA0",310"07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" +311"56fd2464c335543936521c24403085d59a449a5037514a879d");312313//encoded314runDiffieHellmanTest(315"3048020100300706032B656F0500043A04389A8F4925D1519F5775CF46B04B" +316"5800D4EE9EE8BAE8BC5565D498C28DD9C9BAF574A9419744897391006382A6" +317"F127AB1D9AC2D8C0A598726B",318"3044300706032B656F05000339003EB7A829B0CD20F5BCFC0B599B6FECCF6D" +319"A4627107BDB0D4F345B43027D8B972FC3E34FB4232A13CA706DCB57AEC3DAE" +320"07BDC1C67BF33609",321"07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" +322"56fd2464c335543936521c24403085d59a449a5037514a879d");323324runDiffieHellmanTest(325"3048020100300706032B656F0500043A04381C306A7AC2A0E2E0990B294470" +326"CBA339E6453772B075811D8FAD0D1D6927C120BB5EE8972B0D3E21374C9C92" +327"1B09D1B0366F10B65173992D",328"3044300706032B656F05000339009B08F7CC31B7E3E67D22D5AEA121074A27" +329"3BD2B83DE09C63FAA73D2C22C5D9BBC836647241D953D40C5B12DA88120D53" +330"177F80E532C41FA0",331"07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" +332"56fd2464c335543936521c24403085d59a449a5037514a879d");333}334335private static void runDiffieHellmanTest(String a_pri,336String b_pub, String result) throws Exception {337338KeyFactory kf = KeyFactory.getInstance("XDH");339byte[] a_pri_ba = HexFormat.of().parseHex(a_pri);340KeySpec privateSpec = new PKCS8EncodedKeySpec(a_pri_ba);341PrivateKey privateKey = kf.generatePrivate(privateSpec);342byte[] b_pub_ba = HexFormat.of().parseHex(b_pub);343KeySpec publicSpec = new X509EncodedKeySpec(b_pub_ba);344PublicKey publicKey = kf.generatePublic(publicSpec);345346KeyAgreement ka = KeyAgreement.getInstance("XDH");347ka.init(privateKey);348ka.doPhase(publicKey, true);349350byte[] sharedSecret = ka.generateSecret();351byte[] expectedResult = HexFormat.of().parseHex(result);352if (!Arrays.equals(sharedSecret, expectedResult)) {353throw new RuntimeException("fail: expected=" + result + ", actual="354+ HexFormat.of().withUpperCase().formatHex(sharedSecret));355}356357}358359private static void runDiffieHellmanTest(String curveName, String a_pri,360String b_pub, String result) throws Exception {361362NamedParameterSpec paramSpec = new NamedParameterSpec(curveName);363KeyFactory kf = KeyFactory.getInstance("XDH");364KeySpec privateSpec = new XECPrivateKeySpec(paramSpec,365HexFormat.of().parseHex(a_pri));366PrivateKey privateKey = kf.generatePrivate(privateSpec);367boolean clearHighBit = curveName.equals("X25519");368KeySpec publicSpec = new XECPublicKeySpec(paramSpec,369Convert.hexStringToBigInteger(clearHighBit, b_pub));370PublicKey publicKey = kf.generatePublic(publicSpec);371372byte[] encodedPrivateKey = privateKey.getEncoded();373System.out.println("Encoded private: " +374HexFormat.of().withUpperCase().formatHex(encodedPrivateKey));375System.out.println(HexPrinter.simple()376.formatter(ASN1Formatter.formatter())377.toString(encodedPrivateKey));378byte[] encodedPublicKey = publicKey.getEncoded();379System.out.println("Encoded public: " +380HexFormat.of().withUpperCase().formatHex(encodedPublicKey));381System.out.println(HexPrinter.simple()382.formatter(ASN1Formatter.formatter())383.toString(encodedPublicKey));384KeyAgreement ka = KeyAgreement.getInstance("XDH");385ka.init(privateKey);386ka.doPhase(publicKey, true);387388byte[] sharedSecret = ka.generateSecret();389byte[] expectedResult = HexFormat.of().parseHex(result);390if (!Arrays.equals(sharedSecret, expectedResult)) {391throw new RuntimeException("fail: expected=" + result + ", actual="392+ HexFormat.of().withUpperCase().formatHex(sharedSecret));393}394}395396/*397* Ensure that SunEC rejects parameters/points for the wrong curve398* when the algorithm ID for a specific curve is specified.399*/400private static void runCurveMixTest() throws Exception {401runCurveMixTest("SunEC", "X25519", 448);402runCurveMixTest("SunEC", "X25519", "X448");403runCurveMixTest("SunEC", "X448", 255);404runCurveMixTest("SunEC", "X448", "X25519");405}406407private static void runCurveMixTest(String providerName, String name,408Object param) throws Exception {409410KeyPairGenerator kpg = KeyPairGenerator.getInstance(name,411providerName);412413try {414if (param instanceof Integer) {415kpg.initialize((Integer) param);416} else if (param instanceof String) {417kpg.initialize(new NamedParameterSpec((String) param));418}419throw new RuntimeException(name + " KeyPairGenerator accepted "420+ param.toString() + " parameters");421} catch (InvalidParameterException ex) {422// expected423}424425// the rest of the test uses the parameter as an algorithm name to426// produce keys427if (param instanceof Integer) {428return;429}430String otherName = (String) param;431KeyPairGenerator otherKpg = KeyPairGenerator.getInstance(otherName,432providerName);433KeyPair otherKp = otherKpg.generateKeyPair();434435// ensure the KeyFactory rejects incorrect keys436KeyFactory kf = KeyFactory.getInstance(name, providerName);437try {438kf.getKeySpec(otherKp.getPublic(), XECPublicKeySpec.class);439throw new RuntimeException(name + " KeyFactory accepted "440+ param.toString() + " key");441} catch (InvalidKeySpecException ex) {442// expected443}444try {445kf.getKeySpec(otherKp.getPrivate(), XECPrivateKeySpec.class);446throw new RuntimeException(name + " KeyFactory accepted "447+ param.toString() + " key");448} catch (InvalidKeySpecException ex) {449// expected450}451452try {453kf.translateKey(otherKp.getPublic());454throw new RuntimeException(name + " KeyFactory accepted "455+ param.toString() + " key");456} catch (InvalidKeyException ex) {457// expected458}459try {460kf.translateKey(otherKp.getPrivate());461throw new RuntimeException(name + " KeyFactory accepted "462+ param.toString() + " key");463} catch (InvalidKeyException ex) {464// expected465}466467KeyFactory otherKf = KeyFactory.getInstance(otherName, providerName);468XECPublicKeySpec otherPubSpec = otherKf.getKeySpec(otherKp.getPublic(),469XECPublicKeySpec.class);470try {471kf.generatePublic(otherPubSpec);472throw new RuntimeException(name + " KeyFactory accepted "473+ param.toString() + " key");474} catch (InvalidKeySpecException ex) {475// expected476}477XECPrivateKeySpec otherPriSpec =478otherKf.getKeySpec(otherKp.getPrivate(), XECPrivateKeySpec.class);479try {480kf.generatePrivate(otherPriSpec);481throw new RuntimeException(name + " KeyFactory accepted "482+ param.toString() + " key");483} catch (InvalidKeySpecException ex) {484// expected485}486487// ensure the KeyAgreement rejects incorrect keys488KeyAgreement ka = KeyAgreement.getInstance(name, providerName);489try {490ka.init(otherKp.getPrivate());491throw new RuntimeException(name + " KeyAgreement accepted "492+ param.toString() + " key");493} catch (InvalidKeyException ex) {494// expected495}496KeyPair kp = kpg.generateKeyPair();497ka.init(kp.getPrivate());498try {499// This should always be rejected because it doesn't match the key500// passed to init, but it is tested here for good measure.501ka.doPhase(otherKp.getPublic(), true);502throw new RuntimeException(name + " KeyAgreement accepted "503+ param.toString() + " key");504} catch (InvalidKeyException ex) {505// expected506}507}508}509510511512