30 |
30 |
31 import java.security.*; |
31 import java.security.*; |
32 import java.security.interfaces.*; |
32 import java.security.interfaces.*; |
33 import java.security.spec.*; |
33 import java.security.spec.*; |
34 |
34 |
35 import sun.security.util.DerInputStream; |
35 import sun.security.util.*; |
36 import sun.security.util.DerOutputStream; |
|
37 import sun.security.util.DerValue; |
|
38 import sun.security.util.ECParameters; |
|
39 import sun.security.util.ECUtil; |
|
40 import sun.security.x509.AlgorithmId; |
36 import sun.security.x509.AlgorithmId; |
41 import sun.security.pkcs.PKCS8Key; |
37 import sun.security.pkcs.PKCS8Key; |
42 |
38 |
43 /** |
39 /** |
44 * Key implementation for EC private keys. |
40 * Key implementation for EC private keys. |
83 */ |
80 */ |
84 ECPrivateKeyImpl(BigInteger s, ECParameterSpec params) |
81 ECPrivateKeyImpl(BigInteger s, ECParameterSpec params) |
85 throws InvalidKeyException { |
82 throws InvalidKeyException { |
86 this.s = s; |
83 this.s = s; |
87 this.params = params; |
84 this.params = params; |
88 // generate the encoding |
85 makeEncoding(s); |
|
86 |
|
87 } |
|
88 |
|
89 ECPrivateKeyImpl(byte[] s, ECParameterSpec params) |
|
90 throws InvalidKeyException { |
|
91 this.arrayS = s.clone(); |
|
92 this.params = params; |
|
93 makeEncoding(s); |
|
94 } |
|
95 |
|
96 private void makeEncoding(byte[] s) throws InvalidKeyException { |
89 algid = new AlgorithmId |
97 algid = new AlgorithmId |
90 (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params)); |
98 (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params)); |
91 try { |
99 try { |
92 DerOutputStream out = new DerOutputStream(); |
100 DerOutputStream out = new DerOutputStream(); |
93 out.putInteger(1); // version 1 |
101 out.putInteger(1); // version 1 |
94 byte[] privBytes = ECUtil.trimZeroes(s.toByteArray()); |
102 byte[] privBytes = s.clone(); |
|
103 ArrayUtil.reverse(privBytes); |
95 out.putOctetString(privBytes); |
104 out.putOctetString(privBytes); |
96 DerValue val = |
105 DerValue val = |
97 new DerValue(DerValue.tag_Sequence, out.toByteArray()); |
106 new DerValue(DerValue.tag_Sequence, out.toByteArray()); |
98 key = val.toByteArray(); |
107 key = val.toByteArray(); |
99 } catch (IOException exc) { |
108 } catch (IOException exc) { |
100 // should never occur |
109 // should never occur |
101 throw new InvalidKeyException(exc); |
110 throw new InvalidKeyException(exc); |
102 } |
111 } |
103 } |
112 } |
104 |
113 |
|
114 private void makeEncoding(BigInteger s) throws InvalidKeyException { |
|
115 algid = new AlgorithmId |
|
116 (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params)); |
|
117 try { |
|
118 byte[] sArr = s.toByteArray(); |
|
119 // convert to fixed-length array |
|
120 int numOctets = (params.getOrder().bitLength() + 7) / 8; |
|
121 byte[] sOctets = new byte[numOctets]; |
|
122 int inPos = Math.max(sArr.length - sOctets.length, 0); |
|
123 int outPos = Math.max(sOctets.length - sArr.length, 0); |
|
124 int length = Math.min(sArr.length, sOctets.length); |
|
125 System.arraycopy(sArr, inPos, sOctets, outPos, length); |
|
126 |
|
127 DerOutputStream out = new DerOutputStream(); |
|
128 out.putInteger(1); // version 1 |
|
129 out.putOctetString(sOctets); |
|
130 DerValue val = |
|
131 new DerValue(DerValue.tag_Sequence, out.toByteArray()); |
|
132 key = val.toByteArray(); |
|
133 } catch (IOException exc) { |
|
134 // should never occur |
|
135 throw new InvalidKeyException(exc); |
|
136 } |
|
137 } |
|
138 |
105 // see JCA doc |
139 // see JCA doc |
106 public String getAlgorithm() { |
140 public String getAlgorithm() { |
107 return "EC"; |
141 return "EC"; |
108 } |
142 } |
109 |
143 |
110 // see JCA doc |
144 // see JCA doc |
111 public BigInteger getS() { |
145 public BigInteger getS() { |
|
146 if (s == null) { |
|
147 byte[] arrCopy = arrayS.clone(); |
|
148 ArrayUtil.reverse(arrCopy); |
|
149 s = new BigInteger(1, arrCopy); |
|
150 } |
112 return s; |
151 return s; |
|
152 } |
|
153 |
|
154 public byte[] getArrayS() { |
|
155 if (arrayS == null) { |
|
156 byte[] arr = getS().toByteArray(); |
|
157 ArrayUtil.reverse(arr); |
|
158 int byteLength = (params.getOrder().bitLength() + 7) / 8; |
|
159 arrayS = new byte[byteLength]; |
|
160 int length = Math.min(byteLength, arr.length); |
|
161 System.arraycopy(arr, 0, arrayS, 0, length); |
|
162 } |
|
163 return arrayS.clone(); |
113 } |
164 } |
114 |
165 |
115 // see JCA doc |
166 // see JCA doc |
116 public ECParameterSpec getParams() { |
167 public ECParameterSpec getParams() { |
117 return params; |
168 return params; |
131 int version = data.getInteger(); |
182 int version = data.getInteger(); |
132 if (version != 1) { |
183 if (version != 1) { |
133 throw new IOException("Version must be 1"); |
184 throw new IOException("Version must be 1"); |
134 } |
185 } |
135 byte[] privData = data.getOctetString(); |
186 byte[] privData = data.getOctetString(); |
136 s = new BigInteger(1, privData); |
187 ArrayUtil.reverse(privData); |
|
188 arrayS = privData; |
137 while (data.available() != 0) { |
189 while (data.available() != 0) { |
138 DerValue value = data.getDerValue(); |
190 DerValue value = data.getDerValue(); |
139 if (value.isContextSpecific((byte)0)) { |
191 if (value.isContextSpecific((byte) 0)) { |
140 // ignore for now |
192 // ignore for now |
141 } else if (value.isContextSpecific((byte)1)) { |
193 } else if (value.isContextSpecific((byte) 1)) { |
142 // ignore for now |
194 // ignore for now |
143 } else { |
195 } else { |
144 throw new InvalidKeyException("Unexpected value: " + value); |
196 throw new InvalidKeyException("Unexpected value: " + value); |
145 } |
197 } |
146 } |
198 } |