1. /*
  2. * @(#)KeyRep.java 1.7 04/04/20
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.security;
  8. import java.io.*;
  9. import java.security.spec.PKCS8EncodedKeySpec;
  10. import java.security.spec.X509EncodedKeySpec;
  11. import java.security.spec.InvalidKeySpecException;
  12. import javax.crypto.SecretKeyFactory;
  13. import javax.crypto.spec.SecretKeySpec;
  14. /**
  15. * Standardized representation for serialized Key objects.
  16. *
  17. * <p>
  18. *
  19. * Note that a serialized Key may contain sensitive information
  20. * which should not be exposed in untrusted environments. See the
  21. * <a href="../../../guide/serialization/spec/security.html">
  22. * Security Appendix</a>
  23. * of the Serialization Specification for more information.
  24. *
  25. * @see Key
  26. * @see KeyFactory
  27. * @see javax.crypto.spec.SecretKeySpec
  28. * @see java.security.spec.X509EncodedKeySpec
  29. * @see java.security.spec.PKCS8EncodedKeySpec
  30. *
  31. * @version 1.7, 04/04/20
  32. * @since 1.5
  33. */
  34. public class KeyRep implements Serializable {
  35. private static final long serialVersionUID = -4757683898830641853L;
  36. /**
  37. * Key type.
  38. *
  39. * @since 1.5
  40. */
  41. public static enum Type {
  42. /** Type for secret keys. */
  43. SECRET,
  44. /** Type for public keys. */
  45. PUBLIC,
  46. /** Type for private keys. */
  47. PRIVATE,
  48. }
  49. private static final String PKCS8 = "PKCS#8";
  50. private static final String X509 = "X.509";
  51. private static final String RAW = "RAW";
  52. /**
  53. * Either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE
  54. *
  55. * @serial
  56. */
  57. private Type type;
  58. /**
  59. * The Key algorithm
  60. *
  61. * @serial
  62. */
  63. private String algorithm;
  64. /**
  65. * The Key encoding format
  66. *
  67. * @serial
  68. */
  69. private String format;
  70. /**
  71. * The encoded Key bytes
  72. *
  73. * @serial
  74. */
  75. private byte[] encoded;
  76. /**
  77. * Construct the alternate Key class.
  78. *
  79. * <p>
  80. *
  81. * @param type either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE
  82. * @param algorithm the algorithm returned from
  83. * <code>Key.getAlgorithm()</code>
  84. * @param format the encoding format returned from
  85. * <code>Key.getFormat()</code>
  86. * @param encoded the encoded bytes returned from
  87. * <code>Key.getEncoded()</code>
  88. *
  89. * @exception NullPointerException
  90. * if type is <code>null</code>,
  91. * if algorithm is <code>null</code>,
  92. * if format is <code>null</code>,
  93. * or if encoded is <code>null</code>
  94. */
  95. public KeyRep(Type type, String algorithm,
  96. String format, byte[] encoded) {
  97. if (type == null || algorithm == null ||
  98. format == null || encoded == null) {
  99. throw new NullPointerException("invalid null input(s)");
  100. }
  101. this.type = type;
  102. this.algorithm = algorithm;
  103. this.format = format.toUpperCase();
  104. this.encoded = (byte[])encoded.clone();
  105. }
  106. /**
  107. * Resolve the Key object.
  108. *
  109. * <p> This method supports three Type/format combinations:
  110. * <ul>
  111. * <li> Type.SECRET/"RAW" - returns a SecretKeySpec object
  112. * constructed using encoded key bytes and algorithm
  113. * <li> Type.PUBLIC/"X.509" - gets a KeyFactory instance for
  114. * the key algorithm, constructs an X509EncodedKeySpec with the
  115. * encoded key bytes, and generates a public key from the spec
  116. * <li> Type.PRIVATE/"PKCS#8" - gets a KeyFactory instance for
  117. * the key algorithm, constructs a PKCS8EncodedKeySpec with the
  118. * encoded key bytes, and generates a private key from the spec
  119. * </ul>
  120. *
  121. * <p>
  122. *
  123. * @return the resolved Key object
  124. *
  125. * @exception NotSerializableException if the Type/format
  126. * combination is unrecognized, if the algorithm, key format, or
  127. * encoded key bytes are unrecognized/invalid, of if the
  128. * resolution of the key fails for any reason
  129. */
  130. protected Object readResolve() throws ObjectStreamException {
  131. try {
  132. if (type == Type.SECRET && RAW.equals(format)) {
  133. return new SecretKeySpec(encoded, algorithm);
  134. } else if (type == Type.PUBLIC && X509.equals(format)) {
  135. KeyFactory f = KeyFactory.getInstance(algorithm);
  136. return f.generatePublic(new X509EncodedKeySpec(encoded));
  137. } else if (type == Type.PRIVATE && PKCS8.equals(format)) {
  138. KeyFactory f = KeyFactory.getInstance(algorithm);
  139. return f.generatePrivate(new PKCS8EncodedKeySpec(encoded));
  140. } else {
  141. throw new NotSerializableException
  142. ("unrecognized type/format combination: " +
  143. type + "/" + format);
  144. }
  145. } catch (NotSerializableException nse) {
  146. throw nse;
  147. } catch (Exception e) {
  148. NotSerializableException nse = new NotSerializableException
  149. ("java.security.Key: " +
  150. "[" + type + "] " +
  151. "[" + algorithm + "] " +
  152. "[" + format + "]");
  153. nse.initCause(e);
  154. throw nse;
  155. }
  156. }
  157. }