Path: blob/master/src/java.base/share/classes/com/sun/crypto/provider/ConstructKeys.java
41161 views
/*1* Copyright (c) 1999, 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. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.crypto.provider;2627import java.security.Key;28import java.security.PublicKey;29import java.security.PrivateKey;30import java.security.KeyFactory;31import java.security.InvalidKeyException;32import java.security.NoSuchAlgorithmException;33import java.security.spec.PKCS8EncodedKeySpec;34import java.security.spec.X509EncodedKeySpec;35import java.security.spec.InvalidKeySpecException;36import java.util.Arrays;37import javax.crypto.SecretKey;38import javax.crypto.Cipher;39import javax.crypto.spec.SecretKeySpec;4041/**42* This class is a helper class which construct key objects43* from encoded keys.44*45* @author Sharon Liu46*47*/4849final class ConstructKeys {50/**51* Construct a public key from its encoding.52*53* @param encodedKey the encoding of a public key.54*55* @param encodedKeyAlgorithm the algorithm the encodedKey is for.56*57* @return a public key constructed from the encodedKey.58*/59private static final PublicKey constructPublicKey(byte[] encodedKey,60String encodedKeyAlgorithm)61throws InvalidKeyException, NoSuchAlgorithmException {62PublicKey key = null;63try {64KeyFactory keyFactory =65KeyFactory.getInstance(encodedKeyAlgorithm,66SunJCE.getInstance());67X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);68key = keyFactory.generatePublic(keySpec);69} catch (NoSuchAlgorithmException nsae) {70// Try to see whether there is another71// provider which supports this algorithm72try {73KeyFactory keyFactory =74KeyFactory.getInstance(encodedKeyAlgorithm);75X509EncodedKeySpec keySpec =76new X509EncodedKeySpec(encodedKey);77key = keyFactory.generatePublic(keySpec);78} catch (NoSuchAlgorithmException nsae2) {79throw new NoSuchAlgorithmException("No installed providers " +80"can create keys for the " +81encodedKeyAlgorithm +82"algorithm");83} catch (InvalidKeySpecException ikse2) {84InvalidKeyException ike =85new InvalidKeyException("Cannot construct public key");86ike.initCause(ikse2);87throw ike;88}89} catch (InvalidKeySpecException ikse) {90InvalidKeyException ike =91new InvalidKeyException("Cannot construct public key");92ike.initCause(ikse);93throw ike;94}9596return key;97}9899/**100* Construct a private key from its encoding.101*102* @param encodedKey the encoding of a private key.103*104* @param encodedKeyAlgorithm the algorithm the wrapped key is for.105*106* @return a private key constructed from the encodedKey.107*/108private static final PrivateKey constructPrivateKey(byte[] encodedKey,109String encodedKeyAlgorithm)110throws InvalidKeyException, NoSuchAlgorithmException {111PrivateKey key = null;112113try {114KeyFactory keyFactory =115KeyFactory.getInstance(encodedKeyAlgorithm,116SunJCE.getInstance());117PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);118return keyFactory.generatePrivate(keySpec);119} catch (NoSuchAlgorithmException nsae) {120// Try to see whether there is another121// provider which supports this algorithm122try {123KeyFactory keyFactory =124KeyFactory.getInstance(encodedKeyAlgorithm);125PKCS8EncodedKeySpec keySpec =126new PKCS8EncodedKeySpec(encodedKey);127key = keyFactory.generatePrivate(keySpec);128} catch (NoSuchAlgorithmException nsae2) {129throw new NoSuchAlgorithmException("No installed providers " +130"can create keys for the " +131encodedKeyAlgorithm +132"algorithm");133} catch (InvalidKeySpecException ikse2) {134InvalidKeyException ike =135new InvalidKeyException("Cannot construct private key");136ike.initCause(ikse2);137throw ike;138}139} catch (InvalidKeySpecException ikse) {140InvalidKeyException ike =141new InvalidKeyException("Cannot construct private key");142ike.initCause(ikse);143throw ike;144}145146return key;147}148149/**150* Construct a secret key from its encoding.151*152* @param encodedKey the encoding of a secret key.153*154* @param encodedKeyAlgorithm the algorithm the secret key is for.155*156* @return a secret key constructed from the encodedKey.157*/158private static final SecretKey constructSecretKey(byte[] encodedKey,159int ofs, int len, String encodedKeyAlgorithm) {160return (new SecretKeySpec(encodedKey, ofs, len, encodedKeyAlgorithm));161}162163static final Key constructKey(byte[] encoding, String keyAlgorithm,164int keyType) throws InvalidKeyException, NoSuchAlgorithmException {165return constructKey(encoding, 0, encoding.length, keyAlgorithm,166keyType);167}168169static final Key constructKey(byte[] encoding, int ofs, int len,170String keyAlgorithm, int keyType)171throws InvalidKeyException, NoSuchAlgorithmException {172switch (keyType) {173case Cipher.SECRET_KEY:174try {175return ConstructKeys.constructSecretKey(encoding, ofs, len,176keyAlgorithm);177} finally {178Arrays.fill(encoding, ofs, len, (byte)0);179}180case Cipher.PRIVATE_KEY:181byte[] encoding2 = encoding;182try {183if (ofs != 0 || len != encoding.length) {184encoding2 = Arrays.copyOfRange(encoding, ofs, ofs + len);185}186return ConstructKeys.constructPrivateKey(encoding2,187keyAlgorithm);188} finally {189Arrays.fill(encoding, ofs, len, (byte)0);190if (encoding2 != encoding) {191Arrays.fill(encoding2, (byte)0);192}193}194case Cipher.PUBLIC_KEY:195if (ofs != 0 || len != encoding.length) {196encoding = Arrays.copyOfRange(encoding, ofs, ofs + len);197}198return ConstructKeys.constructPublicKey(encoding, keyAlgorithm);199default:200throw new NoSuchAlgorithmException("Unsupported key type");201}202}203}204205206