Cryptography and Ruby just got a litte more acquainted. If you have not heard
of djb's crypto library, NaCl, then now would be a good time for you to become
a little more acquainted with cryptography and in particular why this crypto library is awesome. I really
suggest reading about all the state of the art encryption algorithms used in NaCl because this post will
only cover how to use the Ruby library for NaCl.
Crypto You Can Do
Secret-key Encryption
Store some secret stuff with Crypto::SecretBox like so:
# Generate a random secret key
key = Crypto::Random.random_bytes(32)
# initialize a new place to store secret stuff
safe = Crypto::SecretBox.new(key)
# encrypt something using a nonce strategy,
# this can be any number really and it's not secret
# lets use some random bytes though
nonce = Crypto::Random.random_bytes(24)
message = "Coffee and bananas"
cipher_text = crypto_secret_box.box(nonce, message)
# decrypt the message
decrypted_message = safe.open(nonce, cipher_text)
#=> "Coffee and bananas"
Public-key Encryption
Mutual authentication (two-way authentication) can be performed below.
# Dat private key
private_key = Crypto::PrivateKey.generate
# Dat public key
public_key = private_key.public_key
# initialize the safe
safe = Crypto::Box.new(someones_public_key, private_key)
# the other person does this with your key
safe = Crypto::Box.new(public_key, someones_private_key)
# encrypt a message using the box.
# First, do the nonce thingy.
nonce = Crypto::Random.random_bytes(24)
message = "Coffee and bananas"
cipher_text = safe.box(nonce, message)
# Now open the safe
decrypted_message = safe.open(nonce, cipher_text)
Digital Signatures
Digital signatures allow you to publish a public key, then you can use your private signing key to sign messages.
Signer's Perspective
# Generate a new random signing key
signing_key = Crypto::SigningKey.generate
# Sign a message with the signing key
# Signature will be returned in hex format
signature = signing_key.sign(message, :hex)
# Obtain the verify key for a given signing key
verify_key = signing_key.verify_key
# Serialize the verify key to send it to a third party
# Verify key will be returned in hex format
verify_key.to_s(:hex)
Verifier's perspective
# Create a VerifyKey object from a hex serialized public key
verify_key = Crypto::VerifyKey.new(verify_key_hex, :hex)
# Check the validity of a message's signature
# Will raise Crypto::BadSignatureError if the signature check fails
verify_key.verify!(message, signature, :hex)
Hash Functions
A cryptographic hash can be used for checking the integrity of data, but there is no secret involved in the hashing, so anyone can create the hash of a given message.
# compute the SHA-256 digest of the message.
Crypto::Hash.sha256(message)
#=> "..." # a string of bytes.
# compute the SHA-512 digest of the message and hex-encode it.
Crypto::Hash.sha512(message, :hex)
#=> "ab67..." # a string of hexidecimal bytes.
On a recent project, I had the need to integrate some AngularJS-based interactions within an existing Rails application. I wasn't able to treat it as two separate projects in this case, e.g., a Rails API app/project, that my AngularJS app/project would interact with via XHR. So, here is how I've been able to interact with Rails url/routes and have Rails serve the pre-compiled haml as html.
Let's get started.
Create a new folder within app/views, something like app/views/client_views. Then create a new view for one of your AngularJS controllers, we'll use the typical 'main', so now you'll have app/views/client_views/main.html.haml.
Create a new controller to handle your AngularJS views (app/controllers/client_views_controller.rb)
class ClientViewsController < ApplicationController
def show
render params[:id], layout: nil
end
end
Within your AngularJS app's config, you'll now have the following for the $routeProvider:
Today I learned there was a Ruby gem that could detect the gender of a name.
The gem is called Sex Machine. It can
even give geographical specific information on names. Check out my examples:
First you need to install it:
gem install sexmachine
Now you can detect genders based on a person's name like so:
So last week's post was similar to today. However, today I play with a bit more interesting RasPi libraries.
The big difference is that we're using software PWM via the wonderful pi-blaster library. It basically latches onto the DMA for the single PWM pin the RasPi offers, and gives you eight pins. It's derived from Richard Hirst's ServoBlaster but it allows a 100% duty cycle. We'll ultimately use this same library / concept to drive a remote controlled vehicle via drb with the Pi, but first things first!
Let's show some code.
The pi-blaster library expects that you send something like this to a device it creates for you:
echo "1=1" > /dev/pi-blaster
That would turn GPIO pin 1 on 100% of the time. The second argument is just a floating point number from 0 to 1.
I'm all about TDD, so I whipped up this spec for how my RGB LED object should work in Ruby:
describe RGBLed do
it "can be instantiated with three GPIO pin numbers" do
led = RGBLed.new(red_pin: 0, green_pin: 1, blue_pin: 2)
end
describe "setting color intensity" do
before do
@led = RGBLed.new(red_pin: 0, green_pin: 1, blue_pin: 2)
end
it "allows you to set red anywhere from 0 to 1" do
@led.red = 1
@led.red.must_equal 1
end
it "allows you to set green anywhere from 0 to 1" do
@led.green = 1
@led.green.must_equal 1
end
it "allows you to set blue anywhere from 0 to 1" do
@led.blue = 1
@led.blue.must_equal 1
end
it "does not allow you to set intensity above 1 or below 0" do
lambda{ @led.red = 2 }.must_raise OutOfRangeException
lambda{ @led.red = -1 }.must_raise OutOfRangeException
end
end
describe "outputting pi-blaster commands" do
before do
@led = RGBLed.new(red_pin: 0, green_pin: 1, blue_pin: 2)
@led.red = 0.5
@led.green = 0.75
@led.blue = 1
end
it "handles red" do
@led.pi_blast_command(:red).must_equal "echo 0=0.5 > /dev/pi-blaster"
end
it "handles green" do
@led.pi_blast_command(:green).must_equal "echo 1=0.75 > /dev/pi-blaster"
end
it "handles blue" do
@led.pi_blast_command(:blue).must_equal "echo 2=1 > /dev/pi-blaster"
end
end
end
Then it was just a matter of making the spec work, so this class satisfies that spec:
class OutOfRangeException < StandardError; end
class RGBLed
def initialize(options={})
@options = options
@pins = {
red: fetch_option(:red_pin),
green: fetch_option(:green_pin),
blue: fetch_option(:blue_pin)
}
@intensity = {
red: 0,
green: 0,
blue: 0
}
end
def red=(value)
set_intensity(:red, value)
end
def red
get_intensity(:red)
end
def green=(value)
set_intensity(:green, value)
end
def green
get_intensity(:green)
end
def blue=(value)
set_intensity(:blue, value)
end
def blue
get_intensity(:blue)
end
def pi_blast_command(channel)
"echo #{get_pin(channel)}=#{get_intensity(channel)} > /dev/pi-blaster"
end
def pi_blast
%w(red green blue).each do |c|
`#{pi_blast_command(c)}`
end
end
private
def fetch_option(channel)
@options.fetch(channel) { raise "Must specify `#{channel.to_s}` option." }
end
def set_intensity(channel, value)
validate_channel(channel)
validate_intensity(value)
@intensity[channel.to_sym] = value
end
def get_intensity(channel)
validate_channel(channel)
@intensity[channel.to_sym]
end
def get_pin(channel)
validate_channel(channel)
@pins[channel.to_sym]
end
def validate_channel(channel)
return true if valid_channels.include?(channel.to_s)
raise "Invalid attribute channel: #{channel}"
end
def validate_intensity(intensity)
return true if valid_intensities.cover?(intensity)
raise OutOfRangeException, "Invalid intensity: #{intensity}"
end
def valid_channels
%w(red green blue)
end
def valid_intensities
(0..1)
end
end
As I mentioned in the video, the RGB LED we had on hand actually took ground to the channels, and positive voltage to the common pin, which went against my assumptions. Basically, setting red to 1 would mean off, and 0 would mean on. OOP is super-sweet, so this class fixes that up for me:
class InverseRGBLed < RGBLed
def get_intensity(channel)
1-super
end
end
Finally (on the ruby side), we needed to expose him to the network. This script does that for me, as well as initializes him to blue.
require_relative '../lib/inverse_rgb_led.rb'
led = InverseRGBLed.new(red_pin: 0, green_pin: 1, blue_pin: 4)
led.pi_blast
led.red=0
led.green=0
led.blue=1
led.pi_blast
require 'drb/drb'
require 'pi_piper'
# The URI for the server to connect to
URI="druby://192.168.1.76:8787"
# The object that handles requests on the server
FRONT_OBJECT=led
$SAFE = 1 # disable eval() and friends
DRb.start_service(URI, FRONT_OBJECT)
# Wait for the drb server thread to finish before exiting.
DRb.thread.join
Then on the android side, this main activity will handle pretty much everything.
package com.isotope11.rgbledapp;
import java.util.ArrayList;
import java.util.List;
import org.jruby.embed.ScriptingContainer;
import android.app.Activity;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import com.commonsware.cwac.colormixer.ColorMixer;
import com.commonsware.cwac.colormixer.ColorMixer.OnColorChangedAndStoppedListener;
public class MainActivity extends Activity {
protected final String TAG = MainActivity.class.toString();
protected ScriptingContainer mRubyContainer;
protected String mDrbResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.setProperty("jruby.bytecode.version", "1.5");
mRubyContainer = new ScriptingContainer();
List<String> loadPaths = new ArrayList<String>();
loadPaths.add("jruby.home/lib/ruby/shared");
loadPaths.add("jruby.home/lib/ruby/1.8");
mRubyContainer.setLoadPaths(loadPaths);
final Activity lol = this;
ColorMixer colors = (ColorMixer) findViewById(R.id.mixer);
colors.setOnColorChangedAndStoppedListener(new OnColorChangedAndStoppedListener() {
@Override
public void onColorChange(int argb) {
int r = Color.red(argb);
int g = Color.green(argb);
int b = Color.blue(argb);
RGBLedSetter task = new RGBLedSetter();
task.setRed(r);
task.setGreen(g);
task.setBlue(b);
task.execute();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class RGBLedSetter extends AsyncTask<Object, Void, String> {
int mRed = 0;
int mGreen = 0;
int mBlue = 0;
@Override
protected String doInBackground(Object... arg0) {
String rubyDrbClient = "require 'drb/drb';SERVER_URI='druby://192.168.1.76:8787';DRb.start_service;led = DRbObject.new_with_uri(SERVER_URI);led.red=" + getMapped(mRed) + ";led.green=" + getMapped(mGreen) + ";led.blue=" + getMapped(mBlue) + ";led.pi_blast;";
mRubyContainer.runScriptlet(rubyDrbClient);
return "nope";
}
@Override
protected void onPostExecute(String result){
mDrbResult = result;
}
public void setBlue(int val){
mBlue = val;
}
public void setGreen(int val){
mGreen = val;
}
public void setRed(int val){
mRed = val;
}
public String getMapped(int val){
float newVal = Float.valueOf(val) / Float.valueOf(255);
Log.d(TAG, Float.toString(newVal));
return Float.toString(newVal);
}
}
}
isitdownrightnow.com seems to be a step above 'downforeveryoneorjustme' in that it also searches twitter, other social networks for related commentary.
Got the LED Toggler Ruby script from last week exposing a toggle-able LED object over the network with drb under MRI on the Raspberry Pi.
Built an Android app.
Inside of that Android app I embedded a JRuby ScriptingContainer.
In that ScriptingContainer I evaluated some ruby.
In that ruby script I connected to the aforementioned drb object.
On button press in the Android app, I call the #toggle method of the drb object.
This all combines to have the effect of an android app to toggle an LED on the network. This is, of course, extremely awesome and extensible. See the video above for proof.
I'll also just put the relevant bits of code in the post here:
server.rb
require 'drb/drb'
require 'pi_piper'
# The URI for the server to connect to
URI="druby://192.168.1.76:8787"
class Toggler
attr_accessor :pin, :state
def initialize
@pin = PiPiper::Pin.new(pin: 15, direction: :out)
@state = false
end
def toggle
state ? pin.on : pin.off
@state = !state
puts 'toggled'
end
end
# The object that handles requests on the server
FRONT_OBJECT=Toggler.new
$SAFE = 1 # disable eval() and friends
DRb.start_service(URI, FRONT_OBJECT)
# Wait for the drb server thread to finish before exiting.
DRb.thread.join
MainActivity.java
package com.isotope11.ledclicker;
import java.util.ArrayList;
import java.util.List;
import org.apache.bsf.BSFException;
import org.jruby.embed.ScriptingContainer;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
protected final String TAG = MainActivity.class.toString();
protected ScriptingContainer mRubyContainer;
protected String mDrbResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.setProperty("jruby.bytecode.version", "1.5");
mRubyContainer = new ScriptingContainer();
List<String> loadPaths = new ArrayList<String>();
loadPaths.add("jruby.home/lib/ruby/shared");
loadPaths.add("jruby.home/lib/ruby/1.8");
mRubyContainer.setLoadPaths(loadPaths);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void onLEDClickerClick(View view) {
RubyRunner rubyRunner = new RubyRunner();
rubyRunner.execute();
}
public void handleDrbResult() {
Toast.makeText(this, mDrbResult, Toast.LENGTH_LONG).show();
}
private class RubyRunner extends AsyncTask<Object, Void, String> {
@Override
protected String doInBackground(Object... arg0) {
String rubyDrbClient = "require 'drb/drb';SERVER_URI='druby://192.168.1.76:8787';DRb.start_service;toggler = DRbObject.new_with_uri(SERVER_URI);toggler.toggle";
String result = (String) mRubyContainer.runScriptlet(rubyDrbClient);
return result;
}
@Override
protected void onPostExecute(String result){
mDrbResult = result;
handleDrbResult();
}
}
}
Gistbox is 'the personal code library you've always wanted'. It looks really cool, but I couldn't get past it wanting to log in to github (just asked repeatedly). Still, putting it here because it looks so neat :)
signed_form avoids users passing in disallowed fields by really basic form parameter signing in the rendered html. Lots nicer and more sensible than rails 3's attr_accessible on models (what sense did that make?). Seems like just a really easy thing (though it does put the onus on the view designer for security, and seems easier to accidentally overlook on occasion)
More Gtk+ in the cloud. I've been following Alexander Larsson's work on the Broadway backend for GTK for years and it's getting seriously, seriously impressive.
E (programming language)) just a programming language for secure distributed computing. It's based on capabilities, which are a Big Deal if you want to build such a thing. I know @bascule is certainly pretty interested in capabilities.
mutations is a neat looking library for doing "UseCase" style stuff, where your controllers just run a "mutation" and return the result. If you see it and think it's neat, then you will. If you don't know what this sort of thing is for or you think it's lame, that's fine too :)
Adam pointed us to the Kerbal Space Program and people have gotten addicted since as I understand it.
datamappify is a Repository Pattern for ActiveRecord (and others)
CSS-Shack is a visual CSS designer for use in the browser.
If you're interested in Rails security, Bryan Helmkamp posted about Rails' insecure defaults. In the post, he mentioned http://rails-sqli.org, which highlights areas in which sql injection is possible in activerecord (and consequently you should take care not to send user input into).