blob: 1c1058908f77d446b3a8114106ba0242f7f6a079 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.ec;
27
28import java.io.IOException;
29import java.math.BigInteger;
30
31import java.security.*;
32import java.security.interfaces.*;
33import java.security.spec.*;
34
35import sun.security.util.*;
36import sun.security.x509.AlgorithmId;
37import sun.security.pkcs.PKCS8Key;
38
39/**
40 * Key implementation for EC private keys.
41 *
42 * ASN.1 syntax for EC private keys from SEC 1 v1.5 (draft):
43 *
44 * <pre>
45 * EXPLICIT TAGS
46 *
47 * ECPrivateKey ::= SEQUENCE {
48 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
49 * privateKey OCTET STRING,
50 * parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL,
51 * publicKey [1] BIT STRING OPTIONAL
52 * }
53 * </pre>
54 *
55 * We currently ignore the optional parameters and publicKey fields. We
56 * require that the parameters are encoded as part of the AlgorithmIdentifier,
57 * not in the private key structure.
58 *
59 * @since 1.6
60 * @author Andreas Sterbenz
61 */
62public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
63
64 private static final long serialVersionUID = 88695385615075129L;
65
66 private BigInteger s; // private value
67 private ECParameterSpec params;
68
69 /**
70 * Construct a key from its encoding. Called by the ECKeyFactory and
71 * the SunPKCS11 code.
72 */
73 public ECPrivateKeyImpl(byte[] encoded) throws InvalidKeyException {
74 decode(encoded);
75 }
76
77 /**
78 * Construct a key from its components. Used by the
79 * KeyFactory and the SunPKCS11 code.
80 */
81 public ECPrivateKeyImpl(BigInteger s, ECParameterSpec params)
82 throws InvalidKeyException {
83 this.s = s;
84 this.params = params;
85 // generate the encoding
86 algid = new AlgorithmId
87 (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
88 try {
89 DerOutputStream out = new DerOutputStream();
90 out.putInteger(1); // version 1
91 byte[] privBytes = ECParameters.trimZeroes(s.toByteArray());
92 out.putOctetString(privBytes);
93 DerValue val =
94 new DerValue(DerValue.tag_Sequence, out.toByteArray());
95 key = val.toByteArray();
96 } catch (IOException exc) {
97 // should never occur
98 throw new InvalidKeyException(exc);
99 }
100 }
101
102 // see JCA doc
103 public String getAlgorithm() {
104 return "EC";
105 }
106
107 // see JCA doc
108 public BigInteger getS() {
109 return s;
110 }
111
112 // see JCA doc
113 public ECParameterSpec getParams() {
114 return params;
115 }
116
117 /**
118 * Parse the key. Called by PKCS8Key.
119 */
120 protected void parseKeyBits() throws InvalidKeyException {
121 try {
122 DerInputStream in = new DerInputStream(key);
123 DerValue derValue = in.getDerValue();
124 if (derValue.tag != DerValue.tag_Sequence) {
125 throw new IOException("Not a SEQUENCE");
126 }
127 DerInputStream data = derValue.data;
128 int version = data.getInteger();
129 if (version != 1) {
130 throw new IOException("Version must be 1");
131 }
132 byte[] privData = data.getOctetString();
133 s = new BigInteger(1, privData);
134 while (data.available() != 0) {
135 DerValue value = data.getDerValue();
136 if (value.isContextSpecific((byte)0)) {
137 // ignore for now
138 } else if (value.isContextSpecific((byte)1)) {
139 // ignore for now
140 } else {
141 throw new InvalidKeyException("Unexpected value: " + value);
142 }
143 }
144 AlgorithmParameters algParams = this.algid.getParameters();
145 if (algParams == null) {
146 throw new InvalidKeyException("EC domain parameters must be "
147 + "encoded in the algorithm identifier");
148 }
149 params = algParams.getParameterSpec(ECParameterSpec.class);
150 } catch (IOException e) {
151 throw new InvalidKeyException("Invalid EC private key", e);
152 } catch (InvalidParameterSpecException e) {
153 throw new InvalidKeyException("Invalid EC private key", e);
154 }
155 }
156
157 // return a string representation of this key for debugging
158 public String toString() {
159 return "Sun EC private key, " + params.getCurve().getField().getFieldSize()
160 + " bits\n private value: "
161 + s + "\n parameters: " + params;
162 }
163
164}