Example usage for org.apache.commons.codec.binary Hex encodeHexString

List of usage examples for org.apache.commons.codec.binary Hex encodeHexString

Introduction

In this page you can find the example usage for org.apache.commons.codec.binary Hex encodeHexString.

Prototype

public static String encodeHexString(byte[] data) 

Source Link

Document

Converts an array of bytes into a String representing the hexadecimal values of each byte in order.

Usage

From source file:eu.europa.ec.markt.dss.signature.pades.PAdESProfileLTV.java

private void integrateOCSP(LTVSignatureValidationCallback callback, PdfStamper stamper,
        PdfDictionary dssDictionary, PdfDictionary sigVriDictionary, PdfDictionary vriDictionary)
        throws IOException {
    if (callback.getOcspsArray().size() > 0) {
        // Reference in the DSS dictionary
        PdfIndirectReference ocspsRef = stamper.getWriter().getPdfIndirectReference();
        stamper.getWriter().addToBody(callback.getOcspsArray(), ocspsRef, false);
        dssDictionary.put(new PdfName("OCSPs"), ocspsRef);

        // Array in the signature's VRI dictionary
        PdfIndirectReference sigVriOcspRef = stamper.getWriter().getPdfIndirectReference();
        stamper.getWriter().addToBody(callback.getOcspsArray(), sigVriOcspRef, false);
        sigVriDictionary.put(new PdfName("OCSP"), sigVriOcspRef);

        // Build and reference a VRI dictionary for each OCSP response
        for (BasicOCSPResp ocsp : ocspRefs.keySet()) {
            try {
                PdfIndirectReference vriRef = buildVRIDict(stamper, ocsp);
                MessageDigest md = MessageDigest.getInstance(DigestAlgorithm.SHA1.getName());
                String hexHash = Hex.encodeHexString(md.digest(ocsp.getSignature())).toUpperCase();
                vriDictionary.put(new PdfName(hexHash), vriRef);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException();
            }/*from w  w  w  . j  a v  a 2  s .co m*/
        }
    }
}

From source file:com.aoppp.gatewaysdk.internal.hw.DigestUtils2.java

/**
 * Calculates the SHA-1 digest and returns the value as a hex string.
 *
 * @param data/* w  w  w  .j a  v a2 s  .com*/
 *            Data to digest
 * @return SHA-1 digest as a hex string
 * @since 1.7
 */
public static String sha1Hex(final String data) {
    return Hex.encodeHexString(sha1(data));
}

From source file:com.hortonworks.streamline.streams.service.UDFCatalogResource.java

private void processUdf(InputStream inputStream, UDF udf, boolean checkDuplicate, boolean builtin)
        throws Exception {
    if (builtin) {
        udf.setDigest("builtin");
        udf.setJarStoragePath("builtin");
        checkDuplicate(udf);/*from   w  w w . j  a v a  2 s .co  m*/
    } else {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        File tmpFile;
        try (DigestInputStream dis = new DigestInputStream(inputStream, md)) {
            tmpFile = FileUtil.writeInputStreamToTempFile(dis, ".jar");
        }
        Map<String, Class<?>> udfs = catalogService.loadUdfsFromJar(tmpFile);
        validateUDF(new HashSet<>(ProxyUtil.canonicalNames(udfs.values())), udf, checkDuplicate);
        updateTypeInfo(udf, udfs.get(udf.getClassName()));
        String digest = Hex.encodeHexString(md.digest());
        LOG.debug("Digest: {}", digest);
        udf.setDigest(digest);
        String jarPath = getExistingJarPath(digest).orElseGet(() -> uploadJar(tmpFile, udf.getName()));
        if (!fileStorage.exists(jarPath)) {
            String msg = String.format("The jar path '%s' does not exist. "
                    + "You may have to reset the db and run bootstrap again.", jarPath);
            LOG.error(msg);
            throw new RuntimeException(msg);
        }
        udf.setJarStoragePath(jarPath);
    }
}

From source file:com.dinochiesa.edgecallouts.AesCryptoCallout.java

private void emitEncodedOutput(MessageContext msgCtxt, String name, byte[] data) {
    String encoded = Hex.encodeHexString(data);
    msgCtxt.setVariable(varName(name + "_hex"), encoded);
    encoded = Base64.encodeBase64String(data);
    msgCtxt.setVariable(varName(name + "_b64"), encoded);
}

From source file:com.tremolosecurity.unison.google.u2f.U2FServerUnison.java

@Override
public SecurityKeyData processSignResponse(SignResponse signResponse) throws U2FException {
    if (log.isDebugEnabled()) {
        log.debug(">> processSignResponse");
    }/*from   w w w  .  j a  v  a2s . c  o m*/

    String sessionId = signResponse.getSessionId();
    String browserDataBase64 = signResponse.getClientData();
    String rawSignDataBase64 = signResponse.getSignatureData();

    SignSessionData sessionData = dataStore.getSignSessionData(sessionId);

    if (sessionData == null) {
        throw new U2FException("Unknown session_id");
    }

    String appId = sessionData.getAppId();
    SecurityKeyData securityKeyData = null;

    for (SecurityKeyData temp : dataStore.getSecurityKeyData(sessionData.getAccountName())) {
        if (Arrays.equals(sessionData.getPublicKey(), temp.getPublicKey())) {
            securityKeyData = temp;
            break;
        }
    }

    if (securityKeyData == null) {
        throw new U2FException("No security keys registered for this user");
    }

    String browserData = new String(Base64.decodeBase64(browserDataBase64));
    byte[] rawSignData = Base64.decodeBase64(rawSignDataBase64);

    if (log.isDebugEnabled()) {
        log.debug("-- Input --");
        log.debug("  sessionId: " + sessionId);
        log.debug("  publicKey: " + Hex.encodeHexString(securityKeyData.getPublicKey()));
        log.debug("  challenge: " + Hex.encodeHexString(sessionData.getChallenge()));
        log.debug("  accountName: " + sessionData.getAccountName());
        log.debug("  browserData: " + browserData);
        log.debug("  rawSignData: " + Hex.encodeHexString(rawSignData));
    }
    verifyBrowserData(new JsonParser().parse(browserData), "navigator.id.getAssertion", sessionData);

    AuthenticateResponse authenticateResponse = RawMessageCodec.decodeAuthenticateResponse(rawSignData);
    byte userPresence = authenticateResponse.getUserPresence();
    int counter = authenticateResponse.getCounter();
    byte[] signature = authenticateResponse.getSignature();

    if (log.isDebugEnabled()) {
        log.debug("-- Parsed rawSignData --");
        log.debug("  userPresence: " + Integer.toHexString(userPresence & 0xFF));
        log.debug("  counter: " + counter);
        log.debug("  signature: " + Hex.encodeHexString(signature));
    }

    if ((userPresence & UserPresenceVerifier.USER_PRESENT_FLAG) == 0) {
        throw new U2FException("User presence invalid during authentication");
    }

    if (counter <= securityKeyData.getCounter()) {
        throw new U2FException("Counter value smaller than expected!");
    }

    byte[] appIdSha256 = crypto.computeSha256(appId.getBytes());
    byte[] browserDataSha256 = crypto.computeSha256(browserData.getBytes());
    byte[] signedBytes = RawMessageCodec.encodeAuthenticateSignedBytes(appIdSha256, userPresence, counter,
            browserDataSha256);

    if (log.isDebugEnabled()) {
        log.debug("Verifying signature of bytes " + Hex.encodeHexString(signedBytes));
    }

    if (!crypto.verifySignature(crypto.decodePublicKey(securityKeyData.getPublicKey()), signedBytes,
            signature)) {
        throw new U2FException("Signature is invalid");
    }

    dataStore.updateSecurityKeyCounter(sessionData.getAccountName(), securityKeyData.getPublicKey(), counter);

    if (log.isDebugEnabled()) {
        log.debug("<< processSignResponse");
    }
    return securityKeyData;
}

From source file:com.tremolosecurity.proxy.auth.SAML2Auth.java

public void initializeSSO(HttpServletRequest req, HttpServletResponse resp, HttpSession session, boolean isJump,
        String jumpPage) throws MalformedURLException, ServletException {
    {//ww  w . ja  v  a2  s .  c  o m
        RequestHolder reqHolder = ((AuthController) session.getAttribute(ProxyConstants.AUTH_CTL)).getHolder();

        HashMap<String, Attribute> authParams = (HashMap<String, Attribute>) session
                .getAttribute(ProxyConstants.AUTH_MECH_PARAMS);

        boolean isMultiIdp = authParams.get("isMultiIdP") != null
                && authParams.get("isMultiIdP").getValues().get(0).equalsIgnoreCase("true");

        String postAuthnReqTo = "";
        String redirAuthnReqTo = "";
        String assertionConsumerServiceURL = "";
        boolean signAuthnReq = false;

        String uri = (String) req.getAttribute(ProxyConstants.AUTH_REDIR_URI);
        if (uri == null) {
            uri = req.getRequestURI();
        }

        if (isMultiIdp) {

            URL url = new URL(req.getRequestURL().toString());
            String hostName = url.getHost();
            String dn = authParams.get("idpDir").getValues().get(0);

            try {
                StringBuffer b = new StringBuffer();

                LDAPSearchResults res = cfgMgr.getMyVD().search(dn, 2, equal("hostname", hostName).toString(),
                        new ArrayList<String>());
                if (!res.hasMore()) {
                    throw new ServletException("No IdP found");
                }

                LDAPEntry entry = res.next();
                postAuthnReqTo = entry.getAttribute("idpURL").getStringValue();

                redirAuthnReqTo = entry.getAttribute("idpRedirURL").getStringValue();

                assertionConsumerServiceURL = ProxyTools.getInstance().getFqdnUrl(uri, req);
                signAuthnReq = entry.getAttribute("signAuthnReq").getStringValue().equalsIgnoreCase("1");

            } catch (LDAPException e) {
                throw new ServletException("Could not load IdP data", e);
            }

        } else {
            postAuthnReqTo = authParams.get("idpURL").getValues().get(0);// "http://idp.partner.domain.com:8080/opensso/SSOPOST/metaAlias/testSaml2Idp";

            redirAuthnReqTo = authParams.get("idpRedirURL").getValues().get(0);

            assertionConsumerServiceURL = ProxyTools.getInstance().getFqdnUrl(uri, req);// "http://sp.localdomain.com:8080/SampleSP/echo";

            if (authParams.get("forceToSSL") != null
                    && authParams.get("forceToSSL").getValues().get(0).equalsIgnoreCase("true")) {
                if (!assertionConsumerServiceURL.startsWith("https")) {
                    assertionConsumerServiceURL = assertionConsumerServiceURL.replace("http://", "https://");
                }
            }

            signAuthnReq = authParams.get("signAuthnReq") != null
                    && authParams.get("signAuthnReq").getValues().get(0).equalsIgnoreCase("true");
        }

        ConfigManager cfg = (ConfigManager) req.getAttribute(ProxyConstants.TREMOLO_CFG_OBJ);

        AuthnRequestBuilder authnBuilder = new AuthnRequestBuilder();
        AuthnRequest authn = authnBuilder.buildObject();
        authn.setAssertionConsumerServiceURL(assertionConsumerServiceURL);
        authn.setProtocolBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
        //authn.setDestination(postAuthnReqTo);
        authn.setDestination(redirAuthnReqTo);
        DateTime dt = new DateTime();

        String authMechanism = authParams.get("authCtxRef").getValues().get(0);

        byte[] idBytes = new byte[20];
        random.nextBytes(idBytes);

        /*StringBuffer id = new StringBuffer();
        for (byte b : idBytes) {
           id.append(Hex.encode(idBytes));
        }*/

        StringBuffer b = new StringBuffer();
        b.append('f').append(Hex.encodeHexString(idBytes));

        String id = b.toString();

        authn.setIssueInstant(dt);
        //authn.setID(Long.toString(random.nextLong()));
        authn.setID(id.toString());
        session.setAttribute("AUTOIDM_SAML2_REQUEST", authn.getID());
        IssuerBuilder ib = new IssuerBuilder();
        Issuer issuer = ib.buildObject();
        issuer.setValue(assertionConsumerServiceURL);

        authn.setIssuer(issuer);
        //authn.setAssertionConsumerServiceIndex(0);
        //authn.setAttributeConsumingServiceIndex(0);

        NameIDPolicyBuilder nidbpb = new NameIDPolicyBuilder();
        NameIDPolicy nidp = nidbpb.buildObject();
        //nidp.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified");
        nidp.setFormat("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
        nidp.setAllowCreate(true);
        nidp.setSPNameQualifier(assertionConsumerServiceURL);
        //authn.setNameIDPolicy(nidp);

        authn.setIsPassive(false);
        //authn.setProviderName("tremolosecurity.com");

        if (!authMechanism.isEmpty() && !authMechanism.equalsIgnoreCase("none")) {
            AuthnContextClassRefBuilder accrb = new AuthnContextClassRefBuilder();
            AuthnContextClassRef accr = accrb.buildObject();

            accr.setAuthnContextClassRef(authMechanism);

            //accr.setAuthnContextClassRef("urn:federation:authentication:windows");
            //accr.setAuthnContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport");

            RequestedAuthnContextBuilder racb = new RequestedAuthnContextBuilder();
            RequestedAuthnContext rac = racb.buildObject();
            rac.getAuthnContextClassRefs().add(accr);
            rac.setComparison(AuthnContextComparisonTypeEnumeration.EXACT);
            authn.setRequestedAuthnContext(rac);
        }

        authn.setForceAuthn(false);

        try {
            // Get the Subject marshaller
            Marshaller marshaller = new AuthnRequestMarshaller();

            // Marshall the Subject
            //Element assertionElement = marshaller.marshall(authn);

            String xml = OpenSAMLUtils.xml2str(authn);
            xml = xml.substring(xml.indexOf("?>") + 2);

            if (logger.isDebugEnabled()) {
                logger.debug("=======AuthnRequest============");
                logger.debug(xml);
                logger.debug("=======AuthnRequest============");
            }

            byte[] bxml = xml.getBytes("UTF-8");

            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            DeflaterOutputStream compressor = new DeflaterOutputStream(baos,
                    new Deflater(Deflater.BEST_COMPRESSION, true));

            compressor.write(bxml);
            compressor.flush();
            compressor.close();

            String b64 = new String(Base64.encodeBase64(baos.toByteArray()));
            StringBuffer redirURL = new StringBuffer();
            StringBuffer query = new StringBuffer();

            idBytes = new byte[20];
            random.nextBytes(idBytes);

            query.append("SAMLRequest=").append(URLEncoder.encode(b64, "UTF-8")).append("&RelayState=")
                    .append(URLEncoder.encode(Hex.encodeHexString(idBytes), "UTF-8"));

            if (signAuthnReq) {

                String sigAlg = authParams.get("sigAlg") != null ? authParams.get("sigAlg").getValues().get(0)
                        : "RSA-SHA1";

                String xmlSigAlg = SAML2Auth.xmlDigSigAlgs.get(sigAlg);
                String javaSigAlg = SAML2Auth.javaDigSigAlgs.get(sigAlg);

                //sb.append("SAMLRequest=").append(xml).append("&SigAlg=").append(URLEncoder.encode("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "UTF-8"));
                query.append("&SigAlg=").append(URLEncoder.encode(xmlSigAlg, "UTF-8"));

                java.security.Signature signer = java.security.Signature.getInstance(javaSigAlg);

                if (authParams.get("spSigKey") == null) {
                    throw new ServletException("No signature certificate specified");
                }
                String spSigKey = authParams.get("spSigKey").getValues().get(0);

                signer.initSign(cfgMgr.getPrivateKey(spSigKey));
                signer.update(query.toString().getBytes("UTF-8"));
                String base64Sig = new String(Base64.encodeBase64(signer.sign()));
                query.append("&Signature=").append(URLEncoder.encode(base64Sig, "UTF-8"));
            }

            redirURL.append(redirAuthnReqTo).append("?").append(query.toString());

            if (isJump) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Redirecting to Jump Page");
                    logger.debug("SAML2_JUMPPAGE='" + req.getAttribute("TREMOLO_AUTH_REDIR_URI"));
                }

                session.setAttribute("SAML2_JUMPPAGE", redirURL.toString());
                resp.sendRedirect(jumpPage);
            } else {
                resp.sendRedirect(redirURL.toString());
            }

            /*String b64 = new String(
                  org.apache.directory.shared.ldap.util.Base64
                .encode(bxml));
                    
            req.setAttribute("postaction", postAuthnReqTo);
            req.setAttribute("postdata", b64);
            req.getRequestDispatcher("/auth/fed/postauthnreq.jsp").forward(
                  req, resp);*/

        } catch (Exception e) {
            throw new ServletException("Error generating new authn request", e);
        }
    }
}

From source file:com.bitbreeds.webrtc.datachannel.DataChannelImpl.java

/**
 * The method to call to send data./*from  ww w  .j av  a2s . c  om*/
 * Uses a fair lock to ensure thread safety and avoid starvation
 *
 * @param out data to send
 */
private void putDataOnWire(byte[] out) {
    logger.trace("Sending: " + Hex.encodeHexString(out));
    lock.lock();
    try {
        transport.send(out, 0, out.length);
    } catch (IOException e) {
        logger.error("Sending message {} failed", Hex.encodeHex(out), e);
    } finally {
        lock.unlock();
    }
}

From source file:at.gv.egiz.pdfas.lib.pki.impl.DefaultCertificateVerificationDataProvider.java

/**
 * Looks for an certificate chain from configuration folder chain suitable for the provided certificate.
 * //from  w  ww  . j av a 2s .  c  o  m
 * @param certificate
 *            The (end entity) certificate (the signing certificate actually) (required; must not be {@code null}).
 * @param settings
 *            The configuration of the PDF-AS environment (required; must not be {@code null}).
 * @return A readable URL reflecting the a PKCS7 resource or {@code null}.
 */
private File findChainFile(X509Certificate certificate, ISettings settings) {
    final String issuerSkiHex = getAuthorityKeyIdentifierHexString(certificate);
    final String subjectFingerprintHex = Hex.encodeHexString(certificate.getFingerprintSHA());

    if (issuerSkiHex != null) {
        log.debug(
                "Looking for certificate chain file for certificate with SHA-1 fingerprint {} (issuer subject key identifier {}).",
                subjectFingerprintHex, issuerSkiHex);
        File certChainDirectory = new File(settings.getWorkingDirectory(), DEFAULT_CHAINSTORE_FOLDER_NAME);
        if (certChainDirectory.exists() && certChainDirectory.isDirectory()) {
            File certChainFile = new File(certChainDirectory, "certchain-ski" + issuerSkiHex + ".p7b");
            if (certChainFile.exists()) {
                if (certChainFile.canRead()) {
                    log.debug("Found chain file for certificate (SHA-1 fingerprint {}): {}",
                            subjectFingerprintHex, certChainFile.getAbsolutePath());
                    return certChainFile;
                } else {
                    log.warn(
                            "Found chain file for certificate (SHA-1 fingerprint {}), but file is not readable: {}",
                            subjectFingerprintHex, certChainFile.getAbsolutePath());
                }
            } else {
                log.debug("No chain file for certificate (SHA-1 fingerprint {}) provided by configuration: {}",
                        subjectFingerprintHex, certChainFile.getAbsolutePath());
            }
        } else {
            log.trace("Certificate chain folder does not exist: {}", certChainDirectory.getAbsolutePath());
        }
    } else {
        log.warn("Unable to determine authority key identifier of certificate with SHA-1 fingerprint {}.",
                subjectFingerprintHex);
    }
    return null;
}

From source file:com.hurence.logisland.processor.ModifyIdTest.java

@Test
public void testEncoding() throws NoSuchAlgorithmException {
    final TestRunner testRunner = TestRunners.newTestRunner(new ModifyId());
    testRunner.setProperty(ModifyId.STRATEGY, ModifyId.HASH_FIELDS_STRATEGY.getValue());
    testRunner.setProperty(CHARSET_TO_USE_FOR_HASH, "US-ASCII");
    testRunner.assertValid();/*from ww w.  ja  v  a 2  s .co m*/

    /**
     * ERRORS
     */
    String rawValue = "a,b,c,12.5";
    Record record1 = getRecord1().setStringField(FieldDictionary.RECORD_VALUE, rawValue);
    testRunner.enqueue(record1);
    testRunner.run();
    testRunner.assertAllInputRecordsProcessed();
    testRunner.assertOutputRecordsCount(1);
    MockRecord outputRecord = testRunner.getOutputRecords().get(0);

    StringBuilder stb = new StringBuilder();
    stb.append(rawValue);
    final MessageDigest digest = MessageDigest.getInstance("SHA-256");
    final Charset charset = Charset.forName("US-ASCII");
    digest.update(stb.toString().getBytes(charset));
    byte[] digested = digest.digest();

    StringBuffer hexString = new StringBuffer();
    for (int i = 0; i < digested.length; i++) {
        hexString.append(Integer.toHexString(0xFF & digested[i]));
    }

    String id = Hex.encodeHexString(digested);

    outputRecord.assertFieldEquals(FieldDictionary.RECORD_ID, id);

}

From source file:gobblin.tunnel.TestTunnelWithArbitraryTCPTraffic.java

private void runSimultaneousDataExchange(boolean useTunnel, int nclients)
        throws IOException, InterruptedException, NoSuchAlgorithmException {
    long t0 = System.currentTimeMillis();
    final int nMsgs = 50;
    final Map<String, MessageDigest> digestMsgsRecvdAtServer = new HashMap<String, MessageDigest>();
    final Map<String, MessageDigest> digestMsgsSentByClients = new HashMap<String, MessageDigest>();
    final Map<String, MessageDigest> digestMsgsRecvdAtClients = new HashMap<String, MessageDigest>();
    for (int c = 0; c < nclients; c++) {
        digestMsgsRecvdAtServer.put(Integer.toString(c), MessageDigest.getInstance("MD5"));
        digestMsgsSentByClients.put(Integer.toString(c), MessageDigest.getInstance("MD5"));
        digestMsgsRecvdAtClients.put(Integer.toString(c), MessageDigest.getInstance("MD5"));
    }/*from  ww w . j a va2s .  c  o m*/
    final MessageDigest digestMsgsSentByServer = MessageDigest.getInstance("MD5");
    for (int i = 0; i < nMsgs; i++) {
        digestMsgsSentByServer.update(TalkPastServer.generateMsgFromServer(i).getBytes());
    }
    String hashOfMsgsSentByServer = Hex.encodeHexString(digestMsgsSentByServer.digest());

    MockServer talkPastServer = startTalkPastServer(nMsgs, digestMsgsRecvdAtServer);

    int targetPort = talkPastServer.getServerSocketPort();
    Tunnel tunnel = null;
    MockServer proxyServer = null;
    if (useTunnel) {
        proxyServer = startConnectProxyServer();
        tunnel = Tunnel.build("localhost", talkPastServer.getServerSocketPort(), "localhost",
                proxyServer.getServerSocketPort());
        targetPort = tunnel.getPort();
    }

    try {
        List<EasyThread> clientThreads = new ArrayList<EasyThread>();
        final int portToUse = targetPort;
        for (int c = 0; c < nclients; c++) {
            final int clientId = c;
            clientThreads.add(new EasyThread() {
                @Override
                void runQuietly() throws Exception {
                    long t = System.currentTimeMillis();
                    LOG.info("\t" + clientId + ": Client starting");
                    final MessageDigest digestMsgsRecvdAtClient = digestMsgsRecvdAtClients
                            .get(Integer.toString(clientId));
                    //final SocketChannel client = SocketChannel.open(); // tunnel test hangs for some reason with SocketChannel
                    final Socket client = new Socket();
                    client.connect(new InetSocketAddress("localhost", portToUse));
                    EasyThread serverReaderThread = new EasyThread() {
                        @Override
                        public void runQuietly() {
                            try {
                                BufferedReader clientIn = new BufferedReader(
                                        new InputStreamReader(client.getInputStream()));
                                String line = clientIn.readLine();
                                while (line != null && !line.equals("Goodbye")) {
                                    //LOG.info("\t" + clientId + ": Server said [" + line.substring(0, 32) + "... ]");
                                    digestMsgsRecvdAtClient.update(line.getBytes());
                                    digestMsgsRecvdAtClient.update("\n".getBytes());
                                    line = clientIn.readLine();
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            LOG.info("\t" + clientId + ": Client done reading");
                        }
                    }.startThread();

                    MessageDigest hashMsgsFromClient = digestMsgsSentByClients.get(Integer.toString(clientId));
                    BufferedOutputStream clientOut = new BufferedOutputStream(client.getOutputStream());
                    for (int i = 0; i < nMsgs; i++) {
                        String msg = clientId + ":" + i + " " + StringUtils.repeat("Blahhh Blahhh ", 10000)
                                + "\n";
                        //LOG.info(clientId + " sending " + msg.length() + " bytes");
                        byte[] bytes = msg.getBytes();
                        hashMsgsFromClient.update(bytes);
                        clientOut.write(bytes);
                        MockServer.sleepQuietly(2);
                    }
                    clientOut.write(("Goodbye\n".getBytes()));
                    clientOut.flush();
                    LOG.info("\t" + clientId + ": Client done writing in " + (System.currentTimeMillis() - t)
                            + " ms");
                    serverReaderThread.join();
                    LOG.info("\t" + clientId + ": Client done in " + (System.currentTimeMillis() - t) + " ms");
                    client.close();
                }
            }.startThread());
        }
        for (Thread clientThread : clientThreads) {
            clientThread.join();
        }
        LOG.info("All data transfer done in " + (System.currentTimeMillis() - t0) + " ms");
    } finally {
        talkPastServer.stopServer();
        if (tunnel != null) {
            proxyServer.stopServer();
            tunnel.close();
            assertFalse(tunnel.isTunnelThreadAlive());
            assertEquals(proxyServer.getNumConnects(), nclients);
        }

        Map<String, String> hashOfMsgsRecvdAtServer = new HashMap<String, String>();
        Map<String, String> hashOfMsgsSentByClients = new HashMap<String, String>();
        Map<String, String> hashOfMsgsRecvdAtClients = new HashMap<String, String>();
        for (int c = 0; c < nclients; c++) {
            String client = Integer.toString(c);
            hashOfMsgsRecvdAtServer.put(client,
                    Hex.encodeHexString(digestMsgsRecvdAtServer.get(client).digest()));
            hashOfMsgsSentByClients.put(client,
                    Hex.encodeHexString(digestMsgsSentByClients.get(client).digest()));
            hashOfMsgsRecvdAtClients.put(client,
                    Hex.encodeHexString(digestMsgsRecvdAtClients.get(client).digest()));
        }

        LOG.info("\tComparing client sent to server received");
        assertEquals(hashOfMsgsSentByClients, hashOfMsgsRecvdAtServer);

        LOG.info("\tComparing server sent to client received");
        for (String hashOfMsgsRecvdAtClient : hashOfMsgsRecvdAtClients.values()) {
            assertEquals(hashOfMsgsSentByServer, hashOfMsgsRecvdAtClient);
        }
        LOG.info("\tDone");
    }
}