14c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompackage org.bouncycastle.jcajce.provider.asymmetric.dsa;
24c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
34c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.IOException;
44c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.ObjectInputStream;
54c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.ObjectOutputStream;
64c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.math.BigInteger;
74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.interfaces.DSAParams;
84c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.interfaces.DSAPublicKey;
94c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.spec.DSAParameterSpec;
104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.security.spec.DSAPublicKeySpec;
114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Encodable;
134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.ASN1Integer;
144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.DERNull;
154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.x509.AlgorithmIdentifier;
164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.x509.DSAParameter;
174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.crypto.params.DSAPublicKeyParameters;
204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompublic class BCDSAPublicKey
234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    implements DSAPublicKey
244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom{
254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private static final long serialVersionUID = 1752452449903495175L;
264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private BigInteger      y;
284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private transient DSAParams       dsaSpec;
294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    BCDSAPublicKey(
314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        DSAPublicKeySpec spec)
324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.y = spec.getY();
344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.dsaSpec = new DSAParameterSpec(spec.getP(), spec.getQ(), spec.getG());
354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    BCDSAPublicKey(
384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        DSAPublicKey key)
394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.y = key.getY();
414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.dsaSpec = key.getParams();
424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    BCDSAPublicKey(
454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        DSAPublicKeyParameters params)
464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.y = params.getY();
484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.dsaSpec = new DSAParameterSpec(params.getParameters().getP(), params.getParameters().getQ(), params.getParameters().getG());
494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    BCDSAPublicKey(
524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        BigInteger y,
534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        DSAParameterSpec dsaSpec)
544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.y = y;
564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.dsaSpec = dsaSpec;
574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public BCDSAPublicKey(
604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        SubjectPublicKeyInfo info)
614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1Integer              derY;
644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        try
664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            derY = (ASN1Integer)info.parsePublicKey();
684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        catch (IOException e)
704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            throw new IllegalArgumentException("invalid info structure in DSA public key");
724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.y = derY.getValue();
754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (isNotNull(info.getAlgorithm().getParameters()))
774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            DSAParameter params = DSAParameter.getInstance(info.getAlgorithm().getParameters());
794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            this.dsaSpec = new DSAParameterSpec(params.getP(), params.getQ(), params.getG());
814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private boolean isNotNull(ASN1Encodable parameters)
854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return parameters != null && !DERNull.INSTANCE.equals(parameters.toASN1Primitive());
874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public String getAlgorithm()
904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return "DSA";
924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public String getFormat()
954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return "X.509";
974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public byte[] getEncoded()
1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (dsaSpec == null)
1024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new ASN1Integer(y));
1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG()).toASN1Primitive()), new ASN1Integer(y));
1074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public DSAParams getParams()
1104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return dsaSpec;
1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public BigInteger getY()
1154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return y;
1174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public String toString()
1204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        StringBuffer    buf = new StringBuffer();
1224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        String          nl = System.getProperty("line.separator");
1234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        buf.append("DSA Public Key").append(nl);
1254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        buf.append("            y: ").append(this.getY().toString(16)).append(nl);
1264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return buf.toString();
1284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public int hashCode()
1314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return this.getY().hashCode() ^ this.getParams().getG().hashCode()
1334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ^ this.getParams().getP().hashCode() ^ this.getParams().getQ().hashCode();
1344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public boolean equals(
1374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        Object o)
1384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!(o instanceof DSAPublicKey))
1404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return false;
1424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        DSAPublicKey other = (DSAPublicKey)o;
1454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return this.getY().equals(other.getY())
1474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            && this.getParams().getG().equals(other.getParams().getG())
1484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            && this.getParams().getP().equals(other.getParams().getP())
1494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            && this.getParams().getQ().equals(other.getParams().getQ());
1504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private void readObject(
1534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ObjectInputStream in)
1544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IOException, ClassNotFoundException
1554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        in.defaultReadObject();
1574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        this.dsaSpec = new DSAParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject());
1594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private void writeObject(
1624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ObjectOutputStream out)
1634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IOException
1644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        out.defaultWriteObject();
1664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        out.writeObject(dsaSpec.getP());
1684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        out.writeObject(dsaSpec.getQ());
1694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        out.writeObject(dsaSpec.getG());
1704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom}
172