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