Example usage for org.apache.commons.codec.digest DigestUtils sha256

List of usage examples for org.apache.commons.codec.digest DigestUtils sha256

Introduction

In this page you can find the example usage for org.apache.commons.codec.digest DigestUtils sha256.

Prototype

public static byte[] sha256(String data) 

Source Link

Usage

From source file:org.gluu.oxpush2.u2f.v2.device.U2FKeyImpl.java

@Override
public AuthenticateResponse authenticate(AuthenticateRequest authenticateRequest) throws U2FException {
    if (BuildConfig.DEBUG)
        Log.d(TAG, ">> authenticate");

    byte control = authenticateRequest.getControl();
    String application = authenticateRequest.getApplication();
    String challenge = authenticateRequest.getChallenge();
    byte[] keyHandle = authenticateRequest.getKeyHandle();

    if (BuildConfig.DEBUG)
        Log.d(TAG, "-- Inputs --");
    if (BuildConfig.DEBUG)
        Log.d(TAG, "control: " + control);
    if (BuildConfig.DEBUG)
        Log.d(TAG, "application: " + application);
    if (BuildConfig.DEBUG)
        Log.d(TAG, "challenge: " + challenge);
    if (BuildConfig.DEBUG)
        Log.d(TAG, "keyHandle: " + Utils.base64UrlEncode(keyHandle));

    TokenEntry tokenEntry = dataStore.getTokenEntry(keyHandle);

    if (tokenEntry == null) {
        Log.e(TAG, "There is no keyPair for keyHandle: " + Utils.base64UrlEncode(keyHandle));
        return null;
    }//from ww w.j a  v  a2 s  .co  m

    if (!StringUtils.equals(application, tokenEntry.getApplication())) {
        throw new U2FException("KeyHandle " + Utils.base64UrlEncode(keyHandle)
                + " is associated with application: " + tokenEntry.getApplication());
    }

    String keyPairJson = tokenEntry.getKeyPair();
    if (keyPairJson == null) {
        Log.e(TAG, "There is no keyPair for keyHandle: " + Utils.base64UrlEncode(keyHandle));
        return null;
    }

    KeyPair keyPair;
    try {
        keyPair = keyPairGenerator.keyPairFromJson(keyPairJson);
    } catch (U2FException ex) {
        Log.e(TAG, "There is no keyPair for keyHandle: " + Utils.base64UrlEncode(keyHandle));
        return null;
    }

    int counter = dataStore.incrementCounter(keyHandle);
    byte userPresence = userPresenceVerifier.verifyUserPresence();
    byte[] applicationSha256 = DigestUtils.sha256(application);
    byte[] challengeSha256 = DigestUtils.sha256(challenge);
    byte[] signedData = rawMessageCodec.encodeAuthenticateSignedBytes(applicationSha256, userPresence, counter,
            challengeSha256);

    if (BuildConfig.DEBUG)
        Log.d(TAG, "Signing bytes " + Utils.encodeHexString(signedData));

    byte[] signature = keyPairGenerator.sign(signedData, keyPair.getPrivate());

    if (BuildConfig.DEBUG)
        Log.d(TAG, "-- Outputs --");
    if (BuildConfig.DEBUG)
        Log.d(TAG, "userPresence: " + userPresence);
    if (BuildConfig.DEBUG)
        Log.d(TAG, "counter: " + counter);
    if (BuildConfig.DEBUG)
        Log.d(TAG, "signature: " + Utils.encodeHexString(signature));

    if (BuildConfig.DEBUG)
        Log.d(TAG, "<< authenticate");

    return new AuthenticateResponse(userPresence, counter, signature);
}

From source file:org.gluu.super_gluu.u2f.v2.device.U2FKeyImpl.java

@Override
public EnrollmentResponse register(EnrollmentRequest enrollmentRequest) throws U2FException {
    if (BuildConfig.DEBUG)
        Log.d(TAG, ">> register");

    String application = enrollmentRequest.getApplication();
    String challenge = enrollmentRequest.getChallenge();

    if (BuildConfig.DEBUG)
        Log.d(TAG, "-- Inputs --");
    if (BuildConfig.DEBUG)
        Log.d(TAG, "application: " + application);
    if (BuildConfig.DEBUG)
        Log.d(TAG, "challenge: " + challenge);

    byte userPresent = userPresenceVerifier.verifyUserPresence();
    if ((userPresent & AuthenticateRequest.USER_PRESENT_FLAG) == 0) {
        throw new U2FException("Cannot verify user presence");
    }// ww  w . j  ava  2 s  .  c  o  m

    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    byte[] keyHandle = keyPairGenerator.generateKeyHandle();

    TokenEntry tokenEntry = new TokenEntry(keyPairGenerator.keyPairToJson(keyPair),
            enrollmentRequest.getApplication(), enrollmentRequest.getOxPush2Request().getIssuer());
    tokenEntry.setCreatedDate(enrollmentRequest.getOxPush2Request().getCreated());
    tokenEntry.setUserName(enrollmentRequest.getOxPush2Request().getUserName());
    tokenEntry.setAuthenticationMode(enrollmentRequest.getOxPush2Request().getMethod());
    tokenEntry.setKeyHandle(keyHandle);
    String keyHandleTitle = tokenEntry.getIssuer();
    ;
    tokenEntry.setKeyName(keyHandleTitle);
    final boolean oneStep = Utils.isEmpty(enrollmentRequest.getOxPush2Request().getUserName());
    String authenticationType = GluuApplication.get()
            .getString(oneStep ? R.string.one_step : R.string.two_step);
    tokenEntry.setAuthenticationType(authenticationType);
    dataStore.storeTokenEntry(tokenEntry);

    byte[] userPublicKey = keyPairGenerator.encodePublicKey(keyPair.getPublic());

    byte[] applicationSha256 = DigestUtils.sha256(application);
    byte[] challengeSha256 = DigestUtils.sha256(challenge);
    byte[] signedData = rawMessageCodec.encodeRegistrationSignedBytes(applicationSha256, challengeSha256,
            keyHandle, userPublicKey);
    if (BuildConfig.DEBUG)
        Log.d(TAG, "Signing bytes " + Utils.encodeHexString(signedData));

    byte[] signature = keyPairGenerator.sign(signedData, certificatePrivateKey);

    if (BuildConfig.DEBUG)
        Log.d(TAG, "-- Outputs --");
    if (BuildConfig.DEBUG)
        Log.d(TAG, "userPublicKey: " + Utils.encodeHexString(userPublicKey));
    if (BuildConfig.DEBUG)
        Log.d(TAG, "keyHandle: " + Utils.base64UrlEncode(keyHandle));
    if (BuildConfig.DEBUG)
        Log.d(TAG, "vendorCertificate: " + vendorCertificate);
    if (BuildConfig.DEBUG)
        Log.d(TAG, "signature: " + Utils.encodeHexString(signature));

    if (BuildConfig.DEBUG)
        Log.d(TAG, "<< register");

    return new EnrollmentResponse(userPublicKey, keyHandle, vendorCertificate, signature);
}

From source file:org.nmdp.gl.service.jdbc.JdbcUtils.java

static final byte[] hash(final String value) {
    return DigestUtils.sha256(value);
}

From source file:org.saadahmed.snowcrystal.SnowCrystal.java

public static String sha256Base64UrlSafe() {
    return Base64.encodeBase64URLSafeString(DigestUtils.sha256(SnowCrystal.newId().unwrap()));
}

From source file:org.sentilo.web.catalog.utils.IdentityKeyGenerator.java

public static String generateNewToken(final String key) {
    final String value = String.format("%s%s%d", PREFIX, key, new Date().getTime());
    return new String(Hex.encodeHex(DigestUtils.sha256(value)));
}

From source file:org.structr.cloud.CloudConnection.java

public void setEncryptionKey(final String key, final int keyLength) throws InvalidKeyException {

    try {/*from  ww  w . ja v a 2  s.c om*/

        SecretKeySpec skeySpec = new SecretKeySpec(CloudService.trimToSize(DigestUtils.sha256(key), keyLength),
                CloudService.STREAM_CIPHER);

        decrypter.init(Cipher.DECRYPT_MODE, skeySpec);
        encrypter.init(Cipher.ENCRYPT_MODE, skeySpec);

    } catch (Throwable t) {
        t.printStackTrace();
    }
}

From source file:org.toffi.domainmodel.encryptor.impl.AESEncryptorImpl.java

/**
 * Initializes encryptor with current encryption key.
 *
 * @param password//from www .j  av a  2  s  . co  m
 */
public AESEncryptorImpl(String password) {
    try {
        // key = new SecretKeySpec(DigestUtils.sha256(password), "AES");
        key = new SecretKeySpec(DigestUtils.sha256(password), 0, 16, Constants.AES);

        // initialize secure random
        random = SecureRandom.getInstance(Constants.SHA1PRNG);

        // initialize ciphers
        encCipher = Cipher.getInstance(Constants.AES_MODE);
        decCipher = Cipher.getInstance(Constants.AES_MODE);
        ivLen = encCipher.getBlockSize();
    } catch (Exception e) {
        throw new EncryptorException("Error while initializing AESEncryptorImpl.", e);
    }
}

From source file:org.torproject.collector.bridgedescs.SanitizedBridgesWriter.java

private String scrubIpv4Address(String address, byte[] fingerprintBytes, String published) throws IOException {
    if (this.replaceIpAddressesWithHashes) {
        if (this.persistenceProblemWithSecrets) {
            /* There's a persistence problem, so we shouldn't scrub more IP
             * addresses in this execution. */
            return null;
        }//ww w .  ja  v  a 2s . c om
        byte[] hashInput = new byte[4 + 20 + 31];
        String[] ipParts = address.split("\\.");
        for (int i = 0; i < 4; i++) {
            hashInput[i] = (byte) Integer.parseInt(ipParts[i]);
        }
        System.arraycopy(fingerprintBytes, 0, hashInput, 4, 20);
        String month = published.substring(0, "yyyy-MM".length());
        byte[] secret = this.getSecretForMonth(month);
        System.arraycopy(secret, 0, hashInput, 24, 31);
        byte[] hashOutput = DigestUtils.sha256(hashInput);
        String hashedAddress = "10." + (((int) hashOutput[0] + 256) % 256) + "."
                + (((int) hashOutput[1] + 256) % 256) + "." + (((int) hashOutput[2] + 256) % 256);
        return hashedAddress;
    } else {
        return "127.0.0.1";
    }
}

From source file:org.torproject.collector.bridgedescs.SanitizedBridgesWriter.java

private String scrubTcpPort(String portString, byte[] fingerprintBytes, String published) throws IOException {
    if (portString.equals("0")) {
        return "0";
    } else if (this.replaceIpAddressesWithHashes) {
        if (this.persistenceProblemWithSecrets) {
            /* There's a persistence problem, so we shouldn't scrub more TCP
             * ports in this execution. */
            return null;
        }/*from ww  w.j  av  a 2s.  c o m*/
        byte[] hashInput = new byte[2 + 20 + 33];
        int portNumber = Integer.parseInt(portString);
        hashInput[0] = (byte) (portNumber >> 8);
        hashInput[1] = (byte) portNumber;
        System.arraycopy(fingerprintBytes, 0, hashInput, 2, 20);
        String month = published.substring(0, "yyyy-MM".length());
        byte[] secret = this.getSecretForMonth(month);
        System.arraycopy(secret, 50, hashInput, 22, 33);
        byte[] hashOutput = DigestUtils.sha256(hashInput);
        int hashedPort = ((((hashOutput[0] & 0b1111_1111) << 8) | (hashOutput[1] & 0b1111_1111)) >> 2)
                | 0b1100_0000_0000_0000;
        return String.valueOf(hashedPort);
    } else {
        return "1";
    }
}

From source file:org.torproject.collector.bridgedescs.SanitizedBridgesWriter.java

/**
 * Sanitizes a bridge server descriptor and writes it to disk.
 *//* www.  j  a v a 2 s .c o m*/
public void sanitizeAndStoreServerDescriptor(byte[] data) {

    if (this.persistenceProblemWithSecrets) {
        /* There's a persistence problem, so we shouldn't scrub more IP
         * addresses in this execution. */
        return;
    }

    /* Parse descriptor to generate a sanitized version. */
    String scrubbedDesc = null;
    String published = null;
    String masterKeyEd25519FromIdentityEd25519 = null;
    try {
        BufferedReader br = new BufferedReader(new StringReader(new String(data, "US-ASCII")));
        StringBuilder scrubbed = new StringBuilder();
        String line = null;
        String hashedBridgeIdentity = null;
        String address = null;
        String routerLine = null;
        String scrubbedRouterLine = null;
        String scrubbedAddress = null;
        String masterKeyEd25519 = null;
        List<String> orAddresses = null;
        List<String> scrubbedOrAddresses = null;
        boolean skipCrypto = false;
        while ((line = br.readLine()) != null) {

            /* Skip all crypto parts that might be used to derive the bridge's
             * identity fingerprint. */
            if (skipCrypto && !line.startsWith("-----END ")) {
                continue;

                /* Store the router line for later processing, because we may need
                 * the bridge identity fingerprint for replacing the IP address in
                 * the scrubbed version.  */
            } else if (line.startsWith("router ")) {
                String[] parts = line.split(" ");
                if (parts.length != 6) {
                    logger.warn("Invalid router line: '" + line + "'.  Skipping.");
                    return;
                }
                address = parts[2];
                routerLine = line;

                /* Store or-address parts in a list and sanitize them when we have
                 * read the fingerprint. */
            } else if (line.startsWith("or-address ")) {
                if (orAddresses == null) {
                    orAddresses = new ArrayList<String>();
                }
                orAddresses.add(line.substring("or-address ".length()));

                /* Parse the publication time to see if we're still inside the
                 * sanitizing interval. */
            } else if (line.startsWith("published ")) {
                published = line.substring("published ".length());
                if (published.compareTo(maxServerDescriptorPublishedTime) > 0) {
                    maxServerDescriptorPublishedTime = published;
                }
                if (this.bridgeSanitizingCutOffTimestamp.compareTo(published) > 0) {
                    String text = "Sanitizing and storing "
                            + "server descriptor with publication time outside our "
                            + "descriptor sanitizing interval.";
                    if (this.haveWarnedAboutInterval) {
                        logger.debug(text);
                    } else {
                        logger.warn(text);
                        this.haveWarnedAboutInterval = true;
                    }
                }
                scrubbed.append(line + "\n");

                /* Parse the fingerprint to determine the hashed bridge
                 * identity. */
            } else if (line.startsWith("opt fingerprint ") || line.startsWith("fingerprint ")) {
                String fingerprint = line
                        .substring(
                                line.startsWith("opt ") ? "opt fingerprint".length() : "fingerprint".length())
                        .replaceAll(" ", "").toLowerCase();
                byte[] fingerprintBytes = Hex.decodeHex(fingerprint.toCharArray());
                hashedBridgeIdentity = DigestUtils.shaHex(fingerprintBytes).toLowerCase();
                try {
                    scrubbedAddress = scrubIpv4Address(address, fingerprintBytes, published);
                    if (orAddresses != null) {
                        scrubbedOrAddresses = new ArrayList<String>();
                        for (String orAddress : orAddresses) {
                            String scrubbedOrAddress = scrubOrAddress(orAddress, fingerprintBytes, published);
                            if (scrubbedOrAddress != null) {
                                scrubbedOrAddresses.add(scrubbedOrAddress);
                            } else {
                                logger.warn("Invalid address in line " + "'or-address " + orAddress
                                        + "' in bridge server " + "descriptor.  Skipping line!");
                            }
                        }
                    }
                    String[] routerLineParts = routerLine.split(" ");
                    String nickname = routerLineParts[1];
                    String scrubbedOrPort = this.scrubTcpPort(routerLineParts[3], fingerprintBytes, published);
                    String scrubbedDirPort = this.scrubTcpPort(routerLineParts[4], fingerprintBytes, published);
                    String scrubbedSocksPort = this.scrubTcpPort(routerLineParts[5], fingerprintBytes,
                            published);
                    scrubbedRouterLine = String.format("router %s %s %s %s %s%n", nickname, scrubbedAddress,
                            scrubbedOrPort, scrubbedDirPort, scrubbedSocksPort);
                } catch (IOException e) {
                    /* There's a persistence problem, so we shouldn't scrub more
                     * IP addresses in this execution. */
                    this.persistenceProblemWithSecrets = true;
                    return;
                }
                scrubbed.append((line.startsWith("opt ") ? "opt " : "") + "fingerprint");
                for (int i = 0; i < hashedBridgeIdentity.length() / 4; i++) {
                    scrubbed.append(" " + hashedBridgeIdentity.substring(4 * i, 4 * (i + 1)).toUpperCase());
                }
                scrubbed.append("\n");

                /* Replace the contact line (if present) with a generic one. */
            } else if (line.startsWith("contact ")) {
                scrubbed.append("contact somebody\n");

                /* When we reach the signature, we're done. Write the sanitized
                 * descriptor to disk below. */
            } else if (line.startsWith("router-signature")) {
                scrubbedDesc = scrubbedRouterLine;
                if (scrubbedOrAddresses != null) {
                    for (String scrubbedOrAddress : scrubbedOrAddresses) {
                        scrubbedDesc += "or-address " + scrubbedOrAddress + "\n";
                    }
                }
                scrubbedDesc += scrubbed.toString();
                break;

                /* Replace extra-info digest with the hashed digest of the
                 * non-scrubbed descriptor. */
            } else if (line.startsWith("opt extra-info-digest ") || line.startsWith("extra-info-digest ")) {
                String[] parts = line.split(" ");
                if (line.startsWith("opt ")) {
                    scrubbed.append("opt ");
                    parts = line.substring(4).split(" ");
                }
                if (parts.length > 3) {
                    logger.warn("extra-info-digest line contains more arguments than" + "expected: '" + line
                            + "'.  Skipping descriptor.");
                    return;
                }
                scrubbed.append("extra-info-digest "
                        + DigestUtils.shaHex(Hex.decodeHex(parts[1].toCharArray())).toUpperCase());
                if (parts.length > 2) {
                    if (!Base64.isBase64(parts[2])) {
                        logger.warn("Illegal base64 character in extra-info-digest line '" + line
                                + "'.  Skipping descriptor.");
                        return;
                    }
                    scrubbed.append(
                            " " + Base64.encodeBase64String(DigestUtils.sha256(Base64.decodeBase64(parts[2])))
                                    .replaceAll("=", ""));
                }
                scrubbed.append("\n");

                /* Possibly sanitize reject lines if they contain the bridge's own
                 * IP address. */
            } else if (line.startsWith("reject ")) {
                if (address != null && line.startsWith("reject " + address)) {
                    scrubbed.append("reject " + scrubbedAddress
                            + line.substring("reject ".length() + address.length()) + "\n");
                } else {
                    scrubbed.append(line + "\n");
                }

                /* Extract master-key-ed25519 from identity-ed25519. */
            } else if (line.equals("identity-ed25519")) {
                StringBuilder sb = new StringBuilder();
                while ((line = br.readLine()) != null && !line.equals("-----END ED25519 CERT-----")) {
                    if (line.equals("-----BEGIN ED25519 CERT-----")) {
                        continue;
                    }
                    sb.append(line);
                }
                masterKeyEd25519FromIdentityEd25519 = this
                        .parseMasterKeyEd25519FromIdentityEd25519(sb.toString());
                if (masterKeyEd25519FromIdentityEd25519 == null) {
                    logger.warn("Could not parse master-key-ed25519 from "
                            + "identity-ed25519.  Skipping descriptor.");
                    return;
                }
                String sha256MasterKeyEd25519 = Base64
                        .encodeBase64String(DigestUtils
                                .sha256(Base64.decodeBase64(masterKeyEd25519FromIdentityEd25519 + "=")))
                        .replaceAll("=", "");
                scrubbed.append("master-key-ed25519 " + sha256MasterKeyEd25519 + "\n");
                if (masterKeyEd25519 != null && !masterKeyEd25519.equals(masterKeyEd25519FromIdentityEd25519)) {
                    logger.warn("Mismatch between identity-ed25519 and " + "master-key-ed25519.  Skipping.");
                    return;
                }

                /* Verify that identity-ed25519 and master-key-ed25519 match. */
            } else if (line.startsWith("master-key-ed25519 ")) {
                masterKeyEd25519 = line.substring(line.indexOf(" ") + 1);
                if (masterKeyEd25519FromIdentityEd25519 != null
                        && !masterKeyEd25519FromIdentityEd25519.equals(masterKeyEd25519)) {
                    logger.warn("Mismatch between identity-ed25519 and " + "master-key-ed25519.  Skipping.");
                    return;
                }

                /* Write the following lines unmodified to the sanitized
                 * descriptor. */
            } else if (line.startsWith("accept ") || line.startsWith("platform ")
                    || line.startsWith("opt protocols ") || line.startsWith("protocols ")
                    || line.startsWith("proto ") || line.startsWith("uptime ") || line.startsWith("bandwidth ")
                    || line.startsWith("opt hibernating ") || line.startsWith("hibernating ")
                    || line.startsWith("ntor-onion-key ") || line.equals("opt hidden-service-dir")
                    || line.equals("hidden-service-dir") || line.equals("opt caches-extra-info")
                    || line.equals("caches-extra-info") || line.equals("opt allow-single-hop-exits")
                    || line.equals("allow-single-hop-exits") || line.startsWith("ipv6-policy ")
                    || line.equals("tunnelled-dir-server")) {
                scrubbed.append(line + "\n");

                /* Replace node fingerprints in the family line with their hashes
                 * and leave nicknames unchanged. */
            } else if (line.startsWith("family ")) {
                StringBuilder familyLine = new StringBuilder("family");
                for (String s : line.substring(7).split(" ")) {
                    if (s.startsWith("$")) {
                        familyLine.append(" $" + DigestUtils.shaHex(Hex.decodeHex(s.substring(1).toCharArray()))
                                .toUpperCase());
                    } else {
                        familyLine.append(" " + s);
                    }
                }
                scrubbed.append(familyLine.toString() + "\n");

                /* Skip the purpose line that the bridge authority adds to its
                 * cached-descriptors file. */
            } else if (line.startsWith("@purpose ")) {
                continue;

                /* Skip all crypto parts that might leak the bridge's identity
                 * fingerprint. */
            } else if (line.startsWith("-----BEGIN ") || line.equals("onion-key") || line.equals("signing-key")
                    || line.equals("onion-key-crosscert") || line.startsWith("ntor-onion-key-crosscert ")) {
                skipCrypto = true;

                /* Stop skipping lines when the crypto parts are over. */
            } else if (line.startsWith("-----END ")) {
                skipCrypto = false;

                /* Skip the ed25519 signature; we'll include a SHA256 digest of
                 * the SHA256 descriptor digest in router-digest-sha256. */
            } else if (line.startsWith("router-sig-ed25519 ")) {
                continue;

                /* If we encounter an unrecognized line, stop parsing and print
                 * out a warning. We might have overlooked sensitive information
                 * that we need to remove or replace for the sanitized descriptor
                 * version. */
            } else {
                logger.warn("Unrecognized line '" + line + "'. Skipping.");
                return;
            }
        }
        br.close();
    } catch (Exception e) {
        logger.warn("Could not parse server " + "descriptor.", e);
        return;
    }

    /* Determine filename of sanitized server descriptor. */
    String descriptorDigest = null;
    try {
        String ascii = new String(data, "US-ASCII");
        String startToken = "router ";
        String sigToken = "\nrouter-signature\n";
        int start = ascii.indexOf(startToken);
        int sig = ascii.indexOf(sigToken) + sigToken.length();
        if (start >= 0 && sig >= 0 && sig > start) {
            byte[] forDigest = new byte[sig - start];
            System.arraycopy(data, start, forDigest, 0, sig - start);
            descriptorDigest = DigestUtils.shaHex(DigestUtils.sha(forDigest));
        }
    } catch (UnsupportedEncodingException e) {
        /* Handle below. */
    }
    if (descriptorDigest == null) {
        logger.warn("Could not calculate server " + "descriptor digest.");
        return;
    }
    String descriptorDigestSha256Base64 = null;
    if (masterKeyEd25519FromIdentityEd25519 != null) {
        try {
            String ascii = new String(data, "US-ASCII");
            String startToken = "router ";
            String sigToken = "\n-----END SIGNATURE-----\n";
            int start = ascii.indexOf(startToken);
            int sig = ascii.indexOf(sigToken) + sigToken.length();
            if (start >= 0 && sig >= 0 && sig > start) {
                byte[] forDigest = new byte[sig - start];
                System.arraycopy(data, start, forDigest, 0, sig - start);
                descriptorDigestSha256Base64 = Base64
                        .encodeBase64String(DigestUtils.sha256(DigestUtils.sha256(forDigest)))
                        .replaceAll("=", "");
            }
        } catch (UnsupportedEncodingException e) {
            /* Handle below. */
        }
        if (descriptorDigestSha256Base64 == null) {
            logger.warn("Could not calculate server " + "descriptor SHA256 digest.");
            return;
        }
    }
    String dyear = published.substring(0, 4);
    String dmonth = published.substring(5, 7);
    File tarballFile = new File(this.sanitizedBridgesDirectory.getAbsolutePath() + "/" + dyear + "/" + dmonth
            + "/server-descriptors/" + "/" + descriptorDigest.charAt(0) + "/" + descriptorDigest.charAt(1) + "/"
            + descriptorDigest);
    try {
        File rsyncCatFile = new File(config.getPath(Key.RecentPath).toFile(),
                "bridge-descriptors/server-descriptors/" + this.rsyncCatString + "-server-descriptors.tmp");
        File[] outputFiles = new File[] { tarballFile, rsyncCatFile };
        boolean[] append = new boolean[] { false, true };
        for (int i = 0; i < outputFiles.length; i++) {
            File outputFile = outputFiles[i];
            boolean appendToFile = append[i];
            if (outputFile.exists() && !appendToFile) {
                /* We already stored this descriptor to disk before, so let's
                 * not store it yet another time. */
                break;
            }
            outputFile.getParentFile().mkdirs();
            BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile, appendToFile));
            bw.write(Annotation.BridgeServer.toString());
            bw.write(scrubbedDesc);
            if (descriptorDigestSha256Base64 != null) {
                bw.write("router-digest-sha256 " + descriptorDigestSha256Base64 + "\n");
            }
            bw.write("router-digest " + descriptorDigest.toUpperCase() + "\n");
            bw.close();
        }
    } catch (ConfigurationException | IOException e) {
        logger.warn("Could not write sanitized server " + "descriptor to disk.", e);
        return;
    }
}