1 package org.bouncycastle.x509; 2 3 import java.io.IOException; 4 import java.math.BigInteger; 5 import java.security.GeneralSecurityException; 6 import java.security.InvalidKeyException; 7 import java.security.NoSuchAlgorithmException; 8 import java.security.NoSuchProviderException; 9 import java.security.PrivateKey; 10 import java.security.PublicKey; 11 import java.security.SecureRandom; 12 import java.security.SignatureException; 13 import java.security.cert.CertificateEncodingException; 14 import java.security.cert.CertificateParsingException; 15 import java.security.cert.X509Certificate; 16 import java.util.Date; 17 import java.util.Iterator; 18 19 import javax.security.auth.x500.X500Principal; 20 21 import org.bouncycastle.asn1.ASN1Encodable; 22 import org.bouncycastle.asn1.ASN1EncodableVector; 23 import org.bouncycastle.asn1.ASN1InputStream; 24 import org.bouncycastle.asn1.DERBitString; 25 import org.bouncycastle.asn1.DEREncodable; 26 import org.bouncycastle.asn1.DERInteger; 27 import org.bouncycastle.asn1.DERObjectIdentifier; 28 import org.bouncycastle.asn1.DERSequence; 29 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 30 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 31 import org.bouncycastle.asn1.x509.TBSCertificateStructure; 32 import org.bouncycastle.asn1.x509.Time; 33 import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; 34 import org.bouncycastle.asn1.x509.X509CertificateStructure; 35 import org.bouncycastle.asn1.x509.X509ExtensionsGenerator; 36 import org.bouncycastle.asn1.x509.X509Name; 37 import org.bouncycastle.jce.X509Principal; 38 import org.bouncycastle.jce.provider.X509CertificateObject; 39 import org.bouncycastle.x509.extension.X509ExtensionUtil; 40 41 /** 42 * class to produce an X.509 Version 3 certificate. 43 * @deprecated use org.bouncycastle.cert.X509v3CertificateBuilder. 44 */ 45 public class X509V3CertificateGenerator 46 { 47 private V3TBSCertificateGenerator tbsGen; 48 private DERObjectIdentifier sigOID; 49 private AlgorithmIdentifier sigAlgId; 50 private String signatureAlgorithm; 51 private X509ExtensionsGenerator extGenerator; 52 53 public X509V3CertificateGenerator() 54 { 55 tbsGen = new V3TBSCertificateGenerator(); 56 extGenerator = new X509ExtensionsGenerator(); 57 } 58 59 /** 60 * reset the generator 61 */ 62 public void reset() 63 { 64 tbsGen = new V3TBSCertificateGenerator(); 65 extGenerator.reset(); 66 } 67 68 /** 69 * set the serial number for the certificate. 70 */ 71 public void setSerialNumber( 72 BigInteger serialNumber) 73 { 74 if (serialNumber.compareTo(BigInteger.ZERO) <= 0) 75 { 76 throw new IllegalArgumentException("serial number must be a positive integer"); 77 } 78 79 tbsGen.setSerialNumber(new DERInteger(serialNumber)); 80 } 81 82 /** 83 * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the 84 * certificate. 85 */ 86 public void setIssuerDN( 87 X500Principal issuer) 88 { 89 try 90 { 91 tbsGen.setIssuer(new X509Principal(issuer.getEncoded())); 92 } 93 catch (IOException e) 94 { 95 throw new IllegalArgumentException("can't process principal: " + e); 96 } 97 } 98 99 /** 100 * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the 101 * certificate. 102 */ 103 public void setIssuerDN( 104 X509Name issuer) 105 { 106 tbsGen.setIssuer(issuer); 107 } 108 109 public void setNotBefore( 110 Date date) 111 { 112 tbsGen.setStartDate(new Time(date)); 113 } 114 115 public void setNotAfter( 116 Date date) 117 { 118 tbsGen.setEndDate(new Time(date)); 119 } 120 121 /** 122 * Set the subject distinguished name. The subject describes the entity associated with the public key. 123 */ 124 public void setSubjectDN( 125 X500Principal subject) 126 { 127 try 128 { 129 tbsGen.setSubject(new X509Principal(subject.getEncoded())); 130 } 131 catch (IOException e) 132 { 133 throw new IllegalArgumentException("can't process principal: " + e); 134 } 135 } 136 137 /** 138 * Set the subject distinguished name. The subject describes the entity associated with the public key. 139 */ 140 public void setSubjectDN( 141 X509Name subject) 142 { 143 tbsGen.setSubject(subject); 144 } 145 146 public void setPublicKey( 147 PublicKey key) 148 throws IllegalArgumentException 149 { 150 try 151 { 152 tbsGen.setSubjectPublicKeyInfo( 153 SubjectPublicKeyInfo.getInstance(new ASN1InputStream(key.getEncoded()).readObject())); 154 } 155 catch (Exception e) 156 { 157 throw new IllegalArgumentException("unable to process key - " + e.toString()); 158 } 159 } 160 161 /** 162 * Set the signature algorithm. This can be either a name or an OID, names 163 * are treated as case insensitive. 164 * 165 * @param signatureAlgorithm string representation of the algorithm name. 166 */ 167 public void setSignatureAlgorithm( 168 String signatureAlgorithm) 169 { 170 this.signatureAlgorithm = signatureAlgorithm; 171 172 try 173 { 174 sigOID = X509Util.getAlgorithmOID(signatureAlgorithm); 175 } 176 catch (Exception e) 177 { 178 throw new IllegalArgumentException("Unknown signature type requested: " + signatureAlgorithm); 179 } 180 181 sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm); 182 183 tbsGen.setSignature(sigAlgId); 184 } 185 186 /** 187 * Set the subject unique ID - note: it is very rare that it is correct to do this. 188 */ 189 public void setSubjectUniqueID(boolean[] uniqueID) 190 { 191 tbsGen.setSubjectUniqueID(booleanToBitString(uniqueID)); 192 } 193 194 /** 195 * Set the issuer unique ID - note: it is very rare that it is correct to do this. 196 */ 197 public void setIssuerUniqueID(boolean[] uniqueID) 198 { 199 tbsGen.setIssuerUniqueID(booleanToBitString(uniqueID)); 200 } 201 202 private DERBitString booleanToBitString(boolean[] id) 203 { 204 byte[] bytes = new byte[(id.length + 7) / 8]; 205 206 for (int i = 0; i != id.length; i++) 207 { 208 bytes[i / 8] |= (id[i]) ? (1 << ((7 - (i % 8)))) : 0; 209 } 210 211 int pad = id.length % 8; 212 213 if (pad == 0) 214 { 215 return new DERBitString(bytes); 216 } 217 else 218 { 219 return new DERBitString(bytes, 8 - pad); 220 } 221 } 222 223 /** 224 * add a given extension field for the standard extensions tag (tag 3) 225 */ 226 public void addExtension( 227 String oid, 228 boolean critical, 229 DEREncodable value) 230 { 231 this.addExtension(new DERObjectIdentifier(oid), critical, value); 232 } 233 234 /** 235 * add a given extension field for the standard extensions tag (tag 3) 236 */ 237 public void addExtension( 238 DERObjectIdentifier oid, 239 boolean critical, 240 DEREncodable value) 241 { 242 extGenerator.addExtension(oid, critical, value); 243 } 244 245 /** 246 * add a given extension field for the standard extensions tag (tag 3) 247 * The value parameter becomes the contents of the octet string associated 248 * with the extension. 249 */ 250 public void addExtension( 251 String oid, 252 boolean critical, 253 byte[] value) 254 { 255 this.addExtension(new DERObjectIdentifier(oid), critical, value); 256 } 257 258 /** 259 * add a given extension field for the standard extensions tag (tag 3) 260 */ 261 public void addExtension( 262 DERObjectIdentifier oid, 263 boolean critical, 264 byte[] value) 265 { 266 extGenerator.addExtension(oid, critical, value); 267 } 268 269 /** 270 * add a given extension field for the standard extensions tag (tag 3) 271 * copying the extension value from another certificate. 272 * @throws CertificateParsingException if the extension cannot be extracted. 273 */ 274 public void copyAndAddExtension( 275 String oid, 276 boolean critical, 277 X509Certificate cert) 278 throws CertificateParsingException 279 { 280 byte[] extValue = cert.getExtensionValue(oid); 281 282 if (extValue == null) 283 { 284 throw new CertificateParsingException("extension " + oid + " not present"); 285 } 286 287 try 288 { 289 ASN1Encodable value = X509ExtensionUtil.fromExtensionValue(extValue); 290 291 this.addExtension(oid, critical, value); 292 } 293 catch (IOException e) 294 { 295 throw new CertificateParsingException(e.toString()); 296 } 297 } 298 299 /** 300 * add a given extension field for the standard extensions tag (tag 3) 301 * copying the extension value from another certificate. 302 * @throws CertificateParsingException if the extension cannot be extracted. 303 */ 304 public void copyAndAddExtension( 305 DERObjectIdentifier oid, 306 boolean critical, 307 X509Certificate cert) 308 throws CertificateParsingException 309 { 310 this.copyAndAddExtension(oid.getId(), critical, cert); 311 } 312 313 /** 314 * generate an X509 certificate, based on the current issuer and subject 315 * using the default provider "BC". 316 * @deprecated use generate(key, "BC") 317 */ 318 public X509Certificate generateX509Certificate( 319 PrivateKey key) 320 throws SecurityException, SignatureException, InvalidKeyException 321 { 322 try 323 { 324 return generateX509Certificate(key, "BC", null); 325 } 326 catch (NoSuchProviderException e) 327 { 328 throw new SecurityException("BC provider not installed!"); 329 } 330 } 331 332 /** 333 * generate an X509 certificate, based on the current issuer and subject 334 * using the default provider "BC", and the passed in source of randomness 335 * (if required). 336 * @deprecated use generate(key, random, "BC") 337 */ 338 public X509Certificate generateX509Certificate( 339 PrivateKey key, 340 SecureRandom random) 341 throws SecurityException, SignatureException, InvalidKeyException 342 { 343 try 344 { 345 return generateX509Certificate(key, "BC", random); 346 } 347 catch (NoSuchProviderException e) 348 { 349 throw new SecurityException("BC provider not installed!"); 350 } 351 } 352 353 /** 354 * generate an X509 certificate, based on the current issuer and subject, 355 * using the passed in provider for the signing. 356 * @deprecated use generate() 357 */ 358 public X509Certificate generateX509Certificate( 359 PrivateKey key, 360 String provider) 361 throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException 362 { 363 return generateX509Certificate(key, provider, null); 364 } 365 366 /** 367 * generate an X509 certificate, based on the current issuer and subject, 368 * using the passed in provider for the signing and the supplied source 369 * of randomness, if required. 370 * @deprecated use generate() 371 */ 372 public X509Certificate generateX509Certificate( 373 PrivateKey key, 374 String provider, 375 SecureRandom random) 376 throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException 377 { 378 try 379 { 380 return generate(key, provider, random); 381 } 382 catch (NoSuchProviderException e) 383 { 384 throw e; 385 } 386 catch (SignatureException e) 387 { 388 throw e; 389 } 390 catch (InvalidKeyException e) 391 { 392 throw e; 393 } 394 catch (GeneralSecurityException e) 395 { 396 throw new SecurityException("exception: " + e); 397 } 398 } 399 400 /** 401 * generate an X509 certificate, based on the current issuer and subject 402 * using the default provider. 403 * <p> 404 * <b>Note:</b> this differs from the deprecated method in that the default provider is 405 * used - not "BC". 406 * </p> 407 */ 408 public X509Certificate generate( 409 PrivateKey key) 410 throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException 411 { 412 return generate(key, (SecureRandom)null); 413 } 414 415 /** 416 * generate an X509 certificate, based on the current issuer and subject 417 * using the default provider, and the passed in source of randomness 418 * (if required). 419 * <p> 420 * <b>Note:</b> this differs from the deprecated method in that the default provider is 421 * used - not "BC". 422 * </p> 423 */ 424 public X509Certificate generate( 425 PrivateKey key, 426 SecureRandom random) 427 throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException 428 { 429 TBSCertificateStructure tbsCert = generateTbsCert(); 430 byte[] signature; 431 432 try 433 { 434 signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, key, random, tbsCert); 435 } 436 catch (IOException e) 437 { 438 throw new ExtCertificateEncodingException("exception encoding TBS cert", e); 439 } 440 441 try 442 { 443 return generateJcaObject(tbsCert, signature); 444 } 445 catch (CertificateParsingException e) 446 { 447 throw new ExtCertificateEncodingException("exception producing certificate object", e); 448 } 449 } 450 451 /** 452 * generate an X509 certificate, based on the current issuer and subject, 453 * using the passed in provider for the signing. 454 */ 455 public X509Certificate generate( 456 PrivateKey key, 457 String provider) 458 throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException 459 { 460 return generate(key, provider, null); 461 } 462 463 /** 464 * generate an X509 certificate, based on the current issuer and subject, 465 * using the passed in provider for the signing and the supplied source 466 * of randomness, if required. 467 */ 468 public X509Certificate generate( 469 PrivateKey key, 470 String provider, 471 SecureRandom random) 472 throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException 473 { 474 TBSCertificateStructure tbsCert = generateTbsCert(); 475 byte[] signature; 476 477 try 478 { 479 signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, provider, key, random, tbsCert); 480 } 481 catch (IOException e) 482 { 483 throw new ExtCertificateEncodingException("exception encoding TBS cert", e); 484 } 485 486 try 487 { 488 return generateJcaObject(tbsCert, signature); 489 } 490 catch (CertificateParsingException e) 491 { 492 throw new ExtCertificateEncodingException("exception producing certificate object", e); 493 } 494 } 495 496 private TBSCertificateStructure generateTbsCert() 497 { 498 if (!extGenerator.isEmpty()) 499 { 500 tbsGen.setExtensions(extGenerator.generate()); 501 } 502 503 return tbsGen.generateTBSCertificate(); 504 } 505 506 private X509Certificate generateJcaObject(TBSCertificateStructure tbsCert, byte[] signature) 507 throws CertificateParsingException 508 { 509 ASN1EncodableVector v = new ASN1EncodableVector(); 510 511 v.add(tbsCert); 512 v.add(sigAlgId); 513 v.add(new DERBitString(signature)); 514 515 return new X509CertificateObject(new X509CertificateStructure(new DERSequence(v))); 516 } 517 518 /** 519 * Return an iterator of the signature names supported by the generator. 520 * 521 * @return an iterator containing recognised names. 522 */ 523 public Iterator getSignatureAlgNames() 524 { 525 return X509Util.getAlgNames(); 526 } 527 } 528