1package org.bouncycastle.jcajce.provider.asymmetric.dsa; 2 3import java.io.IOException; 4import java.io.ObjectInputStream; 5import java.io.ObjectOutputStream; 6import java.math.BigInteger; 7import java.security.interfaces.DSAParams; 8import java.security.interfaces.DSAPublicKey; 9import java.security.spec.DSAParameterSpec; 10import java.security.spec.DSAPublicKeySpec; 11 12import org.bouncycastle.asn1.ASN1Encodable; 13import org.bouncycastle.asn1.ASN1Integer; 14import org.bouncycastle.asn1.DERNull; 15import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 16import org.bouncycastle.asn1.x509.DSAParameter; 17import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 18import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 19import org.bouncycastle.crypto.params.DSAPublicKeyParameters; 20import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; 21 22public class BCDSAPublicKey 23 implements DSAPublicKey 24{ 25 private static final long serialVersionUID = 1752452449903495175L; 26 27 private BigInteger y; 28 private transient DSAParams dsaSpec; 29 30 BCDSAPublicKey( 31 DSAPublicKeySpec spec) 32 { 33 this.y = spec.getY(); 34 this.dsaSpec = new DSAParameterSpec(spec.getP(), spec.getQ(), spec.getG()); 35 } 36 37 BCDSAPublicKey( 38 DSAPublicKey key) 39 { 40 this.y = key.getY(); 41 this.dsaSpec = key.getParams(); 42 } 43 44 BCDSAPublicKey( 45 DSAPublicKeyParameters params) 46 { 47 this.y = params.getY(); 48 this.dsaSpec = new DSAParameterSpec(params.getParameters().getP(), params.getParameters().getQ(), params.getParameters().getG()); 49 } 50 51 BCDSAPublicKey( 52 BigInteger y, 53 DSAParameterSpec dsaSpec) 54 { 55 this.y = y; 56 this.dsaSpec = dsaSpec; 57 } 58 59 public BCDSAPublicKey( 60 SubjectPublicKeyInfo info) 61 { 62 63 ASN1Integer derY; 64 65 try 66 { 67 derY = (ASN1Integer)info.parsePublicKey(); 68 } 69 catch (IOException e) 70 { 71 throw new IllegalArgumentException("invalid info structure in DSA public key"); 72 } 73 74 this.y = derY.getValue(); 75 76 if (isNotNull(info.getAlgorithm().getParameters())) 77 { 78 DSAParameter params = DSAParameter.getInstance(info.getAlgorithm().getParameters()); 79 80 this.dsaSpec = new DSAParameterSpec(params.getP(), params.getQ(), params.getG()); 81 } 82 } 83 84 private boolean isNotNull(ASN1Encodable parameters) 85 { 86 return parameters != null && !DERNull.INSTANCE.equals(parameters.toASN1Primitive()); 87 } 88 89 public String getAlgorithm() 90 { 91 return "DSA"; 92 } 93 94 public String getFormat() 95 { 96 return "X.509"; 97 } 98 99 public byte[] getEncoded() 100 { 101 if (dsaSpec == null) 102 { 103 return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new ASN1Integer(y)); 104 } 105 106 return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG()).toASN1Primitive()), new ASN1Integer(y)); 107 } 108 109 public DSAParams getParams() 110 { 111 return dsaSpec; 112 } 113 114 public BigInteger getY() 115 { 116 return y; 117 } 118 119 public String toString() 120 { 121 StringBuffer buf = new StringBuffer(); 122 String nl = System.getProperty("line.separator"); 123 124 buf.append("DSA Public Key").append(nl); 125 buf.append(" y: ").append(this.getY().toString(16)).append(nl); 126 127 return buf.toString(); 128 } 129 130 public int hashCode() 131 { 132 return this.getY().hashCode() ^ this.getParams().getG().hashCode() 133 ^ this.getParams().getP().hashCode() ^ this.getParams().getQ().hashCode(); 134 } 135 136 public boolean equals( 137 Object o) 138 { 139 if (!(o instanceof DSAPublicKey)) 140 { 141 return false; 142 } 143 144 DSAPublicKey other = (DSAPublicKey)o; 145 146 return this.getY().equals(other.getY()) 147 && this.getParams().getG().equals(other.getParams().getG()) 148 && this.getParams().getP().equals(other.getParams().getP()) 149 && this.getParams().getQ().equals(other.getParams().getQ()); 150 } 151 152 private void readObject( 153 ObjectInputStream in) 154 throws IOException, ClassNotFoundException 155 { 156 in.defaultReadObject(); 157 158 this.dsaSpec = new DSAParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject()); 159 } 160 161 private void writeObject( 162 ObjectOutputStream out) 163 throws IOException 164 { 165 out.defaultWriteObject(); 166 167 out.writeObject(dsaSpec.getP()); 168 out.writeObject(dsaSpec.getQ()); 169 out.writeObject(dsaSpec.getG()); 170 } 171} 172