List of usage examples for org.bouncycastle.jce.provider X509CRLEntryObject getSerialNumber
public BigInteger getSerialNumber()
From source file:org.candlepin.util.CrlFileUtil.java
License:Open Source License
/** * Updates the specified CRL file by adding or removing entries. If both lists are either null * or empty, the CRL file will not be modified by this method. If the file does not exist or * appears to be empty, it will be initialized before processing the lists. * * @param file//from w w w . j a v a 2 s. c o m * The CRL file to update * * @param revoke * A collection of serials to revoke (add) * * @param unrevoke * A collection of serials to unrevoke (remove) * * @throws IOException * if an IO error occurs while updating the CRL file */ public void updateCRLFile(File file, final Collection<BigInteger> revoke, final Collection<BigInteger> unrevoke) throws IOException { if (!file.exists() || file.length() == 0) { this.initializeCRLFile(file, revoke); return; } File strippedFile = stripCRLFile(file); InputStream input = null; InputStream reaper = null; BufferedOutputStream output = null; OutputStream filter = null; OutputStream encoder = null; try { // Impl note: // Due to the way the X509CRLStreamWriter works (and the DER format in general), we have // to make two passes through the file. input = new Base64InputStream(new FileInputStream(strippedFile)); reaper = new Base64InputStream(new FileInputStream(strippedFile)); // Note: This will break if we ever stop using RSA keys PrivateKey key = this.pkiReader.getCaKey(); X509CRLStreamWriter writer = new X509CRLStreamWriter(input, (RSAPrivateKey) key, this.pkiReader.getCACert()); // Add new entries if (revoke != null) { Date now = new Date(); for (BigInteger serial : revoke) { writer.add(serial, now, CRLReason.privilegeWithdrawn); } } // Unfortunately, we need to do the prescan before checking if we have changes queued, // or we could miss cases where we have entries to remove, but nothing to add. if (unrevoke != null && !unrevoke.isEmpty()) { writer.preScan(reaper, new CRLEntryValidator() { public boolean shouldDelete(X509CRLEntryObject entry) { return unrevoke.contains(entry.getSerialNumber()); } }); } else { writer.preScan(reaper); } // Verify we actually have work to do now if (writer.hasChangesQueued()) { output = new BufferedOutputStream(new FileOutputStream(file)); filter = new FilterOutputStream(output) { private boolean needsLineBreak = true; public void write(int b) throws IOException { this.needsLineBreak = (b != (byte) '\n'); super.write(b); } public void write(byte[] buffer) throws IOException { this.needsLineBreak = (buffer[buffer.length - 1] != (byte) '\n'); super.write(buffer); } public void write(byte[] buffer, int off, int len) throws IOException { this.needsLineBreak = (buffer[off + len - 1] != (byte) '\n'); super.write(buffer, off, len); } public void close() throws IOException { if (this.needsLineBreak) { super.write((int) '\n'); this.needsLineBreak = false; } // Impl note: // We're intentionally not propagating the call here. } }; encoder = new Base64OutputStream(filter, true, 76, new byte[] { (byte) '\n' }); output.write("-----BEGIN X509 CRL-----\n".getBytes()); writer.lock(); writer.write(encoder); encoder.close(); filter.close(); output.write("-----END X509 CRL-----\n".getBytes()); output.close(); } } catch (GeneralSecurityException e) { // This should never actually happen log.error("Unexpected security error occurred while retrieving CA key", e); } catch (CryptoException e) { // Something went horribly wrong with the stream writer log.error("Unexpected error occurred while writing new CRL file", e); } finally { for (Closeable stream : Arrays.asList(encoder, output, reaper, input)) { if (stream != null) { try { stream.close(); } catch (IOException e) { log.error("Unexpected exception occurred while closing stream: {}", stream, e); } } } if (!strippedFile.delete()) { log.error("Unable to delete temporary CRL file: {}", strippedFile); } } }
From source file:org.candlepin.util.X509CRLStreamWriter.java
License:Open Source License
public synchronized X509CRLStreamWriter preScan(InputStream crlToChange, CRLEntryValidator validator) throws IOException { if (locked) { throw new IllegalStateException("Cannot modify a locked stream."); }//from www .j a va 2 s. c o m if (preScanned) { throw new IllegalStateException("preScan has already been run."); } X509CRLEntryStream reaperStream = null; ASN1InputStream asn1In = null; try { reaperStream = new X509CRLEntryStream(crlToChange); try { if (!reaperStream.hasNext()) { emptyCrl = true; preScanned = true; return this; } while (reaperStream.hasNext()) { X509CRLEntryObject entry = reaperStream.next(); if (validator != null && validator.shouldDelete(entry)) { deletedEntries.add(entry.getSerialNumber()); deletedEntriesLength += entry.getEncoded().length; } } } catch (CRLException e) { throw new IOException("Could not read CRL entry", e); } /* At this point, crlToChange is at the point where the crlExtensions would * be. RFC 5280 says that "Conforming CRL issuers are REQUIRED to include * the authority key identifier (Section 5.2.1) and the CRL number (Section 5.2.3) * extensions in all CRLs issued. */ byte[] oldExtensions = null; DERObject o; asn1In = new ASN1InputStream(crlToChange); while ((o = asn1In.readObject()) != null) { if (o instanceof DERSequence) { // Now we are at the signatureAlgorithm DERSequence seq = (DERSequence) o; if (seq.getObjectAt(0) instanceof DERObjectIdentifier) { signingAlg = new AlgorithmIdentifier(seq); digestAlg = new DefaultDigestAlgorithmIdentifierFinder().find(signingAlg); try { // Build the signer this.signer = new RSADigestSigner(createDigest(digestAlg)); signer.init(true, new RSAKeyParameters(true, key.getModulus(), key.getPrivateExponent())); } catch (CryptoException e) { throw new IOException( "Could not create RSADigest signer for " + digestAlg.getAlgorithm()); } } } else if (o instanceof DERBitString) { oldSigLength = o.getDEREncoded().length; } else { if (oldExtensions != null) { throw new IllegalStateException("Already read in CRL extensions."); } oldExtensions = ((DERTaggedObject) o).getDEREncoded(); } } if (oldExtensions == null) { /* v1 CRLs (defined in RFC 1422) don't require extensions but all new * CRLs should be v2 (defined in RFC 5280). In the extremely unlikely * event that someone is working with a v1 CRL, we handle it here although * we print a warning. */ preScanned = true; newExtensions = null; extensionsDelta = 0; log.warn("The CRL you are modifying is a version 1 CRL." + " Please investigate moving to a version 2 CRL by adding the CRL Number" + " and Authority Key Identifier extensions."); return this; } newExtensions = updateExtensions(oldExtensions); extensionsDelta = (newExtensions.length - oldExtensions.length) + findHeaderBytesDelta(oldExtensions.length, newExtensions.length); } finally { if (reaperStream != null) { reaperStream.close(); } IOUtils.closeQuietly(asn1In); } preScanned = true; return this; }
From source file:org.candlepin.util.X509CRLStreamWriterTest.java
License:Open Source License
@Test public void testDeleteEntryFromCRL() throws Exception { X509v2CRLBuilder crlBuilder = createCRLBuilder(); crlBuilder.addCRLEntry(new BigInteger("101"), new Date(), CRLReason.unspecified); X509CRLHolder holder = crlBuilder.build(signer); File crlToChange = writeCRL(holder); CRLEntryValidator validator = new CRLEntryValidator() { @Override/*from w w w.j a va 2 s .c o m*/ public boolean shouldDelete(X509CRLEntryObject entry) { return entry.getSerialNumber().equals(new BigInteger("101")); } }; X509CRLStreamWriter stream = new X509CRLStreamWriter(crlToChange, (RSAPrivateKey) keyPair.getPrivate(), (RSAPublicKey) keyPair.getPublic()); stream.add(new BigInteger("9000"), new Date(), 0); stream.preScan(crlToChange, validator).lock(); OutputStream o = new BufferedOutputStream(new FileOutputStream(outfile)); stream.write(o); o.close(); X509CRL changedCrl = readCRL(); Set<BigInteger> discoveredSerials = new HashSet<BigInteger>(); for (X509CRLEntry entry : changedCrl.getRevokedCertificates()) { discoveredSerials.add(entry.getSerialNumber()); } Set<BigInteger> expected = new HashSet<BigInteger>(); expected.add(new BigInteger("100")); expected.add(new BigInteger("9000")); assertEquals(expected, discoveredSerials); }