Path: blob/master/test/jdk/sun/security/rsa/pss/SerializedPSSKey.java
41153 views
/*1* Copyright (c) 2020, 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 static javax.crypto.Cipher.PRIVATE_KEY;24import static javax.crypto.Cipher.PUBLIC_KEY;25import java.io.ByteArrayInputStream;26import java.io.ByteArrayOutputStream;27import java.io.IOException;28import java.io.ObjectInputStream;29import java.io.ObjectOutputStream;30import java.security.InvalidKeyException;31import java.security.Key;32import java.security.KeyFactory;33import java.security.KeyPair;34import java.security.KeyPairGenerator;35import java.security.MessageDigest;36import java.security.NoSuchAlgorithmException;37import java.security.NoSuchProviderException;38import java.security.PrivateKey;39import java.security.PublicKey;40import java.security.Signature;41import java.security.interfaces.RSAPrivateCrtKey;42import java.security.interfaces.RSAPublicKey;43import java.security.spec.InvalidKeySpecException;44import java.security.spec.MGF1ParameterSpec;45import java.security.spec.PKCS8EncodedKeySpec;46import java.security.spec.PSSParameterSpec;47import java.security.spec.RSAKeyGenParameterSpec;48import java.security.spec.RSAPrivateCrtKeySpec;49import java.security.spec.RSAPublicKeySpec;50import java.security.spec.X509EncodedKeySpec;51import java.util.Arrays;5253/**54* @test @bug 824233555* @summary Test RSASSA-PSS serialized keys56* @run main SerializedPSSKey57*/58public class SerializedPSSKey {5960private static final String ALGO = "RSASSA-PSS";61private static final String OID = "1.2.840.113549.1.1.10";62private static final String PROVIDER = "SunRsaSign";63private static final int KEY_SIZE = 2048;64private static final byte[] DATA = "Test".getBytes();65/**66* Digest algorithms to test w/ RSASSA-PSS signature algorithms67*/68private static final String[] DIGEST_ALG = {69"SHA-1", "SHA-224", "SHA-256", "SHA-384",70"SHA-512", "SHA-512/224", "SHA-512/256"71};7273public static void main(String[] args) throws Exception {7475for (String algo : new String[]{ALGO, OID}) {76KeyPairGenerator kpg = KeyPairGenerator.getInstance(algo, PROVIDER);7778// Algorithm-Independent Initialization79kpg.initialize(KEY_SIZE);80KeyPair kp = kpg.generateKeyPair();81test(algo, kp, null);82for (String digest : DIGEST_ALG) {83PSSParameterSpec params = genPSSParameter(digest, KEY_SIZE);84// RSAKeyGenParameterSpec#1 Initialization85kpg.initialize(new RSAKeyGenParameterSpec(KEY_SIZE,86RSAKeyGenParameterSpec.F4, params));87KeyPair kp2 = kpg.generateKeyPair();88test(algo, kp2, params);89}90System.out.println("Successful with : " + algo);91}92}9394private static void test(String algo, KeyPair orig, PSSParameterSpec params)95throws Exception {9697Key[] privs = manipulateKey(algo, PRIVATE_KEY, orig.getPrivate());98Key[] pubs = manipulateKey(algo, PUBLIC_KEY, orig.getPublic());99for (Key pri : privs) {100for (Key pub : pubs) {101testSerialize(orig, new KeyPair(102(PublicKey) pub, (PrivateKey) pri));103if (params != null) {104testSignature(algo, (PublicKey) pub,105(PrivateKey) pri, params);106}107}108}109}110111private static void testSignature(String algo, PublicKey pub,112PrivateKey priv, PSSParameterSpec params) throws Exception {113114Signature sig = Signature.getInstance(algo, PROVIDER);115sig.setParameter(params);116sig.initSign(priv);117sig.update(DATA);118byte[] signature = sig.sign();119120sig.initVerify(pub);121sig.update(DATA);122if (!sig.verify(signature)) {123throw new RuntimeException("Signature verification failed");124}125// Re-verify the signature with another Signature instance126Signature sig1 = Signature.getInstance(algo, PROVIDER);127sig1.setParameter(params);128sig1.initVerify(pub);129sig1.update(DATA);130if (!sig1.verify(signature)) {131throw new RuntimeException("Signature verification failed");132}133}134135private static Key[] manipulateKey(String algo, int type, Key key)136throws NoSuchAlgorithmException, InvalidKeySpecException,137NoSuchProviderException, InvalidKeyException {138139KeyFactory kf = KeyFactory.getInstance(algo, PROVIDER);140switch (type) {141case PUBLIC_KEY:142return new Key[]{143kf.generatePublic(kf.getKeySpec(key, RSAPublicKeySpec.class)),144kf.generatePublic(new X509EncodedKeySpec(key.getEncoded())),145kf.generatePublic(new RSAPublicKeySpec(146((RSAPublicKey) key).getModulus(),147((RSAPublicKey) key).getPublicExponent(),148((RSAPublicKey) key).getParams())),149kf.translateKey(key)150};151case PRIVATE_KEY:152RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey) key;153return new Key[]{154kf.generatePrivate(155kf.getKeySpec(key, RSAPrivateCrtKeySpec.class)),156kf.generatePrivate(new PKCS8EncodedKeySpec(key.getEncoded())),157kf.generatePrivate(new RSAPrivateCrtKeySpec(158crtKey.getModulus(),159crtKey.getPublicExponent(),160crtKey.getPrivateExponent(),161crtKey.getPrimeP(),162crtKey.getPrimeQ(),163crtKey.getPrimeExponentP(),164crtKey.getPrimeExponentQ(),165crtKey.getCrtCoefficient(),166crtKey.getParams()167)),168kf.translateKey(key)169};170}171throw new RuntimeException("We shouldn't reach here");172}173174private static PSSParameterSpec genPSSParameter(String digest, int keySize)175throws NoSuchAlgorithmException {176177int dgLen = MessageDigest.getInstance(digest).getDigestLength();178// pick a salt length based on the key length and digestAlgo179int saltLength = keySize / 8 - dgLen - 2;180if (saltLength < 0) {181System.out.printf("keysize: %s, digestLen: %s%n", keySize / 8, dgLen);182return null;183}184return new PSSParameterSpec(digest, "MGF1", new MGF1ParameterSpec(digest),185saltLength, PSSParameterSpec.TRAILER_FIELD_BC);186}187188/**189* Compare original KeyPair with transformed ones.190*/191private static void testKeyEquals(KeyPair orig, PublicKey pubKey,192PrivateKey priKey) {193194if (!orig.getPrivate().equals(priKey)195&& orig.getPrivate().hashCode() != priKey.hashCode()196&& !Arrays.equals(orig.getPrivate().getEncoded(),197priKey.getEncoded())) {198throw new RuntimeException(199"PrivateKey is not equal with transformed one");200}201if (!orig.getPublic().equals(pubKey)202&& orig.getPublic().hashCode() != pubKey.hashCode()203&& !Arrays.equals(orig.getPublic().getEncoded(),204pubKey.getEncoded())) {205throw new RuntimeException(206"PublicKey is not equal with transformed one");207}208}209210/**211* Test serialization of KeyPair and Keys it holds.212*/213private static void testSerialize(KeyPair orig, KeyPair transformed)214throws Exception {215216testKeyEquals(orig, transformed.getPublic(), transformed.getPrivate());217PrivateKey serializedPrivate = deserializedCopy(transformed.getPrivate(),218PrivateKey.class);219PublicKey serializedPublic = deserializedCopy(transformed.getPublic(),220PublicKey.class);221testKeyEquals(orig, serializedPublic, serializedPrivate);222// Verify Serialized KeyPair instance.223KeyPair copy = deserializedCopy(transformed, KeyPair.class);224testKeyEquals(orig, copy.getPublic(), copy.getPrivate());225}226227private static <T extends Object> T deserializedCopy(T orig, Class<T> type)228throws IOException, ClassNotFoundException {229return deserialize(serialize(orig), type);230}231232/**233* Deserialize the Key object.234*/235private static <T extends Object> T deserialize(byte[] serialized,236Class<T> type) throws IOException, ClassNotFoundException {237238T key = null;239try (ByteArrayInputStream bis = new ByteArrayInputStream(serialized);240ObjectInputStream ois = new ObjectInputStream(bis)) {241key = (T) ois.readObject();242}243return key;244}245246/**247* Serialize the given Key object.248*/249private static <T extends Object> byte[] serialize(T key)250throws IOException {251252try (ByteArrayOutputStream bos = new ByteArrayOutputStream();253ObjectOutputStream oos = new ObjectOutputStream(bos)) {254oos.writeObject(key);255return bos.toByteArray();256}257}258259}260261262