package org.bouncycastle.bcpg;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
/**
* base class for an EC Public Key.
*/
public abstract class ECPublicBCPGKey
extends BCPGObject
implements BCPGKey
{
ASN1ObjectIdentifier oid;
ECPoint point;
/**
* @param in the stream to read the packet from.
*/
protected ECPublicBCPGKey(
BCPGInputStream in)
throws IOException
{
this.oid = ASN1ObjectIdentifier.getInstance(ASN1Primitive.fromByteArray(readBytesOfEncodedLength(in)));
this.point = decodePoint(new MPInteger(in).getValue(), oid);
}
protected ECPublicBCPGKey(
ASN1ObjectIdentifier oid,
ECPoint point)
{
this.point = point;
this.oid = oid;
}
protected ECPublicBCPGKey(
BigInteger encodedPoint,
ASN1ObjectIdentifier oid)
throws IOException
{
this.point = decodePoint(encodedPoint, oid);
this.oid = oid;
}
/**
* return "PGP"
*
* @see org.bouncycastle.bcpg.BCPGKey#getFormat()
*/
public String getFormat()
{
return "PGP";
}
/**
* return the standard PGP encoding of the key.
*
* @see org.bouncycastle.bcpg.BCPGKey#getEncoded()
*/
public byte[] getEncoded()
{
try
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
BCPGOutputStream pgpOut = new BCPGOutputStream(bOut);
pgpOut.writeObject(this);
return bOut.toByteArray();
}
catch (IOException e)
{
return null;
}
}
public void encode(
BCPGOutputStream out)
throws IOException
{
byte[] oid = this.oid.getEncoded();
out.write(oid, 1, oid.length - 1);
MPInteger point = new MPInteger(new BigInteger(1, this.point.getEncoded()));
out.writeObject(point);
}
/**
* @return point
*/
public ECPoint getPoint()
{
return point;
}
/**
* @return oid
*/
public ASN1ObjectIdentifier getCurveOID()
{
return oid;
}
protected static byte[] readBytesOfEncodedLength(
BCPGInputStream in)
throws IOException
{
int length = in.read();
if (length == 0 || length == 0xFF)
{
throw new IOException("future extensions not yet implemented.");
}
byte[] buffer = new byte[length + 2];
in.readFully(buffer, 2, buffer.length - 2);
buffer[0] = (byte)0x06;
buffer[1] = (byte)length;
return buffer;
}
private static ECPoint decodePoint(
BigInteger encodedPoint,
ASN1ObjectIdentifier oid)
throws IOException
{
X9ECParameters curve = ECNamedCurveTable.getByOID(oid);
if (curve == null)
{
throw new IOException(oid.getId() + " does not match any known curve.");
}
if (!(curve.getCurve() instanceof ECCurve.Fp))
{
throw new IOException("Only FPCurves are supported.");
}
return curve.getCurve().decodePoint(encodedPoint.toByteArray());
}
}