Path: blob/master/test/jdk/java/security/KeyAgreement/KeySpecTest.java
41149 views
/*1* Copyright (c) 2018, 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 818435926* @summary Standard tests on KeySpec, KeyFactory, KeyPairs and Keys.27* Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <Curve*>28* @run main KeySpecTest DiffieHellman SunJCE DiffieHellman29* @run main KeySpecTest ECDH SunEC EC30* @run main KeySpecTest XDH SunEC XDH X2551931* @run main KeySpecTest XDH SunEC XDH X44832*/33import java.io.ByteArrayInputStream;34import java.io.ByteArrayOutputStream;35import java.io.IOException;36import java.io.ObjectInputStream;37import java.io.ObjectOutputStream;38import java.security.KeyFactory;39import java.security.KeyPair;40import java.security.KeyPairGenerator;41import java.security.PrivateKey;42import java.security.PublicKey;43import java.security.spec.ECPrivateKeySpec;44import java.security.spec.ECPublicKeySpec;45import java.security.spec.PKCS8EncodedKeySpec;46import java.security.spec.X509EncodedKeySpec;47import java.security.spec.NamedParameterSpec;48import java.security.spec.XECPublicKeySpec;49import java.security.spec.XECPrivateKeySpec;50import java.security.spec.KeySpec;51import java.util.ArrayList;52import java.util.List;53import java.util.Arrays;54import javax.crypto.KeyAgreement;55import javax.crypto.spec.DHPrivateKeySpec;56import javax.crypto.spec.DHPublicKeySpec;5758public class KeySpecTest {5960public static void main(String[] args) throws Exception {6162String kaAlgo = args[0];63String provider = args[1];64String kpgAlgo = args[2];65KeyPair kp = genKeyPair(provider, kpgAlgo,66(args.length > 3) ? args[3] : kpgAlgo);67testKeySpecs(provider, kaAlgo, kpgAlgo, kp);68testEncodedKeySpecs(provider, kaAlgo, kpgAlgo, kp);69}7071/**72* Generate keyPair based on KeyPairGenerator algorithm.73*/74private static KeyPair genKeyPair(String provider, String kpgAlgo,75String kpgInit) throws Exception {7677KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);78switch (kpgInit) {79case "DiffieHellman":80kpg.initialize(512);81break;82case "EC":83kpg.initialize(256);84break;85case "X25519":86kpg.initialize(255);87break;88case "X448":89kpg.initialize(448);90break;91default:92throw new RuntimeException("Invalid Algo name " + kpgInit);93}94return kpg.generateKeyPair();95}9697/**98* Standard Test with Keys and the one generated through Spec.99*/100private static void testKeySpecs(String provider, String kaAlgo,101String kpgAlgo, KeyPair kp) throws Exception {102103KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);104// For each public KeySpec supported by KeyPairGenerator105for (Class pubSpecType106: getCompatibleKeySpecs(kpgAlgo, KeyType.PUBLIC)) {107//For each private KeySpec supported by KeyPairGenerator108for (Class priSpecType109: getCompatibleKeySpecs(kpgAlgo, KeyType.PRIVATE)) {110// Transform original PublicKey through KeySpec111KeySpec pubSpec = kf.getKeySpec(kp.getPublic(), pubSpecType);112PublicKey pubKey = kf.generatePublic(pubSpec);113// Transform original PrivateKey through KeySpec114KeySpec priSpec = kf.getKeySpec(kp.getPrivate(), priSpecType);115PrivateKey priKey = kf.generatePrivate(priSpec);116117// Test the keys are equal after transformation through KeySpec.118testKeyEquals(kp, pubKey, priKey);119// Test the keys are serializable.120testSerialize(kp);121// Test Parameter name.122if (!kaAlgo.equals("DiffieHellman")) {123testParamName(priSpec, pubSpec);124}125// Compare KeyAgreement secret generated from original keys126// and by the keys after transformed through KeySpec.127if (!Arrays.equals(getKeyAgreementSecret(provider, kaAlgo,128kp.getPublic(), kp.getPrivate()),129getKeyAgreementSecret(provider, kaAlgo,130pubKey, priKey))) {131throw new RuntimeException("KeyAgreement secret mismatch.");132}133}134}135}136137/**138* Standard Test with Keys and the one generated from encoded bytes.139*/140private static void testEncodedKeySpecs(String provider, String kaAlgo,141String kpgAlgo, KeyPair kp) throws Exception {142143KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);144PKCS8EncodedKeySpec priSpec145= new PKCS8EncodedKeySpec(kp.getPrivate().getEncoded());146PrivateKey priKey = kf.generatePrivate(priSpec);147148X509EncodedKeySpec pubSpec149= new X509EncodedKeySpec(kp.getPublic().getEncoded());150PublicKey pubKey = kf.generatePublic(pubSpec);151152// Test the keys are equal after transformation through KeySpec.153testKeyEquals(kp, pubKey, priKey);154// Test the keys are serializable.155testSerialize(kp);156// Test Parameter name.157if (!kaAlgo.equals("DiffieHellman")) {158testParamName(priSpec, pubSpec);159}160// Compare KeyAgreement secret generated from original keys161// and by the keys after transformed through KeySpec.162if (!Arrays.equals(getKeyAgreementSecret(provider, kaAlgo,163kp.getPublic(), kp.getPrivate()),164getKeyAgreementSecret(provider, kaAlgo, pubKey, priKey))) {165throw new RuntimeException("KeyAgreement secret mismatch.");166}167}168169private enum KeyType {170PUBLIC, PRIVATE;171}172173/**174* Provides Compatible KeySpec Type list for KeyPairGenerator algorithm.175*/176private static List<Class> getCompatibleKeySpecs(String kpgAlgo,177KeyType type) {178179List<Class> specs = new ArrayList<>();180switch (kpgAlgo) {181case "DiffieHellman":182if (type == KeyType.PUBLIC) {183return Arrays.asList(X509EncodedKeySpec.class,184DHPublicKeySpec.class);185} else {186return Arrays.asList(PKCS8EncodedKeySpec.class,187DHPrivateKeySpec.class);188}189case "EC":190if (type == KeyType.PUBLIC) {191return Arrays.asList(X509EncodedKeySpec.class,192ECPublicKeySpec.class);193} else {194return Arrays.asList(PKCS8EncodedKeySpec.class,195ECPrivateKeySpec.class);196}197case "XDH":198if (type == KeyType.PUBLIC) {199return Arrays.asList(X509EncodedKeySpec.class,200XECPublicKeySpec.class);201} else {202return Arrays.asList(PKCS8EncodedKeySpec.class,203XECPrivateKeySpec.class);204}205}206return specs;207}208209/**210* Generate KeyAgreement Secret.211*/212private static byte[] getKeyAgreementSecret(String provider, String kaAlgo,213PublicKey pubKey, PrivateKey priKey) throws Exception {214215KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider);216ka.init(priKey);217ka.doPhase(pubKey, true);218return ka.generateSecret();219}220221/**222* Compare original KeyPair with transformed ones.223*/224private static void testKeyEquals(KeyPair kp, PublicKey pubKey,225PrivateKey priKey) {226227if (!kp.getPrivate().equals(priKey)228&& kp.getPrivate().hashCode() != priKey.hashCode()) {229throw new RuntimeException("PrivateKey is not equal with PrivateKey"230+ " generated through KeySpec");231}232if (!kp.getPublic().equals(pubKey)233&& kp.getPublic().hashCode() != pubKey.hashCode()) {234throw new RuntimeException("PublicKey is not equal with PublicKey"235+ " generated through KeySpec");236}237}238239/**240* Compare the parameter names of Public/Private KeySpec from a pair.241*/242private static void testParamName(KeySpec priSpec, KeySpec pubSpec) {243244if (priSpec instanceof XECPrivateKeySpec245&& pubSpec instanceof XECPublicKeySpec) {246if (((NamedParameterSpec) ((XECPrivateKeySpec) priSpec)247.getParams()).getName()248!= ((NamedParameterSpec) ((XECPublicKeySpec) pubSpec)249.getParams()).getName()) {250throw new RuntimeException("Curve name mismatch found");251}252}253}254255/**256* Test serialization of KeyPair and Keys it holds.257*/258private static void testSerialize(KeyPair keyPair) throws Exception {259260// Verify Serialized PrivateKey instance.261if (!keyPair.getPrivate().equals(262deserializedCopy(keyPair.getPrivate(), PrivateKey.class))) {263throw new RuntimeException("PrivateKey is not equal with PrivateKey"264+ " generated through Serialization");265}266// Verify Serialized PublicKey instance.267if (!keyPair.getPublic().equals(268deserializedCopy(keyPair.getPublic(), PublicKey.class))) {269throw new RuntimeException("PublicKey is not equal with PublicKey"270+ " generated through Serialization");271}272// Verify Serialized KeyPair instance.273KeyPair copy = deserializedCopy(keyPair, KeyPair.class);274if (!keyPair.getPrivate().equals(copy.getPrivate())) {275throw new RuntimeException("PrivateKey is not equal with PrivateKey"276+ " generated through Serialized KeyPair");277}278if (!keyPair.getPublic().equals(copy.getPublic())) {279throw new RuntimeException("PublicKey is not equal with PublicKey"280+ " generated through Serialized KeyPair");281}282}283284private static <T extends Object> T deserializedCopy(T orig, Class<T> type)285throws IOException, ClassNotFoundException {286return deserialize(serialize(orig), type);287}288289/**290* Deserialize the Key object.291*/292private static <T extends Object> T deserialize(byte[] serialized,293Class<T> type) throws IOException, ClassNotFoundException {294295T key = null;296try (ByteArrayInputStream bis = new ByteArrayInputStream(serialized);297ObjectInputStream ois = new ObjectInputStream(bis)) {298key = (T) ois.readObject();299}300return key;301}302303/**304* Serialize the given Key object.305*/306private static <T extends Object> byte[] serialize(T key)307throws IOException {308309try (ByteArrayOutputStream bos = new ByteArrayOutputStream();310ObjectOutputStream oos = new ObjectOutputStream(bos)) {311oos.writeObject(key);312return bos.toByteArray();313}314}315}316317318