001package org.apache.commons.ssl.org.bouncycastle.asn1.eac; 002 003import java.math.BigInteger; 004import java.util.Enumeration; 005 006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector; 007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1ObjectIdentifier; 008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString; 009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive; 010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence; 011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject; 012import org.apache.commons.ssl.org.bouncycastle.asn1.DEROctetString; 013import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence; 014import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject; 015 016/** 017 * an Iso7816ECDSAPublicKeyStructure structure. 018 * <pre> 019 * Certificate Holder Authorization ::= SEQUENCE { 020 * ASN1TaggedObject primeModulusP; // OPTIONAL 021 * ASN1TaggedObject firstCoefA; // OPTIONAL 022 * ASN1TaggedObject secondCoefB; // OPTIONAL 023 * ASN1TaggedObject basePointG; // OPTIONAL 024 * ASN1TaggedObject orderOfBasePointR; // OPTIONAL 025 * ASN1TaggedObject publicPointY; //REQUIRED 026 * ASN1TaggedObject cofactorF; // OPTIONAL 027 * } 028 * </pre> 029 */ 030public class ECDSAPublicKey 031 extends PublicKeyDataObject 032{ 033 private ASN1ObjectIdentifier usage; 034 private BigInteger primeModulusP; // OPTIONAL 035 private BigInteger firstCoefA; // OPTIONAL 036 private BigInteger secondCoefB; // OPTIONAL 037 private byte[] basePointG; // OPTIONAL 038 private BigInteger orderOfBasePointR; // OPTIONAL 039 private byte[] publicPointY; //REQUIRED 040 private BigInteger cofactorF; // OPTIONAL 041 private int options; 042 private static final int P = 0x01; 043 private static final int A = 0x02; 044 private static final int B = 0x04; 045 private static final int G = 0x08; 046 private static final int R = 0x10; 047 private static final int Y = 0x20; 048 private static final int F = 0x40; 049 050 ECDSAPublicKey(ASN1Sequence seq) 051 throws IllegalArgumentException 052 { 053 Enumeration en = seq.getObjects(); 054 055 this.usage = ASN1ObjectIdentifier.getInstance(en.nextElement()); 056 057 options = 0; 058 while (en.hasMoreElements()) 059 { 060 Object obj = en.nextElement(); 061 062 if (obj instanceof ASN1TaggedObject) 063 { 064 ASN1TaggedObject to = (ASN1TaggedObject)obj; 065 switch (to.getTagNo()) 066 { 067 case 0x1: 068 setPrimeModulusP(UnsignedInteger.getInstance(to).getValue()); 069 break; 070 case 0x2: 071 setFirstCoefA(UnsignedInteger.getInstance(to).getValue()); 072 break; 073 case 0x3: 074 setSecondCoefB(UnsignedInteger.getInstance(to).getValue()); 075 break; 076 case 0x4: 077 setBasePointG(ASN1OctetString.getInstance(to, false)); 078 break; 079 case 0x5: 080 setOrderOfBasePointR(UnsignedInteger.getInstance(to).getValue()); 081 break; 082 case 0x6: 083 setPublicPointY(ASN1OctetString.getInstance(to, false)); 084 break; 085 case 0x7: 086 setCofactorF(UnsignedInteger.getInstance(to).getValue()); 087 break; 088 default: 089 options = 0; 090 throw new IllegalArgumentException("Unknown Object Identifier!"); 091 } 092 } 093 else 094 { 095 throw new IllegalArgumentException("Unknown Object Identifier!"); 096 } 097 } 098 if (options != 0x20 && options != 0x7F) 099 { 100 throw new IllegalArgumentException("All options must be either present or absent!"); 101 } 102 } 103 104 public ECDSAPublicKey(ASN1ObjectIdentifier usage, byte[] ppY) 105 throws IllegalArgumentException 106 { 107 this.usage = usage; 108 setPublicPointY(new DEROctetString(ppY)); 109 } 110 111 public ECDSAPublicKey(ASN1ObjectIdentifier usage, BigInteger p, BigInteger a, BigInteger b, byte[] basePoint, BigInteger order, byte[] publicPoint, int cofactor) 112 { 113 this.usage = usage; 114 setPrimeModulusP(p); 115 setFirstCoefA(a); 116 setSecondCoefB(b); 117 setBasePointG(new DEROctetString(basePoint)); 118 setOrderOfBasePointR(order); 119 setPublicPointY(new DEROctetString(publicPoint)); 120 setCofactorF(BigInteger.valueOf(cofactor)); 121 } 122 123 public ASN1ObjectIdentifier getUsage() 124 { 125 return usage; 126 } 127 128 public byte[] getBasePointG() 129 { 130 if ((options & G) != 0) 131 { 132 return basePointG; 133 } 134 else 135 { 136 return null; 137 } 138 } 139 140 private void setBasePointG(ASN1OctetString basePointG) 141 throws IllegalArgumentException 142 { 143 if ((options & G) == 0) 144 { 145 options |= G; 146 this.basePointG = basePointG.getOctets(); 147 } 148 else 149 { 150 throw new IllegalArgumentException("Base Point G already set"); 151 } 152 } 153 154 public BigInteger getCofactorF() 155 { 156 if ((options & F) != 0) 157 { 158 return cofactorF; 159 } 160 else 161 { 162 return null; 163 } 164 } 165 166 private void setCofactorF(BigInteger cofactorF) 167 throws IllegalArgumentException 168 { 169 if ((options & F) == 0) 170 { 171 options |= F; 172 this.cofactorF = cofactorF; 173 } 174 else 175 { 176 throw new IllegalArgumentException("Cofactor F already set"); 177 } 178 } 179 180 public BigInteger getFirstCoefA() 181 { 182 if ((options & A) != 0) 183 { 184 return firstCoefA; 185 } 186 else 187 { 188 return null; 189 } 190 } 191 192 private void setFirstCoefA(BigInteger firstCoefA) 193 throws IllegalArgumentException 194 { 195 if ((options & A) == 0) 196 { 197 options |= A; 198 this.firstCoefA = firstCoefA; 199 } 200 else 201 { 202 throw new IllegalArgumentException("First Coef A already set"); 203 } 204 } 205 206 public BigInteger getOrderOfBasePointR() 207 { 208 if ((options & R) != 0) 209 { 210 return orderOfBasePointR; 211 } 212 else 213 { 214 return null; 215 } 216 } 217 218 private void setOrderOfBasePointR(BigInteger orderOfBasePointR) 219 throws IllegalArgumentException 220 { 221 if ((options & R) == 0) 222 { 223 options |= R; 224 this.orderOfBasePointR = orderOfBasePointR; 225 } 226 else 227 { 228 throw new IllegalArgumentException("Order of base point R already set"); 229 } 230 } 231 232 public BigInteger getPrimeModulusP() 233 { 234 if ((options & P) != 0) 235 { 236 return primeModulusP; 237 } 238 else 239 { 240 return null; 241 } 242 } 243 244 private void setPrimeModulusP(BigInteger primeModulusP) 245 { 246 if ((options & P) == 0) 247 { 248 options |= P; 249 this.primeModulusP = primeModulusP; 250 } 251 else 252 { 253 throw new IllegalArgumentException("Prime Modulus P already set"); 254 } 255 } 256 257 public byte[] getPublicPointY() 258 { 259 if ((options & Y) != 0) 260 { 261 return publicPointY; 262 } 263 else 264 { 265 return null; 266 } 267 } 268 269 private void setPublicPointY(ASN1OctetString publicPointY) 270 throws IllegalArgumentException 271 { 272 if ((options & Y) == 0) 273 { 274 options |= Y; 275 this.publicPointY = publicPointY.getOctets(); 276 } 277 else 278 { 279 throw new IllegalArgumentException("Public Point Y already set"); 280 } 281 } 282 283 public BigInteger getSecondCoefB() 284 { 285 if ((options & B) != 0) 286 { 287 return secondCoefB; 288 } 289 else 290 { 291 return null; 292 } 293 } 294 295 private void setSecondCoefB(BigInteger secondCoefB) 296 throws IllegalArgumentException 297 { 298 if ((options & B) == 0) 299 { 300 options |= B; 301 this.secondCoefB = secondCoefB; 302 } 303 else 304 { 305 throw new IllegalArgumentException("Second Coef B already set"); 306 } 307 } 308 309 public boolean hasParameters() 310 { 311 return primeModulusP != null; 312 } 313 314 public ASN1EncodableVector getASN1EncodableVector(ASN1ObjectIdentifier oid, boolean publicPointOnly) 315 { 316 ASN1EncodableVector v = new ASN1EncodableVector(); 317 v.add(oid); 318 319 if (!publicPointOnly) 320 { 321 v.add(new UnsignedInteger(0x01, getPrimeModulusP())); 322 v.add(new UnsignedInteger(0x02, getFirstCoefA())); 323 v.add(new UnsignedInteger(0x03, getSecondCoefB())); 324 v.add(new DERTaggedObject(false, 0x04, new DEROctetString(getBasePointG()))); 325 v.add(new UnsignedInteger(0x05, getOrderOfBasePointR())); 326 } 327 v.add(new DERTaggedObject(false, 0x06, new DEROctetString(getPublicPointY()))); 328 if (!publicPointOnly) 329 { 330 v.add(new UnsignedInteger(0x07, getCofactorF())); 331 } 332 333 return v; 334 } 335 336 public ASN1Primitive toASN1Primitive() 337 { 338 return new DERSequence(getASN1EncodableVector(usage, false)); 339 } 340}