--- /dev/null 2018-02-28 15:06:04.760000000 -0500 +++ new/src/jdk.crypto.ec/share/classes/sun/security/ec/XDHKeyFactory.java 2018-03-09 11:19:29.650014000 -0500 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2018, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.security.ec; + +import java.security.KeyFactorySpi; +import java.security.Key; +import java.security.PublicKey; +import java.security.PrivateKey; +import java.security.InvalidKeyException; +import java.security.interfaces.XECKey; +import java.security.interfaces.XECPrivateKey; +import java.security.interfaces.XECPublicKey; +import java.security.spec.KeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.security.spec.XECPublicKeySpec; +import java.security.spec.XECPrivateKeySpec; + +public final class XDHKeyFactory extends KeyFactorySpi { + + @Override + protected Key engineTranslateKey(Key key) throws InvalidKeyException { + + if (key == null) { + throw new InvalidKeyException("Key must not be null"); + } + + if (key instanceof XECKey) { + XECKey xecKey = (XECKey) key; + XECParameters params = XECParameters.get(InvalidKeyException::new, + xecKey.getParams()); + + if (xecKey instanceof XECPublicKey) { + XECPublicKey publicKey = (XECPublicKey) xecKey; + return new XDHPublicKeyImpl(params, publicKey.getU()); + } else if (xecKey instanceof XECPrivateKey) { + XECPrivateKey privateKey = (XECPrivateKey) xecKey; + byte[] scalar = privateKey.getScalar().orElseThrow( + () -> new InvalidKeyException("No private key data")); + return new XDHPrivateKeyImpl(params, scalar); + } else { + throw new InvalidKeyException("Unsupported XECKey subclass"); + } + } else if (key instanceof PublicKey && + key.getFormat().equals("X.509")) { + return new XDHPublicKeyImpl(key.getEncoded()); + } else if (key instanceof PrivateKey && + key.getFormat().equals("PKCS#8")) { + return new XDHPrivateKeyImpl(key.getEncoded()); + } else { + throw new InvalidKeyException("Unsupported key type or format"); + } + } + + @Override + protected PublicKey engineGeneratePublic(KeySpec keySpec) + throws InvalidKeySpecException { + + try { + return generatePublicImpl(keySpec); + } catch (InvalidKeyException ex) { + throw new InvalidKeySpecException(ex); + } + } + + @Override + protected PrivateKey engineGeneratePrivate(KeySpec keySpec) + throws InvalidKeySpecException { + + try { + return generatePrivateImpl(keySpec); + } catch (InvalidKeyException ex) { + throw new InvalidKeySpecException(ex); + } + } + + + private PublicKey generatePublicImpl(KeySpec keySpec) + throws InvalidKeyException, InvalidKeySpecException { + + if (keySpec instanceof X509EncodedKeySpec) { + X509EncodedKeySpec x509Spec = (X509EncodedKeySpec) keySpec; + return new XDHPublicKeyImpl(x509Spec.getEncoded()); + } else if (keySpec instanceof XECPublicKeySpec) { + XECPublicKeySpec publicKeySpec = (XECPublicKeySpec) keySpec; + XECParameters params = XECParameters.get( + InvalidKeySpecException::new, publicKeySpec.getParams()); + return new XDHPublicKeyImpl(params, publicKeySpec.getU()); + } else { + throw new InvalidKeySpecException( + "Only X509EncodedKeySpec and XECPublicKeySpec are supported"); + } + } + + private PrivateKey generatePrivateImpl(KeySpec keySpec) + throws InvalidKeyException, InvalidKeySpecException { + + if (keySpec instanceof PKCS8EncodedKeySpec) { + PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec) keySpec; + return new XDHPrivateKeyImpl(pkcsSpec.getEncoded()); + } else if (keySpec instanceof XECPrivateKeySpec) { + XECPrivateKeySpec privateKeySpec = (XECPrivateKeySpec) keySpec; + XECParameters params = XECParameters.get( + InvalidKeySpecException::new, privateKeySpec.getParams()); + return new XDHPrivateKeyImpl(params, privateKeySpec.getScalar()); + } else { + throw new InvalidKeySpecException( + "Only PKCS8EncodedKeySpec and XECPrivateKeySpec supported"); + } + } + + protected T engineGetKeySpec(Key key, Class keySpec) + throws InvalidKeySpecException { + + if (key instanceof XECPublicKey) { + if (X509EncodedKeySpec.class.isAssignableFrom(keySpec)) { + if (!key.getFormat().equals("X.509")) { + throw new InvalidKeySpecException("Format is not X.509"); + } + return keySpec.cast(new X509EncodedKeySpec(key.getEncoded())); + } else if (XECPublicKeySpec.class.isAssignableFrom(keySpec)) { + XECPublicKey xecKey = (XECPublicKey) key; + return keySpec.cast( + new XECPublicKeySpec(xecKey.getParams(), xecKey.getU())); + } else { + throw new InvalidKeySpecException( + "KeySpec must be X509EncodedKeySpec or XECPublicKeySpec"); + } + } else if (key instanceof XECPrivateKey) { + if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec)) { + if (!key.getFormat().equals("PKCS#8")) { + throw new InvalidKeySpecException("Format is not PKCS#8"); + } + return keySpec.cast(new PKCS8EncodedKeySpec(key.getEncoded())); + } else if (XECPrivateKeySpec.class.isAssignableFrom(keySpec)) { + XECPrivateKey xecKey = (XECPrivateKey) key; + byte[] scalar = xecKey.getScalar().orElseThrow( + () -> new InvalidKeySpecException("No private key value") + ); + return keySpec.cast( + new XECPrivateKeySpec(xecKey.getParams(), scalar)); + } else { + throw new InvalidKeySpecException + ("KeySpec must be PKCS8EncodedKeySpec or XECPrivateKeySpec"); + } + } else { + throw new InvalidKeySpecException("Unsupported key type"); + } + } +}