1 /* 2 * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.security; 27 28 import java.io.*; 29 import java.util.Locale; 30 31 import java.security.spec.PKCS8EncodedKeySpec; 32 import java.security.spec.X509EncodedKeySpec; 33 import java.security.spec.InvalidKeySpecException; 34 35 import javax.crypto.SecretKeyFactory; 36 import javax.crypto.spec.SecretKeySpec; 37 38 /** 39 * Standardized representation for serialized Key objects. 40 * 41 * <p> 42 * 43 * Note that a serialized Key may contain sensitive information 44 * which should not be exposed in untrusted environments. See the 45 * <a href="{@docRoot}/../specs/serialization/security.html"> 46 * Security Appendix</a> 47 * of the Serialization Specification for more information. 48 * 49 * @see Key 50 * @see KeyFactory 51 * @see javax.crypto.spec.SecretKeySpec 52 * @see java.security.spec.X509EncodedKeySpec 53 * @see java.security.spec.PKCS8EncodedKeySpec 54 * 55 * @since 1.5 56 */ 57 58 public class KeyRep implements Serializable { 59 60 private static final long serialVersionUID = -4757683898830641853L; 61 62 /** 63 * Key type. 64 * 65 * @since 1.5 66 */ 67 public static enum Type { 68 69 /** Type for secret keys. */ 70 SECRET, 71 72 /** Type for public keys. */ 73 PUBLIC, 74 75 /** Type for private keys. */ 76 PRIVATE, 77 78 } 79 80 private static final String PKCS8 = "PKCS#8"; 81 private static final String X509 = "X.509"; 82 private static final String RAW = "RAW"; 83 84 /** 85 * Either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE 86 * 87 * @serial 88 */ 89 private Type type; 90 91 /** 92 * The Key algorithm 93 * 94 * @serial 95 */ 96 private String algorithm; 97 98 /** 99 * The Key encoding format 100 * 101 * @serial 102 */ 103 private String format; 104 105 /** 106 * The encoded Key bytes 107 * 108 * @serial 109 */ 110 private byte[] encoded; 111 112 /** 113 * Construct the alternate Key class. 114 * 115 * @param type either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE 116 * @param algorithm the algorithm returned from 117 * {@code Key.getAlgorithm()} 118 * @param format the encoding format returned from 119 * {@code Key.getFormat()} 120 * @param encoded the encoded bytes returned from 121 * {@code Key.getEncoded()} 122 * 123 * @exception NullPointerException 124 * if type is {@code null}, 125 * if algorithm is {@code null}, 126 * if format is {@code null}, 127 * or if encoded is {@code null} 128 */ KeyRep(Type type, String algorithm, String format, byte[] encoded)129 public KeyRep(Type type, String algorithm, 130 String format, byte[] encoded) { 131 132 if (type == null || algorithm == null || 133 format == null || encoded == null) { 134 throw new NullPointerException("invalid null input(s)"); 135 } 136 137 this.type = type; 138 this.algorithm = algorithm; 139 this.format = format.toUpperCase(Locale.ENGLISH); 140 this.encoded = encoded.clone(); 141 } 142 143 /** 144 * Resolve the Key object. 145 * 146 * <p> This method supports three Type/format combinations: 147 * <ul> 148 * <li> Type.SECRET/"RAW" - returns a SecretKeySpec object 149 * constructed using encoded key bytes and algorithm 150 * <li> Type.PUBLIC/"X.509" - gets a KeyFactory instance for 151 * the key algorithm, constructs an X509EncodedKeySpec with the 152 * encoded key bytes, and generates a public key from the spec 153 * <li> Type.PRIVATE/"PKCS#8" - gets a KeyFactory instance for 154 * the key algorithm, constructs a PKCS8EncodedKeySpec with the 155 * encoded key bytes, and generates a private key from the spec 156 * </ul> 157 * 158 * @return the resolved Key object 159 * 160 * @exception ObjectStreamException if the Type/format 161 * combination is unrecognized, if the algorithm, key format, or 162 * encoded key bytes are unrecognized/invalid, of if the 163 * resolution of the key fails for any reason 164 */ readResolve()165 protected Object readResolve() throws ObjectStreamException { 166 try { 167 if (type == Type.SECRET && RAW.equals(format)) { 168 return new SecretKeySpec(encoded, algorithm); 169 } else if (type == Type.PUBLIC && X509.equals(format)) { 170 KeyFactory f = KeyFactory.getInstance(algorithm); 171 return f.generatePublic(new X509EncodedKeySpec(encoded)); 172 } else if (type == Type.PRIVATE && PKCS8.equals(format)) { 173 KeyFactory f = KeyFactory.getInstance(algorithm); 174 return f.generatePrivate(new PKCS8EncodedKeySpec(encoded)); 175 } else { 176 throw new NotSerializableException 177 ("unrecognized type/format combination: " + 178 type + "/" + format); 179 } 180 } catch (NotSerializableException nse) { 181 throw nse; 182 } catch (Exception e) { 183 NotSerializableException nse = new NotSerializableException 184 ("java.security.Key: " + 185 "[" + type + "] " + 186 "[" + algorithm + "] " + 187 "[" + format + "]"); 188 nse.initCause(e); 189 throw nse; 190 } 191 } 192 } 193