blob: ef3b87639f2222b9f7dbbe1504082349f5ccf759 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
Anthony Scarpinof0b72432013-07-03 15:10:11 -07002 * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
J. Duke319a3b92007-12-01 00:00:00 +00003 * 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
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07007 * published by the Free Software Foundation. Oracle designates this
J. Duke319a3b92007-12-01 00:00:00 +00008 * particular file as subject to the "Classpath" exception as provided
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07009 * by Oracle in the LICENSE file that accompanied this code.
J. Duke319a3b92007-12-01 00:00:00 +000010 *
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 *
Kelly O'Hairfe008ae2010-05-25 15:58:33 -070021 * 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.
J. Duke319a3b92007-12-01 00:00:00 +000024 */
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
Valerie Peng3d60bea2014-07-23 21:50:21 +000035import sun.security.util.DerInputStream;
36import sun.security.util.DerOutputStream;
37import sun.security.util.DerValue;
38import sun.security.util.ECParameters;
39import sun.security.util.ECUtil;
J. Duke319a3b92007-12-01 00:00:00 +000040import sun.security.x509.AlgorithmId;
41import sun.security.pkcs.PKCS8Key;
42
43/**
44 * Key implementation for EC private keys.
45 *
46 * ASN.1 syntax for EC private keys from SEC 1 v1.5 (draft):
47 *
48 * <pre>
49 * EXPLICIT TAGS
50 *
51 * ECPrivateKey ::= SEQUENCE {
52 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
53 * privateKey OCTET STRING,
54 * parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL,
55 * publicKey [1] BIT STRING OPTIONAL
56 * }
57 * </pre>
58 *
59 * We currently ignore the optional parameters and publicKey fields. We
60 * require that the parameters are encoded as part of the AlgorithmIdentifier,
61 * not in the private key structure.
62 *
63 * @since 1.6
64 * @author Andreas Sterbenz
65 */
66public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
67
68 private static final long serialVersionUID = 88695385615075129L;
69
70 private BigInteger s; // private value
71 private ECParameterSpec params;
72
73 /**
Stephen Floresc39030c2013-05-14 18:08:18 +010074 * Construct a key from its encoding. Called by the ECKeyFactory.
J. Duke319a3b92007-12-01 00:00:00 +000075 */
Stephen Floresc39030c2013-05-14 18:08:18 +010076 ECPrivateKeyImpl(byte[] encoded) throws InvalidKeyException {
J. Duke319a3b92007-12-01 00:00:00 +000077 decode(encoded);
78 }
79
80 /**
81 * Construct a key from its components. Used by the
Stephen Floresc39030c2013-05-14 18:08:18 +010082 * KeyFactory.
J. Duke319a3b92007-12-01 00:00:00 +000083 */
Stephen Floresc39030c2013-05-14 18:08:18 +010084 ECPrivateKeyImpl(BigInteger s, ECParameterSpec params)
J. Duke319a3b92007-12-01 00:00:00 +000085 throws InvalidKeyException {
86 this.s = s;
87 this.params = params;
88 // generate the encoding
89 algid = new AlgorithmId
90 (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
91 try {
92 DerOutputStream out = new DerOutputStream();
93 out.putInteger(1); // version 1
Stephen Floresc39030c2013-05-14 18:08:18 +010094 byte[] privBytes = ECUtil.trimZeroes(s.toByteArray());
J. Duke319a3b92007-12-01 00:00:00 +000095 out.putOctetString(privBytes);
96 DerValue val =
97 new DerValue(DerValue.tag_Sequence, out.toByteArray());
98 key = val.toByteArray();
99 } catch (IOException exc) {
100 // should never occur
101 throw new InvalidKeyException(exc);
102 }
103 }
104
105 // see JCA doc
106 public String getAlgorithm() {
107 return "EC";
108 }
109
110 // see JCA doc
111 public BigInteger getS() {
112 return s;
113 }
114
115 // see JCA doc
116 public ECParameterSpec getParams() {
117 return params;
118 }
119
120 /**
121 * Parse the key. Called by PKCS8Key.
122 */
123 protected void parseKeyBits() throws InvalidKeyException {
124 try {
125 DerInputStream in = new DerInputStream(key);
126 DerValue derValue = in.getDerValue();
127 if (derValue.tag != DerValue.tag_Sequence) {
128 throw new IOException("Not a SEQUENCE");
129 }
130 DerInputStream data = derValue.data;
131 int version = data.getInteger();
132 if (version != 1) {
133 throw new IOException("Version must be 1");
134 }
135 byte[] privData = data.getOctetString();
136 s = new BigInteger(1, privData);
137 while (data.available() != 0) {
138 DerValue value = data.getDerValue();
139 if (value.isContextSpecific((byte)0)) {
140 // ignore for now
141 } else if (value.isContextSpecific((byte)1)) {
142 // ignore for now
143 } else {
144 throw new InvalidKeyException("Unexpected value: " + value);
145 }
146 }
147 AlgorithmParameters algParams = this.algid.getParameters();
148 if (algParams == null) {
149 throw new InvalidKeyException("EC domain parameters must be "
150 + "encoded in the algorithm identifier");
151 }
152 params = algParams.getParameterSpec(ECParameterSpec.class);
153 } catch (IOException e) {
154 throw new InvalidKeyException("Invalid EC private key", e);
155 } catch (InvalidParameterSpecException e) {
156 throw new InvalidKeyException("Invalid EC private key", e);
157 }
158 }
J. Duke319a3b92007-12-01 00:00:00 +0000159}