text:
layout: post
title: "How Real Estate Companies Can Implement Open ID Connect With Auth0"
description: All National Association of REALTORS affiliated listing services are now required to adopt the Open ID Connect standard
date: 2016-08-16 12:30
category: Growth, Industries
is_non-tech: true
author:
  name: Martin Gontovnikas
  url: http://twitter.com/mgonto
  mail: gonto@auth0.com
  avatar: "https://www.gravatar.com/avatar/df6c864847fba9687d962cb80b482764??s=60"
design:
  bg_color: "#2D2D2D"
  image: https://cdn.auth0.com/blog/reso-oidc/logo.png
tags:
- oidc
- grow-hacking
- identity
related:
- 2016-07-08-why-your-project-estimations-are-always-wrong
- 2016-07-05-growth-hacking-is-dead-long-live-growth-hacking
- 2016-07-01-why-staying-agile-is-key-to-startup-success
---

At the Real Estate Standards Organization's annual conference in Austin last October, the issue of identity authentication had top billing. The big announcement? Widespread and wholesale encouragement to adopt the Open ID identity management standard across the industry.

Today, it's more than a recommendation. All National Association of REALTORS affiliated listing services **[are now required](http://www.reso.org/new-reso-web-api-standard-3-reasons-implement/)** to adopt the Open ID Connect standard. This is huge, because the seamless management of identity has historically been a big problem for the increasingly digital real estate industry.

While agents have been able to use their personal Google or Facebook accounts to access and share information across different apps, vendor lock-in and proprietary software have made it impossible to do the same at work. Single SSO integrations have taken weeks to complete.

And there's been no shortage of reasons to open up the information flow. Between contact management systems, listings management systems, marketing programs, market analysis systems, and document storage, real estate agents consume a ton of data. All that data used to be siloed off in databases that were totally disconnected from one another—until now.

## What Is Open ID Connect?

Before the RESO adopted Open ID Connect, they were on the Real Estate Transaction System, or RETS. A sixteen-year old system based in XML, this antiquated standard was difficult to learn and use, it was slow, and it was once used by every single real estate website out there.

Open ID Connect is a authentication layer that sits on top of the widely used OAuth 2.0 authorization standard.

OAuth gives websites the power to delegate access to secure areas. It's like a key—if you have yours, you can log in to your account.

Unfortunately, it doesn't offer any way to tie that key to your identity. That means if someone else gets your key, they can also log into your account.

Individual service providers like Facebook have built their own extra authentication layers in years past, ensuring that when *your* key is used it's actually you on the other end. Open ID Connect extends the same logic across the web, providing the same kind of security that Facebook and Google have been using for years as an open standard that any organization can adopt.

## Implementing Open ID Connect With Auth0

The coup de grâce of Open ID Connect is [how easy](https://auth0.com/docs/oauth-web-protocol) it can be to implement into your application. Cal Heldenbrand shared his experience with the OpenID Foundation

> The certification process was pretty easy as well. I was expecting it to be more intensive! Our environment is Ruby on Rails, and I used [Nov's openid_connec](https://github.com/nov/openid_connect)t Ruby gem for constructing ID Tokens. Other than that, my Provider is written from scratch. It took me about 2 weeks to have a very simple provider running for demo purposes. Then another 2 weeks to have it fully compliant with the certification tools. This is also along side my usual day job tasks of web operations. I'd have to say this was a breeze compared to the old OpenID 2.0.

Of course, it can always be a bit faster and easier. Auth0 supports Open ID Connect and a long list of [identity providers](https://auth0.com/docs/identityproviders) and [development stacks](https://auth0.com/docs).

![Auth0 Identity Providers](https://cdn.auth0.com/blog/reso-oidc/identity-providers.png)

You're covered no matter your IdP. There's no need to spend a month writing your own provider and getting it compliant, either—Auth0 is as close to plug-and-play as it gets.

You can set up Open ID Connect in four basic steps:

1. Set up a callback URL from your Auth0 dashboard
2. Integrate Auth0 Lock on your site or trigger login manually
3. Send the `code` your app receives to the Auth0 with a `POST`
4. Use a `GET` to retrieve the user profile from the server's response

Then, when users visit your website, this is what they'll see (you can customize the look of the box, of course!):

![Auth0 Lock Widget](https://cdn.auth0.com/blog/reso-oidc/auth0-lock.png)

For the full breakdown, check out the documentation on implementing Auth0 into your web app [here](https://auth0.com/docs/oauth-web-protocol).

### Building Your Own Identity Provider Hurts

Building your own identity provider could be a good summertime project—no one knows that better than us!—but that month spent wrangling with Open ID Connect starts to look very different when it's the only thing keeping you from launching.

It can easily become a frustrating way to spend your valuable time early on while you should be worrying about finishing your product and finding customers. It can also become a serious roadblock on your feature map, and that sucks.

Plus, even once you finish building it, you have to deal with the tweaks and changes that will become necessary every time a change is made to one of the platforms your users use to log-in. Building an identity provider is not a one-time investment.

With an identity "clearinghouse" like Auth0, all the work of maintaining and keeping your different connections current is taken care of.

## Why Open ID Connect

We've been working with OAuth since we first started building out the core functionality of Auth0. OAuth was always simple, widely used, and highly cross-compatible. But it was never enough to provide secure federated identity management, which is how we found Open ID Connect.

But Open ID Connect isn't just secure. That's the baseline. The true magic of it is something you've already experienced if you've ever used your Facebook account to find your friends' playlists on Spotify—the seamless interchange of information between apps.

Imagine having your listing info, market analysis, customer data and documents all accessible to one another. No more signing in and out of different overlapping systems for different markets and dealing with incompatible systems. One login and one password—that's what Open ID Connect promises.

Auth0 can handle all the different connections and layers of authentication, but it can also help use this data to supercharge your company's marketing and promotional efforts.

### Put Your User Data To Work And Drive Growth

Auth0 "rules" are Javascript snippets run by Auth0 and executed when users are authenticated in your app. These are what allow Auth0 to provide simple, actionable analytics for you to use to grow your business.

![Auth0 Rules Engine](https://cdn.auth0.com/blog/reso-oidc/rules-engine.png)

Conventional analytics run client-side often fail, or even return misleading results—rules are far more reliable because they're run from the back-end. That means clean data you can immediately start using to execute on personalized marketing and retention tactics:

1. **Enrich lead profiles:** Pull publicly available information on your new sign-ups and use it to build detailed customer personas.
2. **Notify your team of new leads:** Loop your authentication into an application like Slack to let everyone know when you have a new prospect.
3. **Craft highly personal marketing emails:** Send the right emails to the right users—you don't want to send a listing announcement to a user who's been inactive for a year.
4. **Analyze user registration info:** Graph your new sign-ups and separate them by source so you can understand what promo campaigns are working and which aren't.

Open ID Connect is changing the world of real estate technology by making it easier than ever to develop and use business applications, but it's not just good for convenience's sake.

Because it provides a way to securely share authentication and verification across platforms, Open ID Connect is opening up to real estate companies the same opportunities that tech companies have had for years—opportunities to treat customers better, learn faster, and [grow at unprecedented rates](https://auth0.com/blog/7-ways-to-2x-your-revenue-growth-by-putting-your-user-data-to-work/).


text:
from __future__ import division
import sendgrid
from datetime import date
from beagle import Game, Status, mailsend, datetimef, User
from jinja2 import Environment, PackageLoader

env = Environment(loader=PackageLoader('beagle', 'templates'))
env.filters['datetime'] = datetimef

def get_games(dau=None, status=None):
	status_ids = []
	status_ids.append(Status.query.filter_by(name=status).first().id)
	status_query = Game.query.join('statuses').filter(Status.id.in_(status_ids)).distinct()
	games = status_query.filter(Game.dau>=dau).all()
	return games

def todays_date():
	today = date.today()
	todays_date = today.strftime("%A, %B %d")
	return todays_date

def get_user_percentage():
	user_data = []
	users = []
	all_users = User.query.all()
	for user in all_users:
		if len(user.leads) > 2:
			users.append(user)
	total_games = len(Game.query.all())
	for user in users:
		number_games = 0
		for lead in user.leads:
			number_games = number_games + len(lead.games)
		game_percentage = (number_games / total_games) * 100
		user_specific = {user.name: round(game_percentage)}
		user_data.append(user_specific)
	return user_data

def make_chart_url():
	users = []
	percentages = []
	user_data = get_user_percentage()
	for user in user_data:
		users.append(user.keys()[0])
		percentages.append(user.values()[0])
	percentages = ','.join(map(str, percentages))
	users = '|'.join(map(str, users))
	url = "https://chart.googleapis.com/chart?cht=p3&chd=t:%s&chs=400x100&chl=%s" % (percentages, users)
	return url

template = env.get_template('twibd.html')

html = template.render(games_10000=get_games(10000, "Testing"), games_50000=get_games(50000, "Integrating"), url=make_chart_url())

plain = "The TWIBD Update for %s includes new games, live games and upcoming games." % (todays_date())

message = sendgrid.Message("beagle@kiip.me", "TWIBD Update for %s" % (todays_date()), plain, html)
message.add_to("jack@kiip.me", "Sales Team")
mailsend.web.send(message)

redpajama_set_name: RedPajamaGithub


text:
"use strict";

var Promise = require('bluebird');

var config = require('../configuration');

function get_amount_string(amounts) {
  var amount = "";
  for(var cur in amounts) {
    if(amount != "") {
      amount += ", ";
    }
    amount += config['registration']['currencies'][cur]['symbol'];
    amount += Math.ceil(amounts[cur]);
  }
  return amount;
}

function get_amounts(reg, type) {
  var amounts = {};
  for(var payment in reg.RegistrationPayments) {
    payment = reg.RegistrationPayments[payment];
    if(payment.paid && (type === undefined || type == payment.type)) {
      if(payment.currency in amounts) {
        amounts[payment.currency] += payment.amount;
      } else {
        amounts[payment.currency] = payment.amount;
      }
    }
  }
  return amounts;
}

// Associate RegistrationPayment with the RegistrationInfo entry that logged
// the user's purchase.
//
// This allows us to determine whether a purchase has been paid for yet.
function associate_payment_with_purchase(reg, payment, field, option) {
  for(var info in reg.RegistrationInfos) {
    info = reg.RegistrationInfos[info];
    if (info.field == field) {
      if (info.value != option) {
        console.warn("Associating payment for " + field + " choice " +
                     info.value + " but expected choice " + option);
      }
      return info.setRegistrationPayment(payment);
    }
  };
  console.warn(": Couldn't associate payment with field " + field + " choice " +
               option + ": value is not set in this registration");
  return Promise.resolve();
}

function get_payment_for_purchase(reg, field) {
  for (var info_id in reg.RegistrationInfos) {
    var info = reg.RegistrationInfos[info_id];
    if (info.field == field) {
      return info.RegistrationPayment;
    }
  }
  return null;
}

module.exports = function(sequelize, DataTypes) {
  var Registration = sequelize.define("Registration", {
    is_public: DataTypes.BOOLEAN,
    badge_printed: DataTypes.BOOLEAN,
    receipt_sent: DataTypes.BOOLEAN,
    regfee: DataTypes.DECIMAL(10,2),
    currency: DataTypes.STRING(10),
  }, {
    classMethods: {
      associate: function(models) {
        Registration.belongsTo(models.User);
        Registration.hasMany(models.RegistrationPayment);
        Registration.hasMany(models.RegistrationInfo);
      }
    },
    instanceMethods: {
      associate_payment_with_purchase: function(payment, field, option) {
        associate_payment_with_purchase(this, payment, field, option);
      },
      get_payment_for_purchase: function(field) {
        return get_payment_for_purchase(this, field);
      }
    },
    getterMethods: {
      display_id: function() {
        return this.id;
      },

      paid_amounts: function() {
        return get_amounts(this);
      },
      paid: function() {
        return get_amount_string(this.paid_amounts);
      },
      paid_paypal: function() {
        return get_amount_string(get_amounts(this, 'paypal'));
      },
      outstanding_onsite: function() {
        var amounts = {};
        for(var payment in this.RegistrationPayments) {
          payment = this.RegistrationPayments[payment];
          if(!payment.paid && payment.type == 'onsite') {
            if(payment.currency in amounts) {
              amounts[payment.currency] += payment.amount;
            } else {
              amounts[payment.currency] = payment.amount;
            }
          }
        }
        return get_amount_string(amounts);
      },
      has_outstanding_onsite: function() {
        for(var payment in this.RegistrationPayments) {
          payment = this.RegistrationPayments[payment];
          if(!payment.paid && payment.type == 'onsite') {
            return true;
          }
        }
        return false;
      },
      has_confirmed_payment: function() {
        for(var payment in this.RegistrationPayments) {
          console.log('payment:', payment);
          payment = this.RegistrationPayments[payment];
          if(payment.paid) {
            return true;
          }
        }
        return false;
      },
    }
  });

  return Registration;
};


text:
package org.apache.commons.math3.random;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;

import org.apache.commons.math3.TestUtils;
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.integration.BaseAbstractUnivariateIntegrator;
import org.apache.commons.math3.analysis.integration.IterativeLegendreGaussIntegrator;
import org.apache.commons.math3.distribution.AbstractRealDistribution;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.distribution.RealDistribution;
import org.apache.commons.math3.distribution.RealDistributionAbstractTest;
import org.apache.commons.math3.distribution.UniformRealDistribution;
import org.apache.commons.math3.exception.NullArgumentException;
import org.apache.commons.math3.exception.OutOfRangeException;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * Test cases for the EmpiricalDistribution class
 *
 * @version $Id: EmpiricalDistributionTest.java 1461172 2013-03-26 15:11:18Z luc $
 */

public final class EmpiricalDistributionTest extends RealDistributionAbstractTest {

    protected EmpiricalDistribution empiricalDistribution = null;
    protected EmpiricalDistribution empiricalDistribution2 = null;
    protected File file = null;
    protected URL url = null;
    protected double[] dataArray = null;
    protected final int n = 10000;

    @Before
    public void setUp() {
        super.setUp();
        empiricalDistribution = new EmpiricalDistribution(100);
//         empiricalDistribution = new EmpiricalDistribution(100, new RandomDataImpl()); // XXX Deprecated API
        url = getClass().getResource("testData.txt");
        final ArrayList<Double> list = new ArrayList<Double>();
        try {
            empiricalDistribution2 = new EmpiricalDistribution(100);
//             empiricalDistribution2 = new EmpiricalDistribution(100, new RandomDataImpl()); // XXX Deprecated API
            BufferedReader in =
                new BufferedReader(new InputStreamReader(
                        url.openStream()));
            String str = null;
            while ((str = in.readLine()) != null) {
                list.add(Double.valueOf(str));
            }
            in.close();
            in = null;
        } catch (IOException ex) {
            Assert.fail("IOException " + ex);
        }

        dataArray = new double[list.size()];
        int i = 0;
        for (Double data : list) {
            dataArray[i] = data.doubleValue();
            i++;
        }
    }

    /**
     * Test EmpiricalDistrbution.load() using sample data file.

     * Check that the sampleCount, mu and sigma match data in
     * the sample data file. Also verify that load is idempotent.
     */
    @Test
    public void testLoad() throws Exception {
        // Load from a URL
        empiricalDistribution.load(url);
        checkDistribution();

        // Load again from a file (also verifies idempotency of load)
        File file = new File(url.toURI());
        empiricalDistribution.load(file);
        checkDistribution();
    }

    private void checkDistribution() {
        // testData File has 10000 values, with mean ~ 5.0, std dev ~ 1
        // Make sure that loaded distribution matches this
        Assert.assertEquals(empiricalDistribution.getSampleStats().getN(),1000,10E-7);
        //TODO: replace with statistical tests
        Assert.assertEquals(empiricalDistribution.getSampleStats().getMean(),
                5.069831575018909,10E-7);
        Assert.assertEquals(empiricalDistribution.getSampleStats().getStandardDeviation(),
                1.0173699343977738,10E-7);
    }

    /**
     * Test EmpiricalDistrbution.load(double[]) using data taken from
     * sample data file.

     * Check that the sampleCount, mu and sigma match data in
     * the sample data file.
     */
    @Test
    public void testDoubleLoad() throws Exception {
        empiricalDistribution2.load(dataArray);
        // testData File has 10000 values, with mean ~ 5.0, std dev ~ 1
        // Make sure that loaded distribution matches this
        Assert.assertEquals(empiricalDistribution2.getSampleStats().getN(),1000,10E-7);
        //TODO: replace with statistical tests
        Assert.assertEquals(empiricalDistribution2.getSampleStats().getMean(),
                5.069831575018909,10E-7);
        Assert.assertEquals(empiricalDistribution2.getSampleStats().getStandardDeviation(),
                1.0173699343977738,10E-7);

        double[] bounds = empiricalDistribution2.getGeneratorUpperBounds();
        Assert.assertEquals(bounds.length, 100);
        Assert.assertEquals(bounds[99], 1.0, 10e-12);

    }

    /**
      * Generate 1000 random values and make sure they look OK.

      * Note that there is a non-zero (but very small) probability that
      * these tests will fail even if the code is working as designed.
      */
    @Test
    public void testNext() throws Exception {
        tstGen(0.1);
        tstDoubleGen(0.1);
    }

    /**
      * Make sure exception thrown if digest getNext is attempted
      * before loading empiricalDistribution.
     */
    @Test
    public void testNexFail() {
        try {
            empiricalDistribution.getNextValue();
            empiricalDistribution2.getNextValue();
            Assert.fail("Expecting IllegalStateException");
        } catch (IllegalStateException ex) {
            // expected
        }
    }

    /**
     * Make sure we can handle a grid size that is too fine
     */
    @Test
    public void testGridTooFine() throws Exception {
        empiricalDistribution = new EmpiricalDistribution(1001);
        tstGen(0.1);
        empiricalDistribution2 = new EmpiricalDistribution(1001);
        tstDoubleGen(0.1);
    }

    /**
     * How about too fat?
     */
    @Test
    public void testGridTooFat() throws Exception {
        empiricalDistribution = new EmpiricalDistribution(1);
        tstGen(5); // ridiculous tolerance; but ridiculous grid size
                   // really just checking to make sure we do not bomb
        empiricalDistribution2 = new EmpiricalDistribution(1);
        tstDoubleGen(5);
    }

    /**
     * Test bin index overflow problem (BZ 36450)
     */
    @Test
    public void testBinIndexOverflow() throws Exception {
        double[] x = new double[] {9474.94326071674, 2080107.8865462579};
        new EmpiricalDistribution().load(x);
    }

    @Test
    public void testSerialization() {
        // Empty
        EmpiricalDistribution dist = new EmpiricalDistribution();
        EmpiricalDistribution dist2 = (EmpiricalDistribution) TestUtils.serializeAndRecover(dist);
        verifySame(dist, dist2);

        // Loaded
        empiricalDistribution2.load(dataArray);
        dist2 = (EmpiricalDistribution) TestUtils.serializeAndRecover(empiricalDistribution2);
        verifySame(empiricalDistribution2, dist2);
    }

    @Test(expected=NullArgumentException.class)
    public void testLoadNullDoubleArray() {
       new EmpiricalDistribution().load((double[]) null);
    }

    @Test(expected=NullArgumentException.class)
    public void testLoadNullURL() throws Exception {
        new EmpiricalDistribution().load((URL) null);
    }

    @Test(expected=NullArgumentException.class)
    public void testLoadNullFile() throws Exception {
        new EmpiricalDistribution().load((File) null);
    }

    /**
     * MATH-298
     */
    @Test
    public void testGetBinUpperBounds() {
        double[] testData = {0, 1, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10};
        EmpiricalDistribution dist = new EmpiricalDistribution(5);
        dist.load(testData);
        double[] expectedBinUpperBounds = {2, 4, 6, 8, 10};
        double[] expectedGeneratorUpperBounds = {4d/13d, 7d/13d, 9d/13d, 11d/13d, 1};
        double tol = 10E-12;
        TestUtils.assertEquals(expectedBinUpperBounds, dist.getUpperBounds(), tol);
        TestUtils.assertEquals(expectedGeneratorUpperBounds, dist.getGeneratorUpperBounds(), tol);
    }

    @Test
    public void testGeneratorConfig() {
        double[] testData = {0, 1, 2, 3, 4};
        RandomGenerator generator = new RandomAdaptorTest.ConstantGenerator(0.5);

        EmpiricalDistribution dist = new EmpiricalDistribution(5, generator);
        dist.load(testData);
        for (int i = 0; i < 5; i++) {
            Assert.assertEquals(2.0, dist.getNextValue(), 0d);
        }

        // Verify no NPE with null generator argument
        dist = new EmpiricalDistribution(5, (RandomGenerator) null);
        dist.load(testData);
        dist.getNextValue();
    }

    @Test
    public void testReSeed() throws Exception {
        empiricalDistribution.load(url);
        empiricalDistribution.reSeed(100);
        final double [] values = new double[10];
        for (int i = 0; i < 10; i++) {
            values[i] = empiricalDistribution.getNextValue();
        }
        empiricalDistribution.reSeed(100);
        for (int i = 0; i < 10; i++) {
            Assert.assertEquals(values[i],empiricalDistribution.getNextValue(), 0d);
        }
    }

    private void verifySame(EmpiricalDistribution d1, EmpiricalDistribution d2) {
        Assert.assertEquals(d1.isLoaded(), d2.isLoaded());
        Assert.assertEquals(d1.getBinCount(), d2.getBinCount());
        Assert.assertEquals(d1.getSampleStats(), d2.getSampleStats());
        if (d1.isLoaded()) {
            for (int i = 0;  i < d1.getUpperBounds().length; i++) {
                Assert.assertEquals(d1.getUpperBounds()[i], d2.getUpperBounds()[i], 0);
            }
            Assert.assertEquals(d1.getBinStats(), d2.getBinStats());
        }
    }

    private void tstGen(double tolerance)throws Exception {
        empiricalDistribution.load(url);
        empiricalDistribution.reSeed(1000);
        SummaryStatistics stats = new SummaryStatistics();
        for (int i = 1; i < 1000; i++) {
            stats.addValue(empiricalDistribution.getNextValue());
        }
        Assert.assertEquals("mean", 5.069831575018909, stats.getMean(),tolerance);
        Assert.assertEquals("std dev", 1.0173699343977738, stats.getStandardDeviation(),tolerance);
    }

    private void tstDoubleGen(double tolerance)throws Exception {
        empiricalDistribution2.load(dataArray);
        empiricalDistribution2.reSeed(1000);
        SummaryStatistics stats = new SummaryStatistics();
        for (int i = 1; i < 1000; i++) {
            stats.addValue(empiricalDistribution2.getNextValue());
        }
        Assert.assertEquals("mean", 5.069831575018909, stats.getMean(), tolerance);
        Assert.assertEquals("std dev", 1.0173699343977738, stats.getStandardDeviation(), tolerance);
    }

    //  Setup for distribution tests

    @Override
    public RealDistribution makeDistribution() {
        // Create a uniform distribution on [0, 10,000]
        final double[] sourceData = new double[n + 1];
        for (int i = 0; i < n + 1; i++) {
            sourceData[i] = i;
        }
        EmpiricalDistribution dist = new EmpiricalDistribution();
        dist.load(sourceData);
        return dist;
    }

    /** Uniform bin mass = 10/10001 == mass of all but the first bin */
    private final double binMass = 10d / (double) (n + 1);

    /** Mass of first bin = 11/10001 */
    private final double firstBinMass = 11d / (double) (n + 1);

    @Override
    public double[] makeCumulativeTestPoints() {
       final double[] testPoints = new double[] {9, 10, 15, 1000, 5004, 9999};
       return testPoints;
    }

    @Override
    public double[] makeCumulativeTestValues() {
        /*
         * Bins should be [0, 10], (10, 20], ..., (9990, 10000]
         * Kernels should be N(4.5, 3.02765), N(14.5, 3.02765)...
         * Each bin should have mass 10/10000 = .001
         */
        final double[] testPoints = getCumulativeTestPoints();
        final double[] cumValues = new double[testPoints.length];
        final EmpiricalDistribution empiricalDistribution = (EmpiricalDistribution) makeDistribution();
        final double[] binBounds = empiricalDistribution.getUpperBounds();
        for (int i = 0; i < testPoints.length; i++) {
            final int bin = findBin(testPoints[i]);
            final double lower = bin == 0 ? empiricalDistribution.getSupportLowerBound() :
                binBounds[bin - 1];
            final double upper = binBounds[bin];
            // Compute bMinus = sum or mass of bins below the bin containing the point
            // First bin has mass 11 / 10000, the rest have mass 10 / 10000.
            final double bMinus = bin == 0 ? 0 : (bin - 1) * binMass + firstBinMass;
            final RealDistribution kernel = findKernel(lower, upper);
            final double withinBinKernelMass = kernel.cumulativeProbability(lower, upper);
            final double kernelCum = kernel.cumulativeProbability(lower, testPoints[i]);
            cumValues[i] = bMinus + (bin == 0 ? firstBinMass : binMass) * kernelCum/withinBinKernelMass;
        }
        return cumValues;
    }

    @Override
    public double[] makeDensityTestValues() {
        final double[] testPoints = getCumulativeTestPoints();
        final double[] densityValues = new double[testPoints.length];
        final EmpiricalDistribution empiricalDistribution = (EmpiricalDistribution) makeDistribution();
        final double[] binBounds = empiricalDistribution.getUpperBounds();
        for (int i = 0; i < testPoints.length; i++) {
            final int bin = findBin(testPoints[i]);
            final double lower = bin == 0 ? empiricalDistribution.getSupportLowerBound() :
                binBounds[bin - 1];
            final double upper = binBounds[bin];
            final RealDistribution kernel = findKernel(lower, upper);
            final double withinBinKernelMass = kernel.cumulativeProbability(lower, upper);
            final double density = kernel.density(testPoints[i]);
            densityValues[i] = density * (bin == 0 ? firstBinMass : binMass) / withinBinKernelMass;
        }
        return densityValues;
    }

    /**
     * Modify test integration bounds from the default. Because the distribution
     * has discontinuities at bin boundaries, integrals spanning multiple bins
     * will face convergence problems.  Only test within-bin integrals and spans
     * across no more than 3 bin boundaries.
     */
    @Override
    @Test
    public void testDensityIntegrals() {
        final RealDistribution distribution = makeDistribution();
        final double tol = 1.0e-9;
        final BaseAbstractUnivariateIntegrator integrator =
            new IterativeLegendreGaussIntegrator(5, 1.0e-12, 1.0e-10);
        final UnivariateFunction d = new UnivariateFunction() {
            public double value(double x) {
                return distribution.density(x);
            }
        };
        final double[] lower = {0, 5, 1000, 5001, 9995};
        final double[] upper = {5, 12, 1030, 5010, 10000};
        for (int i = 1; i < 5; i++) {
            Assert.assertEquals(
                    distribution.cumulativeProbability(
                            lower[i], upper[i]),
                            integrator.integrate(
                                    1000000, // Triangle integrals are very slow to converge
                                    d, lower[i], upper[i]), tol);
        }
    }

    /**
     * Find the bin that x belongs (relative to {@link #makeDistribution()}).
     */
    private int findBin(double x) {
        // Number of bins below x should be trunc(x/10)
        final double nMinus = Math.floor(x / 10);
        final int bin =  (int) Math.round(nMinus);
        // If x falls on a bin boundary, it is in the lower bin
        return Math.floor(x / 10) == x / 10 ? bin - 1 : bin;
    }

    /**
     * Find the within-bin kernel for the bin with lower bound lower
     * and upper bound upper. All bins other than the first contain 10 points
     * exclusive of the lower bound and are centered at (lower + upper + 1) / 2.
     * The first bin includes its lower bound, 0, so has different mean and
     * standard deviation.
     */
    private RealDistribution findKernel(double lower, double upper) {
        if (lower < 1) {
            return new NormalDistribution(5d, 3.3166247903554);
        } else {
            return new NormalDistribution((upper + lower + 1) / 2d, 3.0276503540974917);
        }
    }

    @Test
    public void testKernelOverrideConstant() {
        final EmpiricalDistribution dist = new ConstantKernelEmpiricalDistribution(5);
        final double[] data = {1d,2d,3d, 4d,5d,6d, 7d,8d,9d, 10d,11d,12d, 13d,14d,15d};
        dist.load(data);
        // Bin masses concentrated on 2, 5, 8, 11, 14 <- effectively discrete uniform distribution over these
        double[] values = {2d, 5d, 8d, 11d, 14d};
        for (int i = 0; i < 20; i++) {
            Assert.assertTrue(Arrays.binarySearch(values, dist.sample()) >= 0);
        }
        final double tol = 10E-12;
        Assert.assertEquals(0.0, dist.cumulativeProbability(1), tol);
        Assert.assertEquals(0.2, dist.cumulativeProbability(2), tol);
        Assert.assertEquals(0.6, dist.cumulativeProbability(10), tol);
        Assert.assertEquals(0.8, dist.cumulativeProbability(12), tol);
        Assert.assertEquals(0.8, dist.cumulativeProbability(13), tol);
        Assert.assertEquals(1.0, dist.cumulativeProbability(15), tol);

        Assert.assertEquals(2.0, dist.inverseCumulativeProbability(0.1), tol);
        Assert.assertEquals(2.0, dist.inverseCumulativeProbability(0.2), tol);
        Assert.assertEquals(5.0, dist.inverseCumulativeProbability(0.3), tol);
        Assert.assertEquals(5.0, dist.inverseCumulativeProbability(0.4), tol);
        Assert.assertEquals(8.0, dist.inverseCumulativeProbability(0.5), tol);
        Assert.assertEquals(8.0, dist.inverseCumulativeProbability(0.6), tol);
    }

    @Test
    public void testKernelOverrideUniform() {
        final EmpiricalDistribution dist = new UniformKernelEmpiricalDistribution(5);
        final double[] data = {1d,2d,3d, 4d,5d,6d, 7d,8d,9d, 10d,11d,12d, 13d,14d,15d};
        dist.load(data);
        // Kernels are uniform distributions on [1,3], [4,6], [7,9], [10,12], [13,15]
        final double bounds[] = {3d, 6d, 9d, 12d};
        final double tol = 10E-12;
        for (int i = 0; i < 20; i++) {
            final double v = dist.sample();
            // Make sure v is not in the excluded range between bins - that is (bounds[i], bounds[i] + 1)
            for (int j = 0; j < bounds.length; j++) {
                Assert.assertFalse(v > bounds[j] + tol && v < bounds[j] + 1 - tol);
            }
        }
        Assert.assertEquals(0.0, dist.cumulativeProbability(1), tol);
        Assert.assertEquals(0.1, dist.cumulativeProbability(2), tol);
        Assert.assertEquals(0.6, dist.cumulativeProbability(10), tol);
        Assert.assertEquals(0.8, dist.cumulativeProbability(12), tol);
        Assert.assertEquals(0.8, dist.cumulativeProbability(13), tol);
        Assert.assertEquals(1.0, dist.cumulativeProbability(15), tol);

        Assert.assertEquals(2.0, dist.inverseCumulativeProbability(0.1), tol);
        Assert.assertEquals(3.0, dist.inverseCumulativeProbability(0.2), tol);
        Assert.assertEquals(5.0, dist.inverseCumulativeProbability(0.3), tol);
        Assert.assertEquals(6.0, dist.inverseCumulativeProbability(0.4), tol);
        Assert.assertEquals(8.0, dist.inverseCumulativeProbability(0.5), tol);
        Assert.assertEquals(9.0, dist.inverseCumulativeProbability(0.6), tol);
    }

    /**
     * Empirical distribution using a constant smoothing kernel.
     */
    private class ConstantKernelEmpiricalDistribution extends EmpiricalDistribution {
        private static final long serialVersionUID = 1L;
        public ConstantKernelEmpiricalDistribution(int i) {
            super(i);
        }
        // Use constant distribution equal to bin mean within bin
        protected RealDistribution getKernel(SummaryStatistics bStats) {
            return new ConstantDistribution(bStats.getMean());
        }
    }

    /**
     * Empirical distribution using a uniform smoothing kernel.
     */
    private class UniformKernelEmpiricalDistribution extends EmpiricalDistribution {
        public UniformKernelEmpiricalDistribution(int i) {
            super(i);
        }
        protected RealDistribution getKernel(SummaryStatistics bStats) {
            return new UniformRealDistribution(randomData.getRandomGenerator(), bStats.getMin(), bStats.getMax(),
                    UniformRealDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
        }
    }

    /**
     * Distribution that takes just one value.
     */
    private class ConstantDistribution extends AbstractRealDistribution {
        private static final long serialVersionUID = 1L;

        /** Singleton value in the sample space */
        private final double c;

        public ConstantDistribution(double c) {
            this.c = c;
        }

        public double density(double x) {
            return 0;
        }

        public double cumulativeProbability(double x) {
            return x < c ? 0 : 1;
        }

        @Override
        public double inverseCumulativeProbability(double p) {
            if (p < 0.0 || p > 1.0) {
                throw new OutOfRangeException(p, 0, 1);
            }
            return c;
        }

        public double getNumericalMean() {
            return c;
        }

        public double getNumericalVariance() {
            return 0;
        }

        public double getSupportLowerBound() {
            return c;
        }

        public double getSupportUpperBound() {
            return c;
        }

        public boolean isSupportLowerBoundInclusive() {
            return false;
        }

        public boolean isSupportUpperBoundInclusive() {
            return true;
        }

        public boolean isSupportConnected() {
            return true;
        }

        @Override
        public double sample() {
            return c;
        }

    }
}


text:
<Type Name="ShaderParameterFloatFromTo" FullName="Urho.Actions.ShaderParameterFloatFromTo">
  <TypeSignature Language="C#" Value="public class ShaderParameterFloatFromTo : Urho.Actions.ShaderParameterFromTo<float>" />
  <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ShaderParameterFloatFromTo extends Urho.Actions.ShaderParameterFromTo`1<float32>" />
  <AssemblyInfo>
    <AssemblyName>Urho</AssemblyName>
    <AssemblyVersion>1.0.0.0</AssemblyVersion>
  </AssemblyInfo>
  <Base>
    <BaseTypeName>Urho.Actions.ShaderParameterFromTo<System.Single></BaseTypeName>
    <BaseTypeArguments>
      <BaseTypeArgument TypeParamName="TShaderParamType">System.Single</BaseTypeArgument>
    </BaseTypeArguments>
  </Base>
  <Interfaces />
  <Docs>
    To be added.
    <remarks>To be added.</remarks>
  </Docs>
  <Members>
    <Member MemberName=".ctor">
      <MemberSignature Language="C#" Value="public ShaderParameterFloatFromTo (string parameter, float fromValue, float toValue, float duration, Urho.Material material = null);" />
      <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string parameter, float32 fromValue, float32 toValue, float32 duration, class Urho.Material material) cil managed" />
      <MemberType>Constructor</MemberType>
      <AssemblyInfo>
        <AssemblyVersion>1.0.0.0</AssemblyVersion>
      </AssemblyInfo>
      <Parameters>
        <Parameter Name="parameter" Type="System.String" />
        <Parameter Name="fromValue" Type="System.Single" />
        <Parameter Name="toValue" Type="System.Single" />
        <Parameter Name="duration" Type="System.Single" />
        <Parameter Name="material" Type="Urho.Material" />
      </Parameters>
      <Docs>
        <param name="parameter">To be added.</param>
        <param name="fromValue">To be added.</param>
        <param name="toValue">To be added.</param>
        <param name="duration">To be added.</param>
        <param name="material">To be added.</param>
        To be added.
        <remarks>To be added.</remarks>
      </Docs>
    </Member>
  </Members>
</Type>


text:
using TransactionalNodeService.Proxy.Universal.Collections;
using TransactionalNodeService.Proxy.Universal.Collections.NodeContainers;

namespace TransactionalNodeService.Proxy.Universal
{
    internal interface INodeManager
    {
        void Load(ConnectionSet connectionSet);
        void Clear();
        void UnionWith(NodeSet nodes);
    }
}


text:
using System;
using System.Windows.Forms;

namespace AldursLab.WurmAssistant3.Areas.Triggers.TriggersManager
{
    public partial class SimpleConditionTriggerBaseConfig : UserControl, ITriggerConfig
    {
        private readonly SimpleConditionTriggerBase _simpleConditionTriggerBase;

        private readonly bool initComplete = false;
        public SimpleConditionTriggerBaseConfig(SimpleConditionTriggerBase simpleConditionTriggerBase)
        {
            _simpleConditionTriggerBase = simpleConditionTriggerBase;
            InitializeComponent();
            ConditionTbox.Text = simpleConditionTriggerBase.Condition;
            DescLabel.Text = simpleConditionTriggerBase.ConditionHelp;
            checkBoxMatchEveryLine.Checked = _simpleConditionTriggerBase.MatchEveryLine;
            sourceTbox.Text = _simpleConditionTriggerBase.Source;
            SourceHelpLabel.Text = simpleConditionTriggerBase.SourceHelp;
            UpdateControls();
            initComplete = true;
        }

        public UserControl ControlHandle { get { return this; } }

        private void ConditionTbox_TextChanged(object sender, EventArgs e)
        {
            if (initComplete) _simpleConditionTriggerBase.Condition = ConditionTbox.Text;
        }

        private void sourceTbox_TextChanged(object sender, EventArgs e)
        {
            if (initComplete) _simpleConditionTriggerBase.Source = sourceTbox.Text;
        }

        private void checkBoxMatchEveryLine_CheckedChanged(object sender, EventArgs e)
        {
            if (initComplete)
            {
                _simpleConditionTriggerBase.MatchEveryLine = checkBoxMatchEveryLine.Checked;
                UpdateControls();
            }
        }

        private void UpdateControls()
        {
            ConditionTbox.Enabled = !checkBoxMatchEveryLine.Checked;
        }
    }
}


text:
<?php
/**
 * @author Yann-Eric <yann-eric@live.fr>
 */
namespace DW\UserBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\ManyToMany;
use Doctrine\ORM\Mapping\JoinTable;

/**
 * DW\UserBundle\Entity\User
 *
 * @ORM\Table(name="dw_user")
 * @ORM\Entity(repositoryClass="DW\UserBundle\Entity\UserRepository")
 */
class User
{

    /** @ManyToMany(targetEntity="Role", cascade={"persist"})
     *  @JoinTable(name="dw_user_role")
     */
    private $roles;

     public function getRoles() {
        return $this->roles;
    }

     public function getStringRoles() {

        $string_roles = '';
         foreach ($this->roles as $key => $value) {
             $string_roles .= $value->getName().' / ';

         }
         return $string_roles;

    }

    public function addRole($role) {
        $this->roles[] = $role;
    }

    public function removeRole($role) {
       // Not implemented here

    }

    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string $username
     *
     * @ORM\Column(name="username", type="string", length=255)
     */
    private $username;

    /**
     * @var string $email
     *
     * @ORM\Column(name="email", type="string", length=255, nullable=true, unique=true)
     */
    private $email;

    /**
     * @var string $password
     *
     * @ORM\Column(name="password", type="string", length=255)
     */
    private $password;

    /**
     * @var string $encrypted_password
     *
     * @ORM\Column(name="encrypted_password", type="string", length=255)
     */
    private $encrypted_password;

    /**
     * @var boolean $enabled
     *
     * @ORM\Column(name="enabled", type="boolean", nullable=true)
     */
    private $enabled;

    /**
     * @var boolean $accountExpired
     *
     * @ORM\Column(name="accountExpired", type="boolean", nullable=true)
     */
    private $accountExpired;

    /**
     * @var boolean $accountLocked
     *
     * @ORM\Column(name="accountLocked", type="boolean", nullable=true)
     */
    private $accountLocked;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set username
     *
     * @param string $username
     * @return User
     */
    public function setUsername($username)
    {
        $this->username = $username;

        return $this;
    }

    /**
     * Get username
     *
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * Set email
     *
     * @param string $email
     * @return User
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

    /**
     * Get email
     *
     * @return string
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * Set password
     *
     * @param string $password
     * @return User
     */
    public function setPassword($password)
    {
        $this->password = $password;
        $this->setEncryptedPassword($password);

        return $this;
    }

    /**
     * Get password
     *
     * @return string
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * Set encrypted_password
     *
     * @param string $encrypted_password
     * @return User
     */
    public function setEncryptedPassword($password)
    {
        $this->encrypted_password = sha1($password);

        return $this;
    }

    /**
     * Get encrypted_password
     *
     * @return string
     */
    public function getEncryptedPassword()
    {
        return $this->encrypted_password;
    }

    /**
     * Set enabled
     *
     * @param boolean $enabled
     * @return User
     */
    public function setEnabled($enabled)
    {
        $this->enabled = $enabled;

        return $this;
    }

    /**
     * Get enabled
     *
     * @return boolean
     */
    public function getEnabled()
    {
        return $this->enabled;
    }

    /**
     * Set accountExpired
     *
     * @param boolean $accountExpired
     * @return User
     */
    public function setAccountExpired($accountExpired)
    {
        $this->accountExpired = $accountExpired;

        return $this;
    }

    /**
     * Get accountExpired
     *
     * @return boolean
     */
    public function getAccountExpired()
    {
        return $this->accountExpired;
    }

    /**
     * Set accountLocked
     *
     * @param boolean $accountLocked
     * @return User
     */
    public function setAccountLocked($accountLocked)
    {
        $this->accountLocked = $accountLocked;

        return $this;
    }

    /**
     * Get accountLocked
     *
     * @return boolean
     */
    public function getAccountLocked()
    {
        return $this->accountLocked;
    }

}


text:
#include <jni.h>
/* Header for jnetpcap_utils utility methods */

#ifndef _Included_org_jnetpcap_WinPcapExtensions
#define _Included_org_jnetpcap_WinPcapExtensions
#ifdef __cplusplus
extern "C" {
#define	EXTERN extern "C"
#endif

extern	jclass winPcapClass;

// Prototypes

#ifdef __cplusplus
}
#endif
#endif


text:
			Posted on

			by


text:
title: How to use the crypto module
date: '2011-08-26T10:08:50.000Z'
tags:
  - core
  - crypto
difficulty: 3
layout: knowledge-post.hbs
---

The [crypto](https://nodejs.org/api/crypto.html) module is a wrapper for [OpenSSL](http://en.wikipedia.org/wiki/Openssl) cryptographic functions. It supports calculating hashes, authentication with HMAC, ciphers, and more!

The crypto module is mostly useful as a tool for implementing [cryptographic protocols](http://en.wikipedia.org/wiki/Cryptographic_protocol) such as [TLS](http://en.wikipedia.org/wiki/Transport_Layer_Security) and [https](http://en.wikipedia.org/wiki/Https). For most users, Node's built-in [tls module](https://nodejs.org/api/tls.html) and [https module](https://nodejs.org/api/https.html) should more than suffice. However, for the user that only wants to use small parts of what's needed for full-scale cryptography or is crazy/desperate enough to implement a protocol using OpenSSL and Node: Read on.

## Hashes

### What Is A Hash?

A hash is a fixed-length string of bits that is procedurally and deterministially generated from some arbitrary block of source data. Some important properties of these hashes (the type useful for cryptography) include:

* **Fixed length:** This means that, no matter what the input, the length of the hash is the same. For example, SHA-256 hashes are always 256 bits long whether the input data is a few bits or a few gigabytes.

* **Deterministic:** For the same input, you should expect to be able to calculate exactly the same hash. This makes hashes useful for checksums.

* **Collision-Resistant:** A collision is when the same hash is generated for two different input blocks of data. Hash algorithms are designed to be extremely unlikely to have collisions -- just how unlikely is a property of the hash algorithm. The importance of this property depends on the use case.

* **Unidirectional:** A good hash algorithm is easy to apply, but hard to undo. This means that, given a hash, there isn't any reasonable way to find out what the original piece of data was.

### Hash Algorithms That Work With Crypto

The hashes that work with crypto are dependent on what your version of OpenSSL supports. If you have a new enough version of OpenSSL, you can get a list of hash types your OpenSSL supports by typing `openssl list-message-digest-algorithms` into the command line. For older versions, simply type `openssl list-message-digest-commands` instead!

One of the most common hash algorithms is [SHA-256](https://en.wikipedia.org/wiki/SHA-2). Older popular types like **[SHA-1](http://en.wikipedia.org/wiki/Sha1) or [MD5](https://en.wikipedia.org/wiki/MD5#Security) are not secure any more** and should not be used.

### How To Calculate Hashes with Crypto

Crypto has a method called `createHash` which allows you to calculate a hash. Its only argument is a string representing the hash This example finds the SHA-256 hash for the string, "Man oh man do I love node!":

```js
require("crypto")
  .createHash("sha256")
  .update("Man oh man do I love node!")
  .digest("hex");
```

The `update` method is used to push data to later be turned into a hash with the `digest` method. `update` can be invoked multiple times to ingest streaming data, such as buffers from a file read stream. The argument for `digest` represents the output format, and may either be "binary", "hex" or "base64". It defaults to binary.

## HMAC

HMAC stands for Hash-based Message Authentication Code, and is a process for applying a hash algorithm to both data and a secret key that results in a single final hash. Its use is similar to that of a vanilla hash, but also allows to check the *authenticity* of data as *well* as the integrity of said data (as you can using SHA-256 checksums).

The API for hmacs is very similar to that of `createHash`, except that the method is called `createHmac` and it takes a key as a second argument:

```js
require("crypto").createHmac("sha256", "password")
  .update("If you love node so much why don't you marry it?")
  .digest("hex");
```

The resulting SHA-256 hash is unique to both the input data and the key.

## Ciphers

Ciphers allow you to encode and decode messages given a password.

### Cipher Algorithms That Work With Crypto

Like crypto's hash algorithms, the cyphers that work with crypto are dependent on what your version of OpenSSL supports. You can get a list of hash types your OpenSSL supports by typing `openssl list-cipher-commands` into the command line for older versions, or `openssl list-cipher-algorithms` for newer versions of OpenSSL. OpenSSL supports *many* ciphers; A good and popular one is [AES_256](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard).

### How To Use Cipher Algorithms with Crypto:

Crypto comes with two methods for ciphering and deciphering:

* `crypto.createCipheriv(algorithm, key, iv)`
* `crypto.createDecipheriv(algorithm, key, iv)`

Both of these methods take arguments similarly to `createHmac`. They also both have analogous `update` functions. However, each use of `update` returns a chunk of the encoded/decoded data instead of requiring one to call `digest` to get the result. Moreover, after encoding (or decoding) your data, you will likely have to call the `final` method to get the last chunk of encoded information.

Another important addition in the cipher method is of the `iv` or [initialization vector](https://en.wikipedia.org/wiki/Initialization_vector). Initialization vectors should be unpredictable and unique, typically required to be random or pseudorandom. Randomization is crucial for encryption schemes to achieve semantic security, a property whereby repeated usage of the scheme under the same key does not allow an attacker to infer relationships between segments of the encrypted message.

Here's an example, slightly less trivial than previous examples, that uses crypto and [yargs](https://github.com/yargs/yargs) to encode and decode messages from the command line:

```js
#!/usr/bin/env node

const crypto = require('crypto'),
    argv = require("yargs").argv,
    resizedIV = Buffer.allocUnsafe(16),
    iv = crypto
      .createHash("sha256")
      .update("myHashedIV")
      .digest();

iv.copy(resizedIV);

if (argv.e && argv.key) {
    const key = crypto
        .createHash("sha256")
        .update(argv.key)
        .digest(),
        cipher = crypto.createCipheriv("aes256", key, resizedIV),
        msg = [];

    argv._.forEach( function (phrase) {
        msg.push(cipher.update(phrase, "binary", "hex"));
    });

    msg.push(cipher.final("hex"));
    console.log(msg.join(""));

} else if (argv.d && argv.key) {
    const key = crypto
        .createHash("sha256")
        .update(argv.key)
        .digest(),
        decipher = crypto.createDecipheriv("aes256", key, resizedIV),
        msg = [];

    argv._.forEach( function (phrase) {
        msg.push(decipher.update(phrase, "hex", "binary"));
    });

    msg.push(decipher.final("binary"));
    console.log(msg.join(""));
}
```

NODE PRO TIP: The `crypto.createCipheriv()` and `crypto.createDecipheriv()` methods do not take a password, rather a `key` and an `iv` which are combined together to form a random password. The size of the `key` and `iv` depends on the choosen algorithm. A reference to common algorithms and their `key` and `iv` size is given below:

| Algorithm      | Key                | iv                 |
| -------------  |:-----------------: | :----------------: |
| aes128         | 16 byte (128 bits) | 16 byte (128 bits) |
| aes-128-cbc    | 16 byte (128 bits) | 16 byte (128 bits) |
| aes192         | 24 byte (192 bits) | 16 byte (128 bits) |
| aes256         | 32 byte (256 bits) | 16 byte (128 bits) |

In the code above The user entered `key` is hashed using `SHA-256 encryption` which produces a 32 byte buffer by default, this buffered key is then used as the [cryptographic key](https://en.wikipedia.org/wiki/Key_(cryptography)) in the `crypto.createCipheriv()` and `crypto.createDecipheriv()` methods. The `iv` is also hashed with `SHA-256 encryption` and is 32 byte in size but all AES (CBC mode and CFB mode) take `iv` of exactly 16 byte (128 bits) therefor another Buffer `resizedIV` is used which contains the first 16 byte of orignal 32 byte `iv`.

Using this script to encode a message looks like this:

```bash
$ node ./secretmsg.js -e --key="popcorn" "My treasure is buried behind Carl's Jr. on Telegraph."
c8c78895fd91da17cca9cf0d28e742c6077fb5a89ef5cdc23d9c37c96c5fb7f321d7f52c06e73c46633783d9535e2aa5cc07f2ad1803d73614c4e6882026bfd9
```

Now, if I gave somebody the same script, my encoded message and the key, they can decode the message and find out where I buried my treasure:

```bash
$ node ./secretmsg.js -d --key="popcorn" c8c78895fd91da17cca9cf0d28e742c6077fb5a89ef5cdc23d9c37c96c5fb7f321d7f52c06e73c46633783d9535e2aa5cc07f2ad1803d73614c4e6882026bfd9
My treasure is buried behind Carl's Jr. on Telegraph.
```

You should know that what I buried behind Carl's Jr was just a cigarette butt, and that this script is obviously not for serious use.

## Signing and Verification

Crypto has other methods used for dealing with certificates and credentials, as used for TLS:

* `crypto.createCredentials`
* `crypto.createSign`
* `crypto.createVerify`

These methods supply the last building blocks for a complete cryptographic protocol, and require an advanced knowledge of real-world cryptographic protocols to be useful. Again, it is recommended that developers use either the [tls](https://nodejs.org/api/tls.html) module or the [https](https://nodejs.org/api/https.html) module if applicable.


text:
package org.intellij.images.util;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ImageLoader;
import com.intellij.util.SVGLoader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.stream.ImageInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Objects;

/**
 * @author spleaner
 */
public class ImageInfoReader {
  private static final Logger LOG = Logger.getInstance("#org.intellij.images.util.ImageInfoReader");

  private ImageInfoReader() {
  }

  @Nullable
  public static Info getInfo(byte @NotNull [] data) {
    return getInfo(data, null);
  }

  @Nullable
  public static Info getInfo(byte @NotNull [] data, @Nullable String inputName) {
    Info info = getSvgInfo(data);
    if (info != null) return info;

    return read(new ByteArrayInputStream(data), inputName);
  }

  @Nullable
  private static Info getSvgInfo(byte @NotNull [] data) {
    for (int i = 0; i < Math.min(data.length, 100); i++) {
      byte b = data[i];
      if (b == '<') {
        Info info = getSvgSize(data);
        if (info != null) {
          return info;
        }
      }
      if (!Character.isWhitespace(b)) {
        break;
      }
    }
    return null;
  }

  private static Info getSvgSize(byte[] data) {
    try {
      ImageLoader.Dimension2DDouble size = SVGLoader.getDocumentSize(null, new ByteArrayInputStream(data), 1.0f);
      return new Info((int)Math.round(size.getWidth()), (int)Math.round(size.getHeight()), 32, true);
    }
    catch (Throwable e) {
      return null;
    }
  }

  @Nullable
  private static Info read(@NotNull Object input, @Nullable String inputName) {
    ImageIO.setUseCache(false);
    try (ImageInputStream iis = ImageIO.createImageInputStream(input)) {
      if (isAppleOptimizedPNG(iis)) {
        // They are not supported by PNGImageReader
        return null;
      }
      Iterator<ImageReader> it = ImageIO.getImageReaders(iis);
      ImageReader reader = it.hasNext() ? it.next() : null;
      if (reader != null) {
        reader.setInput(iis, true);
        int w = reader.getWidth(0);
        int h = reader.getHeight(0);
        Iterator<ImageTypeSpecifier> it2 = reader.getImageTypes(0);
        int bpp = it2 != null && it2.hasNext() ? it2.next().getColorModel().getPixelSize() : -1;
        return new Info(w, h, bpp, false);
      }
    }
    catch (Throwable ignore) {}
    return null;
  }

  public static class Info extends ImageInfo {
    private final boolean myIsSvg;

    public Info(int width, int height, int bpp, boolean isSvg) {
      super(width, height, bpp);
      myIsSvg = isSvg;
    }

    public boolean isSvg() {
      return myIsSvg;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      if (!super.equals(o)) return false;
      Info info = (Info)o;
      return myIsSvg == info.myIsSvg;
    }

    @Override
    public int hashCode() {
      return Objects.hash(super.hashCode(), myIsSvg);
    }
  }

  private static final byte[] APPLE_PNG_SIGNATURE = {-119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 4, 67, 103, 66, 73};

  private static boolean isAppleOptimizedPNG(@NotNull ImageInputStream iis) throws IOException {
    try {
      byte[] signature = new byte[APPLE_PNG_SIGNATURE.length];
      if (iis.read(signature) != APPLE_PNG_SIGNATURE.length) {
        return false;
      }
      return Arrays.equals(signature, APPLE_PNG_SIGNATURE);
    }
    finally {
      iis.seek(0);
    }
  }
}


text:
A repo demonstrating [CLJS Issue 2023](https://dev.clojure.org/jira/browse/CLJS-2023)

This repo provides a minimal harness for testing the efficacy of using `js/goog.DEBUG`
to provoke Dead Code Elimination in production builds.

It compares the efficacy of `js/goog.DEBUG` and `goog.DEBUG`.  It can be used to
show a change of behaviour (bug!) occured sometime
between ClojureScript 1.9.293 and 1.9.456.

### Test Steps:

1.  Choose to [download a particular version of ClojureScript](https://github.com/clojure/clojurescript/releases).
    Download the `cljs.jar` for the release you want to test, into the root of this repo.

2.  In the root of this repo, at the commandline, trigger a compile by executing:
     - Windows: `java -cp "cljs.jar;src" clojure.main build.clj`
     - Linux/Mac: `java -cp cljs.jar:src clojure.main build.clj`

    Look in `build.clj` for the compile options used. Notice use of
    `:advanced` compilation and that `goog.DEBUG` is set to false.

3.  open `out/main.js` and inspect the compiled code.
    Look at the end of the file for what strings exist.
    If you see `"If this string appears in main.js then '^boolean js/goog.DEBUG' is failing to cause DCE"`
    the string is self explanatory.

To appreciate step 3, [look at the tiny amount of code in `src\core.cljs`](https://github.com/mike-thompson-day8/CLJS-issue-2023/blob/master/src/core.cljs).

### My Experimental Results

By varing Step 1 (above), I found:
  - For ClojureScript version 1.9.456 there was a problem  (the damning string showed up in main.js)
  - For ClojureScript version 1.9.293 there was NO problem (no damning string showed up in main.js)


text:
/**
 * Module dependencies
 */

var util = require('util'),
    crypto = require('crypto'),
    _ = require('lodash');

// Make _.defaults recursive
_.defaults = require('merge-defaults');

/**
 * This `before` function is run before generating targets.
 * Validate, configure defaults, get extra dependencies, etc.
 *
 * @param  {Object} scope
 * @param  {Function} cb    [callback]
 */

module.exports = function(scope, cb) {

    //
    // Validate custom scope variables which
    // are required by this generator.
    //
    //
    if ( !scope.rootPath ) {
        return cb(new Error(
            'Missing scope variable: `rootPath`\n' +
            'Please make sure it is specified and try again.'
        ));
    }

    //
    // Determine default values based on the
    // available scope.
    //
    _.defaults(scope, {
        currentTime: new Date(),
        viewEngine: 'ejs'
    });

    // Create a default session secret
    scope.secret = generateSecret();

    cb();
};

/**
 * Generate session secret
 * @return {[type]} [description]
 */
function generateSecret () {

    // Combine random and case-specific factors into a base string
    var factors = {
        creationDate: (new Date()).getTime(),
        random: Math.random() * (Math.random() * 1000),
        nodeVersion: process.version
    };
    var basestring = '';
    _.each(factors, function (val) { basestring += val; });

    // Build hash
    var hash =  crypto.
                createHash('md5').
                update(basestring).
                digest('hex');

    return hash;
}


text:
package im.actor.core.js;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.Scheduler;

import org.timepedia.exporter.client.ExporterUtil;

import im.actor.core.entity.Contact;
import im.actor.core.entity.Dialog;
import im.actor.core.entity.Message;
import im.actor.core.entity.SearchEntity;
import im.actor.core.js.entity.JsContact;
import im.actor.core.js.entity.JsDialog;
import im.actor.core.js.entity.JsMessage;
import im.actor.core.js.entity.JsSearchEntity;
import im.actor.core.js.providers.Assets;
import im.actor.runtime.js.JsAssetsProvider;
import im.actor.runtime.js.JsEngineProvider;

public class GwtEntryPoint implements EntryPoint {

    public void onModuleLoad() {
        ExporterUtil.exportAll();
        JsAssetsProvider.registerBundle(Assets.INSTANCE);
        JsEngineProvider.registerEntity(Contact.ENTITY_NAME, JsContact.CONVERTER);
        JsEngineProvider.registerEntity(Dialog.ENTITY_NAME, JsDialog.CONVERTER);
        JsEngineProvider.registerEntity(Message.ENTITY_NAME, JsMessage.CONVERTER);
        JsEngineProvider.registerEntity(SearchEntity.ENTITY_NAME, JsSearchEntity.CONVERTER);

        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                onAppLoaded();
            }
        });
    }

    public native void onAppLoaded()/*-{
        if ($wnd.jsAppLoaded) $wnd.jsAppLoaded();
    }-*/;
}