001package org.apache.commons.ssl.org.bouncycastle.asn1.ua;
002
003import java.math.BigInteger;
004
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
012import org.apache.commons.ssl.org.bouncycastle.asn1.DEROctetString;
013import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
014import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
015import org.bouncycastle.crypto.params.ECDomainParameters;
016import org.bouncycastle.math.ec.ECAlgorithms;
017import org.bouncycastle.math.ec.ECCurve;
018import org.bouncycastle.math.field.PolynomialExtensionField;
019import org.bouncycastle.util.Arrays;
020
021public class DSTU4145ECBinary
022    extends ASN1Object
023{
024    BigInteger version = BigInteger.valueOf(0);
025
026    DSTU4145BinaryField f;
027    ASN1Integer a;
028    ASN1OctetString b;
029    ASN1Integer n;
030    ASN1OctetString bp;
031
032    public DSTU4145ECBinary(ECDomainParameters params)
033    {
034        ECCurve curve = params.getCurve();
035        if (!ECAlgorithms.isF2mCurve(curve))
036        {
037            throw new IllegalArgumentException("only binary domain is possible");
038        }
039
040        // We always use big-endian in parameter encoding
041
042        PolynomialExtensionField field = (PolynomialExtensionField)curve.getField();
043        int[] exponents = field.getMinimalPolynomial().getExponentsPresent();
044        if (exponents.length == 3)
045        {
046            f = new DSTU4145BinaryField(exponents[2], exponents[1]);
047        }
048        else if (exponents.length == 5)
049        {
050            f = new DSTU4145BinaryField(exponents[4], exponents[1], exponents[2], exponents[3]);
051        }
052
053        a = new ASN1Integer(curve.getA().toBigInteger());
054        b = new DEROctetString(curve.getB().getEncoded());
055        n = new ASN1Integer(params.getN());
056        bp = new DEROctetString(DSTU4145PointEncoder.encodePoint(params.getG()));
057    }
058
059    private DSTU4145ECBinary(ASN1Sequence seq)
060    {
061        int index = 0;
062
063        if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
064        {
065            ASN1TaggedObject taggedVersion = (ASN1TaggedObject)seq.getObjectAt(index);
066            if (taggedVersion.isExplicit() && 0 == taggedVersion.getTagNo())
067            {
068                version = ASN1Integer.getInstance(taggedVersion.getLoadedObject()).getValue();
069                index++;
070            }
071            else
072            {
073                throw new IllegalArgumentException("object parse error");
074            }
075        }
076        f = DSTU4145BinaryField.getInstance(seq.getObjectAt(index));
077        index++;
078        a = ASN1Integer.getInstance(seq.getObjectAt(index));
079        index++;
080        b = ASN1OctetString.getInstance(seq.getObjectAt(index));
081        index++;
082        n = ASN1Integer.getInstance(seq.getObjectAt(index));
083        index++;
084        bp = ASN1OctetString.getInstance(seq.getObjectAt(index));
085    }
086
087    public static DSTU4145ECBinary getInstance(Object obj)
088    {
089        if (obj instanceof DSTU4145ECBinary)
090        {
091            return (DSTU4145ECBinary)obj;
092        }
093
094        if (obj != null)
095        {
096            return new DSTU4145ECBinary(ASN1Sequence.getInstance(obj));
097        }
098
099        return null;
100    }
101
102    public DSTU4145BinaryField getField()
103    {
104        return f;
105    }
106
107    public BigInteger getA()
108    {
109        return a.getValue();
110    }
111
112    public byte[] getB()
113    {
114        return Arrays.clone(b.getOctets());
115    }
116
117    public BigInteger getN()
118    {
119        return n.getValue();
120    }
121
122    public byte[] getG()
123    {
124        return Arrays.clone(bp.getOctets());
125    }
126
127    /**
128     * ECBinary  ::= SEQUENCE {
129     * version          [0] EXPLICIT INTEGER    DEFAULT 0,
130     * f     BinaryField,
131     * a    INTEGER (0..1),
132     * b    OCTET STRING,
133     * n    INTEGER,
134     * bp    OCTET STRING}
135     */
136    public ASN1Primitive toASN1Primitive()
137    {
138
139        ASN1EncodableVector v = new ASN1EncodableVector();
140
141        if (0 != version.compareTo(BigInteger.valueOf(0)))
142        {
143            v.add(new DERTaggedObject(true, 0, new ASN1Integer(version)));
144        }
145        v.add(f);
146        v.add(a);
147        v.add(b);
148        v.add(n);
149        v.add(bp);
150
151        return new DERSequence(v);
152    }
153
154}