001: package org.bouncycastle.asn1.x9;
002:
003: import java.math.BigInteger;
004:
005: import org.bouncycastle.asn1.ASN1Encodable;
006: import org.bouncycastle.asn1.ASN1EncodableVector;
007: import org.bouncycastle.asn1.ASN1OctetString;
008: import org.bouncycastle.asn1.ASN1Sequence;
009: import org.bouncycastle.asn1.DERBitString;
010: import org.bouncycastle.asn1.DERInteger;
011: import org.bouncycastle.asn1.DERObject;
012: import org.bouncycastle.asn1.DERObjectIdentifier;
013: import org.bouncycastle.asn1.DERSequence;
014: import org.bouncycastle.math.ec.ECCurve;
015:
016: /**
017: * ASN.1 def for Elliptic-Curve Curve structure. See
018: * X9.62, for further details.
019: */
020: public class X9Curve extends ASN1Encodable implements
021: X9ObjectIdentifiers {
022: private ECCurve curve;
023: private byte[] seed;
024: private DERObjectIdentifier fieldIdentifier = null;
025:
026: public X9Curve(ECCurve curve) {
027: this .curve = curve;
028: this .seed = null;
029: setFieldIdentifier();
030: }
031:
032: public X9Curve(ECCurve curve, byte[] seed) {
033: this .curve = curve;
034: this .seed = seed;
035: setFieldIdentifier();
036: }
037:
038: public X9Curve(X9FieldID fieldID, ASN1Sequence seq) {
039: fieldIdentifier = fieldID.getIdentifier();
040: if (fieldIdentifier.equals(prime_field)) {
041: BigInteger p = ((DERInteger) fieldID.getParameters())
042: .getValue();
043: X9FieldElement x9A = new X9FieldElement(p,
044: (ASN1OctetString) seq.getObjectAt(0));
045: X9FieldElement x9B = new X9FieldElement(p,
046: (ASN1OctetString) seq.getObjectAt(1));
047: curve = new ECCurve.Fp(p, x9A.getValue().toBigInteger(),
048: x9B.getValue().toBigInteger());
049: } else {
050: if (fieldIdentifier.equals(characteristic_two_field)) {
051: // Characteristic two field
052: DERSequence parameters = (DERSequence) fieldID
053: .getParameters();
054: int m = ((DERInteger) parameters.getObjectAt(0))
055: .getValue().intValue();
056: DERObjectIdentifier representation = (DERObjectIdentifier) parameters
057: .getObjectAt(1);
058:
059: int k1 = 0;
060: int k2 = 0;
061: int k3 = 0;
062: if (representation.equals(tpBasis)) {
063: // Trinomial basis representation
064: k1 = ((DERInteger) parameters.getObjectAt(2))
065: .getValue().intValue();
066: } else {
067: // Pentanomial basis representation
068: DERSequence pentanomial = (DERSequence) parameters
069: .getObjectAt(2);
070: k1 = ((DERInteger) pentanomial.getObjectAt(0))
071: .getValue().intValue();
072: k2 = ((DERInteger) pentanomial.getObjectAt(1))
073: .getValue().intValue();
074: k3 = ((DERInteger) pentanomial.getObjectAt(2))
075: .getValue().intValue();
076: }
077: X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3,
078: (ASN1OctetString) seq.getObjectAt(0));
079: X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3,
080: (ASN1OctetString) seq.getObjectAt(1));
081: // TODO Is it possible to get the order (n) and cofactor(h) too?
082: curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue()
083: .toBigInteger(), x9B.getValue().toBigInteger());
084: }
085: }
086:
087: if (seq.size() == 3) {
088: seed = ((DERBitString) seq.getObjectAt(2)).getBytes();
089: }
090: }
091:
092: private void setFieldIdentifier() {
093: if (curve instanceof ECCurve.Fp) {
094: fieldIdentifier = prime_field;
095: } else if (curve instanceof ECCurve.F2m) {
096: fieldIdentifier = characteristic_two_field;
097: } else {
098: throw new IllegalArgumentException(
099: "This type of ECCurve is not " + "implemented");
100: }
101: }
102:
103: public ECCurve getCurve() {
104: return curve;
105: }
106:
107: public byte[] getSeed() {
108: return seed;
109: }
110:
111: /**
112: * Produce an object suitable for an ASN1OutputStream.
113: * <pre>
114: * Curve ::= SEQUENCE {
115: * a FieldElement,
116: * b FieldElement,
117: * seed BIT STRING OPTIONAL
118: * }
119: * </pre>
120: */
121: public DERObject toASN1Object() {
122: ASN1EncodableVector v = new ASN1EncodableVector();
123:
124: if (fieldIdentifier.equals(prime_field)) {
125: v.add(new X9FieldElement(curve.getA()).getDERObject());
126: v.add(new X9FieldElement(curve.getB()).getDERObject());
127: } else if (fieldIdentifier.equals(characteristic_two_field)) {
128: v.add(new X9FieldElement(curve.getA()).getDERObject());
129: v.add(new X9FieldElement(curve.getB()).getDERObject());
130: }
131:
132: if (seed != null) {
133: v.add(new DERBitString(seed));
134: }
135:
136: return new DERSequence(v);
137: }
138: }
|