001: package org.bouncycastle.jce.provider;
002:
003: import org.bouncycastle.asn1.ASN1Sequence;
004: import org.bouncycastle.asn1.DEREncodable;
005: import org.bouncycastle.asn1.DERInteger;
006: import org.bouncycastle.asn1.DERNull;
007: import org.bouncycastle.asn1.DERObject;
008: import org.bouncycastle.asn1.DERObjectIdentifier;
009: import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
010: import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
011: import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
012: import org.bouncycastle.asn1.sec.ECPrivateKeyStructure;
013: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
014: import org.bouncycastle.asn1.x9.X962Parameters;
015: import org.bouncycastle.asn1.x9.X9ECParameters;
016: import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
017: import org.bouncycastle.crypto.params.ECDomainParameters;
018: import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
019: import org.bouncycastle.jce.interfaces.ECPointEncoder;
020: import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
021: import org.bouncycastle.jce.spec.ECNamedCurveSpec;
022: import org.bouncycastle.math.ec.ECCurve;
023:
024: import java.math.BigInteger;
025: import java.security.interfaces.ECPrivateKey;
026: import java.security.spec.ECParameterSpec;
027: import java.security.spec.ECPoint;
028: import java.security.spec.ECPrivateKeySpec;
029: import java.security.spec.EllipticCurve;
030: import java.util.Enumeration;
031:
032: public class JCEECPrivateKey implements ECPrivateKey,
033: org.bouncycastle.jce.interfaces.ECPrivateKey,
034: PKCS12BagAttributeCarrier, ECPointEncoder {
035: private String algorithm = "EC";
036: private BigInteger d;
037: private ECParameterSpec ecSpec;
038: private boolean withCompression;
039:
040: private PKCS12BagAttributeCarrier attrCarrier = new PKCS12BagAttributeCarrierImpl();
041:
042: protected JCEECPrivateKey() {
043: }
044:
045: JCEECPrivateKey(ECPrivateKey key) {
046: this .d = key.getS();
047: this .algorithm = key.getAlgorithm();
048: this .ecSpec = key.getParams();
049: }
050:
051: JCEECPrivateKey(String algorithm,
052: org.bouncycastle.jce.spec.ECPrivateKeySpec spec) {
053: this .algorithm = algorithm;
054: this .d = spec.getD();
055:
056: if (spec.getParams() != null) // can be null if implictlyCa
057: {
058: ECCurve curve = spec.getParams().getCurve();
059: EllipticCurve ellipticCurve;
060:
061: ellipticCurve = EC5Util.convertCurve(curve, spec
062: .getParams().getSeed());
063:
064: this .ecSpec = EC5Util.convertSpec(ellipticCurve, spec
065: .getParams());
066: } else {
067: this .ecSpec = null;
068: }
069: }
070:
071: JCEECPrivateKey(String algorithm, ECPrivateKeySpec spec) {
072: this .algorithm = algorithm;
073: this .d = spec.getS();
074: this .ecSpec = spec.getParams();
075: }
076:
077: JCEECPrivateKey(String algorithm, JCEECPrivateKey key) {
078: this .algorithm = algorithm;
079: this .d = key.d;
080: this .ecSpec = key.ecSpec;
081: this .withCompression = key.withCompression;
082: this .attrCarrier = key.attrCarrier;
083: }
084:
085: JCEECPrivateKey(String algorithm, ECPrivateKeyParameters params,
086: ECParameterSpec spec) {
087: ECDomainParameters dp = params.getParameters();
088:
089: this .algorithm = algorithm;
090: this .d = params.getD();
091:
092: if (spec == null) {
093: EllipticCurve ellipticCurve = EC5Util.convertCurve(dp
094: .getCurve(), dp.getSeed());
095:
096: this .ecSpec = new ECParameterSpec(ellipticCurve,
097: new ECPoint(dp.getG().getX().toBigInteger(), dp
098: .getG().getY().toBigInteger()), dp.getN(),
099: dp.getH().intValue());
100: } else {
101: this .ecSpec = spec;
102: }
103: }
104:
105: JCEECPrivateKey(String algorithm, ECPrivateKeyParameters params,
106: org.bouncycastle.jce.spec.ECParameterSpec spec) {
107: ECDomainParameters dp = params.getParameters();
108:
109: this .algorithm = algorithm;
110: this .d = params.getD();
111:
112: if (spec == null) {
113: EllipticCurve ellipticCurve = EC5Util.convertCurve(dp
114: .getCurve(), dp.getSeed());
115:
116: this .ecSpec = new ECParameterSpec(ellipticCurve,
117: new ECPoint(dp.getG().getX().toBigInteger(), dp
118: .getG().getY().toBigInteger()), dp.getN(),
119: dp.getH().intValue());
120: } else {
121: EllipticCurve ellipticCurve = EC5Util.convertCurve(spec
122: .getCurve(), spec.getSeed());
123:
124: this .ecSpec = new ECParameterSpec(ellipticCurve,
125: new ECPoint(spec.getG().getX().toBigInteger(), spec
126: .getG().getY().toBigInteger()),
127: spec.getN(), spec.getH().intValue());
128: }
129: }
130:
131: JCEECPrivateKey(String algorithm, ECPrivateKeyParameters params) {
132: this .algorithm = algorithm;
133: this .d = params.getD();
134: this .ecSpec = null;
135: }
136:
137: JCEECPrivateKey(PrivateKeyInfo info) {
138: X962Parameters params = new X962Parameters((DERObject) info
139: .getAlgorithmId().getParameters());
140:
141: if (params.isNamedCurve()) {
142: DERObjectIdentifier oid = (DERObjectIdentifier) params
143: .getParameters();
144: X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid);
145:
146: if (ecP == null) // GOST Curve
147: {
148: ECDomainParameters gParam = ECGOST3410NamedCurves
149: .getByOID(oid);
150: EllipticCurve ellipticCurve = EC5Util.convertCurve(
151: gParam.getCurve(), gParam.getSeed());
152:
153: ecSpec = new ECNamedCurveSpec(ECGOST3410NamedCurves
154: .getName(oid), ellipticCurve, new ECPoint(
155: gParam.getG().getX().toBigInteger(), gParam
156: .getG().getY().toBigInteger()), gParam
157: .getN(), gParam.getH());
158: } else {
159: EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP
160: .getCurve(), ecP.getSeed());
161:
162: ecSpec = new ECNamedCurveSpec(ECUtil.getCurveName(oid),
163: ellipticCurve, new ECPoint(ecP.getG().getX()
164: .toBigInteger(), ecP.getG().getY()
165: .toBigInteger()), ecP.getN(), ecP
166: .getH());
167: }
168: } else if (params.isImplicitlyCA()) {
169: ecSpec = null;
170: } else {
171: X9ECParameters ecP = new X9ECParameters(
172: (ASN1Sequence) params.getParameters());
173: EllipticCurve ellipticCurve = EC5Util.convertCurve(ecP
174: .getCurve(), ecP.getSeed());
175:
176: this .ecSpec = new ECParameterSpec(ellipticCurve,
177: new ECPoint(ecP.getG().getX().toBigInteger(), ecP
178: .getG().getY().toBigInteger()), ecP.getN(),
179: ecP.getH().intValue());
180: }
181:
182: if (info.getPrivateKey() instanceof DERInteger) {
183: DERInteger derD = (DERInteger) info.getPrivateKey();
184:
185: this .d = derD.getValue();
186: } else {
187: ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
188: (ASN1Sequence) info.getPrivateKey());
189:
190: this .d = ec.getKey();
191: }
192: }
193:
194: public String getAlgorithm() {
195: return algorithm;
196: }
197:
198: /**
199: * return the encoding format we produce in getEncoded().
200: *
201: * @return the string "PKCS#8"
202: */
203: public String getFormat() {
204: return "PKCS#8";
205: }
206:
207: /**
208: * Return a PKCS8 representation of the key. The sequence returned
209: * represents a full PrivateKeyInfo object.
210: *
211: * @return a PKCS8 representation of the key.
212: */
213: public byte[] getEncoded() {
214: X962Parameters params;
215:
216: if (ecSpec instanceof ECNamedCurveSpec) {
217: DERObjectIdentifier curveOid = ECUtil
218: .getNamedCurveOid(((ECNamedCurveSpec) ecSpec)
219: .getName());
220:
221: params = new X962Parameters(curveOid);
222: } else if (ecSpec == null) {
223: params = new X962Parameters(DERNull.INSTANCE);
224: } else {
225: ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve());
226:
227: X9ECParameters ecP = new X9ECParameters(curve, EC5Util
228: .convertPoint(curve, ecSpec.getGenerator(),
229: withCompression), ecSpec.getOrder(),
230: BigInteger.valueOf(ecSpec.getCofactor()), ecSpec
231: .getCurve().getSeed());
232:
233: params = new X962Parameters(ecP);
234: }
235:
236: PrivateKeyInfo info;
237:
238: if (algorithm.equals("ECGOST3410")) {
239: info = new PrivateKeyInfo(new AlgorithmIdentifier(
240: CryptoProObjectIdentifiers.gostR3410_2001, params
241: .getDERObject()),
242: new ECPrivateKeyStructure(this .getS())
243: .getDERObject());
244: } else {
245: info = new PrivateKeyInfo(new AlgorithmIdentifier(
246: X9ObjectIdentifiers.id_ecPublicKey, params
247: .getDERObject()),
248: new ECPrivateKeyStructure(this .getS())
249: .getDERObject());
250: }
251:
252: return info.getDEREncoded();
253: }
254:
255: public ECParameterSpec getParams() {
256: return ecSpec;
257: }
258:
259: public org.bouncycastle.jce.spec.ECParameterSpec getParameters() {
260: if (ecSpec == null) {
261: return null;
262: }
263:
264: return EC5Util.convertSpec(ecSpec, withCompression);
265: }
266:
267: org.bouncycastle.jce.spec.ECParameterSpec engineGetSpec() {
268: if (ecSpec != null) {
269: return EC5Util.convertSpec(ecSpec, withCompression);
270: }
271:
272: return ProviderUtil.getEcImplicitlyCa();
273: }
274:
275: public BigInteger getS() {
276: return d;
277: }
278:
279: public BigInteger getD() {
280: return d;
281: }
282:
283: public void setBagAttribute(DERObjectIdentifier oid,
284: DEREncodable attribute) {
285: attrCarrier.setBagAttribute(oid, attribute);
286: }
287:
288: public DEREncodable getBagAttribute(DERObjectIdentifier oid) {
289: return attrCarrier.getBagAttribute(oid);
290: }
291:
292: public Enumeration getBagAttributeKeys() {
293: return attrCarrier.getBagAttributeKeys();
294: }
295:
296: public void setPointFormat(String style) {
297: withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style));
298: }
299:
300: public boolean equals(Object o) {
301: if (!(o instanceof JCEECPrivateKey)) {
302: return false;
303: }
304:
305: JCEECPrivateKey other = (JCEECPrivateKey) o;
306:
307: return getD().equals(other.getD())
308: && (engineGetSpec().equals(other.engineGetSpec()));
309: }
310:
311: public int hashCode() {
312: return getD().hashCode() ^ engineGetSpec().hashCode();
313: }
314: }
|