1 /* 2 * Copyright (c) 2003, 2013, 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}openjdk-redirect.html?v=8&path=/platform/serialization/spec/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 * <p> 116 * 117 * @param type either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE 118 * @param algorithm the algorithm returned from 119 * {@code Key.getAlgorithm()} 120 * @param format the encoding format returned from 121 * {@code Key.getFormat()} 122 * @param encoded the encoded bytes returned from 123 * {@code Key.getEncoded()} 124 * 125 * @exception NullPointerException 126 * if type is {@code null}, 127 * if algorithm is {@code null}, 128 * if format is {@code null}, 129 * or if encoded is {@code null} 130 */ 131 public KeyRep(Type type, String algorithm, 132 String format, byte[] encoded) { 133 134 if (type == null || algorithm == null || 135 format == null || encoded == null) { 136 throw new NullPointerException("invalid null input(s)"); 137 } 138 139 this.type = type; 140 this.algorithm = algorithm; 141 this.format = format.toUpperCase(Locale.ENGLISH); 142 this.encoded = encoded.clone(); 143 } 144 145 /** 146 * Resolve the Key object. 147 * 148 * <p> This method supports three Type/format combinations: 149 * <ul> 150 * <li> Type.SECRET/"RAW" - returns a SecretKeySpec object 151 * constructed using encoded key bytes and algorithm 152 * <li> Type.PUBLIC/"X.509" - gets a KeyFactory instance for 153 * the key algorithm, constructs an X509EncodedKeySpec with the 154 * encoded key bytes, and generates a public key from the spec 155 * <li> Type.PRIVATE/"PKCS#8" - gets a KeyFactory instance for 156 * the key algorithm, constructs a PKCS8EncodedKeySpec with the 157 * encoded key bytes, and generates a private key from the spec 158 * </ul> 159 * 160 * <p> 161 * 162 * @return the resolved Key object 163 * 164 * @exception ObjectStreamException if the Type/format 165 * combination is unrecognized, if the algorithm, key format, or 166 * encoded key bytes are unrecognized/invalid, of if the 167 * resolution of the key fails for any reason 168 */ 169 protected Object readResolve() throws ObjectStreamException { 170 try { 171 if (type == Type.SECRET && RAW.equals(format)) { 172 return new SecretKeySpec(encoded, algorithm); 173 } else if (type == Type.PUBLIC && X509.equals(format)) { 174 KeyFactory f = KeyFactory.getInstance(algorithm); 175 return f.generatePublic(new X509EncodedKeySpec(encoded)); 176 } else if (type == Type.PRIVATE && PKCS8.equals(format)) { 177 KeyFactory f = KeyFactory.getInstance(algorithm); 178 return f.generatePrivate(new PKCS8EncodedKeySpec(encoded)); 179 } else { 180 throw new NotSerializableException 181 ("unrecognized type/format combination: " + 182 type + "/" + format); 183 } 184 } catch (NotSerializableException nse) { 185 throw nse; 186 } catch (Exception e) { 187 NotSerializableException nse = new NotSerializableException 188 ("java.security.Key: " + 189 "[" + type + "] " + 190 "[" + algorithm + "] " + 191 "[" + format + "]"); 192 nse.initCause(e); 193 throw nse; 194 } 195 } 196 } 197