using System;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1.X9{
/**
* ASN.1 def for Elliptic-Curve Curve structure. See
* X9.62, for further details.
*/
public class X9Curve
: Asn1Encodable
{
private readonly ECCurve curve;
private readonly byte[] seed;
private readonly DerObjectIdentifier fieldIdentifier;
public X9Curve(
ECCurve curve)
: this(curve, null)
{
this.curve = curve;
}
public X9Curve(
ECCurve curve,
byte[] seed)
{
if (curve == null)
throw new ArgumentNullException("curve");
this.curve = curve;
this.seed = Arrays.Clone(seed);
if (curve is FpCurve)
{
this.fieldIdentifier = X9ObjectIdentifiers.PrimeField;
}
else if (curve is F2mCurve)
{
this.fieldIdentifier = X9ObjectIdentifiers.CharacteristicTwoField;
}
else
{
throw new ArgumentException("This type of ECCurve is not implemented");
}
}
public X9Curve(
X9FieldID fieldID,
Asn1Sequence seq)
{
if (fieldID == null)
throw new ArgumentNullException("fieldID");
if (seq == null)
throw new ArgumentNullException("seq");
this.fieldIdentifier = fieldID.Identifier;
if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField))
{
BigInteger q = ((DerInteger) fieldID.Parameters).Value;
X9FieldElement x9A = new X9FieldElement(q, (Asn1OctetString) seq[0]);
X9FieldElement x9B = new X9FieldElement(q, (Asn1OctetString) seq[1]);
curve = new FpCurve(q, x9A.Value.ToBigInteger(), x9B.Value.ToBigInteger());
}
else
{
if (fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField))
{
// Characteristic two field
DerSequence parameters = (DerSequence)fieldID.Parameters;
int m = ((DerInteger)parameters[0]).Value.IntValue;
DerObjectIdentifier representation
= (DerObjectIdentifier)parameters[1];
int k1 = 0;
int k2 = 0;
int k3 = 0;
if (representation.Equals(X9ObjectIdentifiers.TPBasis))
{
// Trinomial basis representation
k1 = ((DerInteger)parameters[2]).Value.IntValue;
}
else
{
// Pentanomial basis representation
DerSequence pentanomial = (DerSequence) parameters[2];
k1 = ((DerInteger) pentanomial[0]).Value.IntValue;
k2 = ((DerInteger) pentanomial[1]).Value.IntValue;
k3 = ((DerInteger) pentanomial[2]).Value.IntValue;
}
X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[0]);
X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[1]);
// TODO Is it possible to get the order (n) and cofactor(h) too?
curve = new F2mCurve(m, k1, k2, k3, x9A.Value.ToBigInteger(), x9B.Value.ToBigInteger());
}
}
if (seq.Count == 3)
{
seed = ((DerBitString) seq[2]).GetBytes();
}
}
public ECCurve Curve
{
get { return curve; }
}
public byte[] GetSeed()
{
return Arrays.Clone(seed);
}
/**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* Curve ::= Sequence {
* a FieldElement,
* b FieldElement,
* seed BIT STRING OPTIONAL
* }
* </pre>
*/
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector();
if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField)
|| fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField))
{
v.Add(new X9FieldElement(curve.A).ToAsn1Object());
v.Add(new X9FieldElement(curve.B).ToAsn1Object());
}
if (seed != null)
{
v.Add(new DerBitString(seed));
}
return new DerSequence(v);
}
}
}
|