How-to create a reasonably secure Arduino client that post data into a Rails application – part II

In part I I described how to create the Rails application but now lets focus on the Arduino. First you need to find a library for you GSM/GPRS shield you are using. I have the Seeedstudio GPRS Shield even though I do not have version 2.0 no good library existed for it. The libraries Seeedstudio list on their wiki and product pages all work great but they have which I consider a major flaw; they do NOT use the same methods etc as the official Arduino GSM library does. Thus if someone has developed a client using that shield you would need to re-write the code if you have another GSM shield. Both provide same functionality but through a different API. NOT a good solution in my eyes.

The official GSM library is written to be extended with support for other shields and I started to look into it. After examining the code for a while I noticed it is not written very well. The library as such is large and uses a lot of unnecessary RAM. My intentions is to create a client that will be RAM efficient to run on a Duemilanove which has only 2 kb RAM. Thus I started to write yet another GSM library for the Seeedstudio Shield. The result is the GSMGPRS_Shield library.

Anyway that was a sidetrack from the main, to create a reasonably secure Arduino client. Now we got a library to send and receive information to a HTTP server! So the next step is to find a good REST client. I found a number of different libraries that could be used either just for HTTP communication or both HTTP and REST.

HttpClient which is mainly developed for the Spark and not the best on a vanilla Arduino. Then there is the HTTPClient by Interactive Matter. Yet another HttpClient by Adrian McEwen. And uHTTP though all of these are based on the EthernetClient class and thus has to be re-written if going to be used with any GSM library. So much for code reusability.

There also exists a number of REST client libraries, like spark-restclient which is of course developed for the Spark. Another one is arduino-restclient but again both are built on the EthernetClient class.

After a bit of investigation I decided to use arduino-restclient but modify it to work with my GSMGPRS_Shield library. My fork is available here. My modified version uses the F() macro to put almost all strings into PROGMEM to save ram and cleaned up some other parts as well.

Next I needed MD5, SHA-1 and Base64 encoding since those are used in a request that is going to be received by API_Auth that we used on the rails side. MD5 support is provided by ArduinoMD5. Adafruit has created a stripped down SHA-1 library that I use. For Base64 encoding I used arduino-base64 but created a fork of it since it stored it’s whole Base64 alphabet in RAM instead of PROGMEM.

Then finally it was more or less just to set all this together and create the client. I have put the Arduino sketch on Github, ArduinoAuthenticatedClient.

A quick walkthrough of the code:
Change the secret key to the one generated by your rails application and make sure you set the ID in authHeaderStr to the correct id. In my example the id is 3. The numbers after the id and the : is where the authentication string will be copied.

    const char PROGMEM secretKey[] = "wJ+LuCJKuFOcEdV0rdbp0BtkLdLm/EvH31KwiILc/xC35zgDd+KMBTuvmpH9uhNtOvfTr8rl7j6CHVSM8BB7XA==";
    char *authHeaderStr = "Authorization: APIAuth 3:123456789012345678901234567=";

In general the code is a quite straight forward HTTP/REST client. The interesting part is the getHMACSignature_P function that concatenates the four different strings that are used to create the signature. But first we create the MD5 hash of the requests body and Base64 encode that:

    unsigned char* hash=MD5::make_hash(body);  
    base64_encode(b64, (char *)hash, 16);
    strncpy(&contentMD5Str[CONTENT_MD5_STR_CONTENT_START], b64, 22);
    free(hash);
    rest.setHeader(contentMD5Str);

Then we use that as one of the four strings to create the HMAC signature, which we also Base64 encode before setting the authentication header:

   base64_encode(b64,
      (char *)getHMACSignature_P((uint8_t *)secretKey, sizeof(secretKey)-1,
        &contentTypeHeaderStr[CONTENT_TYPE_STR_CONTENT_START],
        &contentMD5Str[CONTENT_MD5_STR_CONTENT_START],
        resourcePath,
        &dateStr[DATE_STR_CONTENT_START]),
      20);

    strncpy(&authHeaderStr[AUTH_HEADER_STR_CONTENT_START], b64, 27);
    rest.setHeader(authHeaderStr);

Two comments:

  1. I use my web server here at YellowOrb as host because I needed some public machine. I setup up an SSH tunnel from that to my local machine which runs the Rails application.
  2. The time stamp of the request is important since the receiving Rails application will not accept the request if it is to old. Thus, change the char *dateStr ="Date: Thu, 13 Nov 2014 14:18:11 GMT"; to something appropriate.

How-to create a reasonably secure Arduino client that post data into a Rails application – part I

Arduinos get more and more connected and I use an Arduino together with a GSM/GPRS shield to build the wind stations.

But the Arduino is a very limited platform and some (as the Nano) has as little as 1k RAM! Then it becomes a real challenge to do web and HTTP communication. Here I will summarise the experience gathered during the construction of a tiny secure REST client for the Arduino.

Why REST?
Ruby on Rails is the framework I prefer when it comes to write web applications. It is powerful still quite fast to work with. Rails uses REST a lot and it is definite the easiest way to considering the server-side. Though HTML is quite talkative so lots of strings(which take RAM) will be needed in the Arduino, or clever use of PROGMEM with which we can put the strings in ROM.

Secure?
What I mainly want to achieve is to make it hard for someone to send/post false information into the Rails application. For the wind stations it does not matter so much but say we use an Arduino for some kind of real world game. Then some clever hacker could quite easily figure out the URL to make a post and then just start posting in actions or whatever the Arduino controls. So we want to make sure those post requests we receive comes from a unit we have put the software inside.

HMAC
But what kind of authentication should one use? Have read around a bit and regarding REST so seems HMAC(Hash based Message AuthentiCation) a good option and recommended(http://restcookbook.com/Basics/loggingin/). Also found an Arduino lib that supports HMAC called Cryptosuite. It seems at first glance to be really memory efficient (uses PROGMEM) but when reading through the code it seems to use about 196 bytes of RAM which is still quite a lot in these circumstances.

Rails application
Lets start with the Rails application. API_AUTH seems to be a good library to get HMAC support for Rails applications so that was my choice.

Create a new Rails project:

>rail new ArduinoAuthenticatedClientExample

Then using you favourite text editor add API_AUTH to the Gemfile:

gem 'api-auth'

After that do a bundle update to get all gems installed.

> bundle update

Our model is quite simple, we have probes(an Arduino) that can post temperature readings(Measures). So lets create these two:

> rails generate scaffold Probe name:string secret:string
> rails generate scaffold Measure temperature:float

We need to setup the relationships between these models, a probe has many measures and measures belongs to probes. In app/models/probe.rb add:

has_many :measures

and in app/models/measure.rb add:

belongs_to:probe

Now give the following command to generate the migration and have it create the needed index in measures:

rails generate migration AddProbeRefToMeasures user:references

Now it is time to update the database:

rake db:migrate

Add the following code to app/controllers/measures_controller.rb so that all REST calls that modify the model needs to be authenticated using HMAC:

# require any kind of change and creation of a measure to come through our authenticated api using HMAC 
  # and we skip the CSRF check for these requests
  before_action :require_authenticated_api, only: [:edit, :update, :destroy, :create]
  skip_before_action :verify_authenticity_token, only: [:edit, :update, :destroy, :create]

  def require_authenticated_api
    @current_probe = Probe.find_by_id(ApiAuth.access_id(request))
    logger.info request.raw_post # needed due to a bug in api_auth
    # if a probe could not be found via the access id or the one found did not authenticate with the data in the request
    # fail the call
    if @current_probe.nil? || !ApiAuth.authentic?(request, @current_probe.secret) 
      flash[:error] = "Authentication required"
      redirect_to measures_url, :status => :unauthorized
    end
  end 

We added a flash error message in the code above so we need to add support in app/views/layouts/application.html-erb to get that presented:

< % flash.each do |name, msg| -%>
      < %= content_tag :div, msg, class: name %>
    < % end -%>

We want the secret keys generated automatically rather then entered by the user. So in app/controllers/probes_controller.rb, in the create method change so the first lines looks like this:

    @probe = Probe.new(probe_params)
    @probe.secret = ApiAuth.generate_secret_key

And we want to remove the input field. Change in app/views/probes/_form.html.erb so

< %= f.text_field :secret %>

becomes

< %= @probe.secret %>

Now we are almost done but we want to add some more security. We do not want anyone be able to change the secret keys and actually we would like to add user authentication so that like an admin is the only one who ca see the secrets but that is not a task for this tutorial. If you need that see for example the Devise getting started guide. Add the following to app/models/probe.rb so that the secret only can be read and not modified:

attr_readonly :secret

Now you can run the server and start creating probes. Do

> rails server

and create a probe or two by going to http://localhost:3000/probes/

To test that is’s working create a simple client:

require 'openssl'
require 'rest_client'
require 'date'
require 'api_auth'

@probe_id = "2"
@secret_key = "rNwtKjjVZ4UUTQWvL+ZpK1PVjXz5N1uKpYRCfLfTD+ySTMaeswfPhkokN/ttjX3J78KNqclcYLHSw/mzHeJDow=="
    
headers = { 'Content-Type' => "text/yaml", 'Timestamp' => DateTime.now.httpdate}

@request = RestClient::Request.new(:url => "http://localhost:3000/measures.json",
        :payload => {:measure => { :temperature => 12}},
        :headers => headers,
        :method => :post)
        
@signed_request = ApiAuth.sign!(@request, @probe_id, @secret_key)    

response = @signed_request.execute()
puts "Response " + response.inspect

And run that and you should get something like:

Response "{\"id\":19,\"temperature\":12.0,\"created_at\":\"2014-09-30T15:04:26.286Z\",\"updated_at\":\"2014-09-30T15:04:26.286Z\"}"

In part II I describe how to create the client on the Arduino.

Writing RAM efficient Arduino code

Developing the software for the wind stations I often run into problems and random restarts of the Arduino. Soon I realised it was due to that I ran out of RAM, 2k does not last that long, specifically when every debug string you put in consumes RAM. I found out about PROGMEM but I did not find so much more information on how to use it so instead I focused on getting things to work. But now when I re-write the whole communication code I plan to do it right!

So have looked a bit more into it and found the great article Putting constant data into program memory (PROGMEM) by Nick Gammon. It explains the whole problem as well as give many practical tips on how to write RAM efficient Arduino code.

And another recommendation is to use the latest Arduino IDE, the 1.5.8 Beta. It uses much newer compiler etc as described in this post. Also when compiling it generates not only information about how much of the storage space you sketch uses but also how much RAM is used at start. Like this:
Sketch uses 9,412 bytes (30%) of program storage space. Maximum is 30,720 bytes.
Global variables use 1,126 bytes (54%) of dynamic memory, leaving 922 bytes for local variables. Maximum is 2,048 bytes.

Remember that this only indicates the situation at start so do you have functions that use large arrays that will not be shown there.

Debugging HTTP communication over GSM

I’m writing a HTTP client for the Arduino. The debugging options on the Arduino are quite limited. And in general doing low level HTTP programming a tool like SockSpy is invaluable. Though for traffic to reach SockSpy it must be connected to a public TCP IP port. With the common use of firewalls and NATed networks this is generally not the case. How do you solve that?

If you have access to a public server on the internet, SSH is your salvation! Setup a reverse SSH tunnel from your server(yelloworb.com in my case, port 3000) to your local machine(port 2000), then configure SockSpy to connect back to the server(if thats the web server you try to talk HTTP with). Like this:
ssh -R 3000:localhost:2000 yelloworb.com
sockspy 2000 www.server.com 80

And change your code to talk to your server instead(yelloworb.com and port 3000 in my case).

To get the port forwarding working you need to enable GatewayPorts in the sshd configuration. Read here how to do that. The SSHd manpages has more useful information.

How to get PostgreSQL to work with Rails3 on Mac OSX snowleopard

I’m about to host a web app on Heroku and they are using PostgreSQL for database. Followed the instructions and added gem ‘pg’ to my Gemfile and made bundle install but it failed:
Installing pg (0.11.0) with native extensions /Users/kalle/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/installer.rb:552:in `rescue in block in build_extensions': ERROR: Failed to build gem native extension. (Gem::Installer::ExtensionBuildError)

Thought I didn’t have PostgreSQL installed so installed it via MacPorts:
sudo port install postgresql90

but still got the same error! After a bit of googling I found out it was due to that the bin folder was not in the path. So by doing this it worked:
export PATH=/opt/local/lib/postgresql90/bin/:${PATH}
env ARCHFLAGS="-arch x86_64" bundle install

Vindmätarbygge – framgångar

Sist jag rapporterade om projektet hade jag bara lyckats kompilera NewSoftSerial men sedan dess har jag lyckats köra det och efter ytterligare en del omkodning bla pga Minins minimala mängd RAM så fungerar det nästan!

Minin har bara 1k RAM så jag kan inte läsa in hela HTML svaret i minnet för det kan mkt väl vara större än så. Eftersom jag bara är intresserad att just nu rapportera in svar och att det går bra skrev jag en ny POST funktion som läser rad efter rad och kollar om en av dem innehåller HTTP/1.1 200 OK så jag vet att det gick bra. Man skulle kunna göra en utökning av GET med som bara returnerar själva XML delen som ett REST anrop ger tillbaka, allt för att nyttja så minimalt med RAM som möjligt.

Dock har jag ett problem kvar, efter att läst en del data så bootar Arduinon om! Jag har lyckats lokalisera det till när jag gör läsning från porten så gissar att NewSoftSerial inte klarar sig så bra i mycket minnes begränsat utrymme. Någon som har bra tips om hur man lätt debuggar dessa typer av problem? Bara göra massa print känns för osäkert då det kan uppstå timing problem etc…

Vindmätarbygge – serieport

Arduino Mini Pro har bara en hårdvarubaserad serial port. GSM Arduino lib som jag tänker använda kräver en för att prata med Telit kretsen men samtidigt vill man gärna ha på debuggingen och den är bunden till den enda hårdvaruporten som finns. Problem!

Det finns ju ett Arduino lib för mjukvaruportar men det är en hel del som inte stöds i det. Men dock finns NewSoftSerial som har stöd för det mesta så det borde inte vara så svårt att skriva om GSM Arduino lib att använda den serieporten istället. Så det blev kvällens lilla projekt.

Så nu har jag en ny version av det som jag kallar Soft GSM Arduino lib. Dock krävde det att jag fick hacka om NewSoftSerial lite också så att den blev än mer kompatibel med vanliga hårdvaruserieportarna. Dock inte hunnit med att testa något alls, men det kompilerar iaf:)

Nu är det dags att sova, god natt!

Vindmätarbygge – vindgivare

Som jag skrev igår skickade jag mail till flera svenska återförsäljare. Fick ett par svar idag och tänkte bara snabbt sammanfatta läget.

Safecast – skickade ett långt svar men hade inget konkret svar men var intresserade och ville veta mer. Diskussionen fortsätter och skickade dem ett längre mail precis.

Svenska Termoinstrument – svarade att de representerar två tyska tillverkare av vindgivare (Adolf Thies GmbH resp Lufft GmbH ) vars givare endast är avsedda för industrin (vindkraft, fastighetsautomation etc.). Några lågprisgivare under 1500 kr finns tyvärr inte i deras sortiment.

Livedata – deras billigaste givare låg på ca 5000 kr, långt över vad jag hoppats på. De får gå bort.

FDS Mätteknik har jag inte hört något från. Dock fick jag en kommentar från Magnus som byggt WindWiz på mitt förra inlägg att ClasOhlson har en trådkopplad givare som reservdel till en annan väderstation. 440 kr kostar vindriktning och vindhastighetsgivare ihop. Beställt!

Vindmätarbygge – start

Har börjat på ett litet projekt, bygga en vindmätare som via mobilnätet postar mätdata till en webserver som sedan kan plotta grafer etc.

Hemma hade jag redan några Arduino samt en GSM modul. Och just till denna GSM modul finns det redan ett Arduino lib så man kan göra GET och POST anrop mot en webserver.

Dock när jag skulle börja med att ansluta min Arduino upptcäkte jag att mina 5V mini inte var direkt lämpliga då jag skulle behöva lite konverteringselektronik för signalnivåerna. Så beställde istället några nya 3.3V istället som jag kan ansluta direkt.

Har även börjat leta efter lämpliga vindgivare som inte kostar en förmögenhet. Började med att kontakta Campbell Scientific och Vaisala men de vill ha mellan 10.000 och 30.000 för de givare jag frågade om. På tok för dyrt! Har skickat iväg ett antal mail till flera olika svenska leverantörer för att se vad de kan erbjuda. De jag kontaktat är SafeCast, Svenska Termoinstrument, LiveData och FDS Mätteknik.

Hittade även lite andra hobby projekt när jag sökte runt efter bra lösningar. Det intressanta var att båda projekten bygger på Arduino 🙂 Visar lite hur stort Arduino börjat bli. WindWiz år också en GSM uppkopplad vindmätare och använder en mätare från ClasOhlson. Så letade runt lite hos dem och hittade en vädligt prisvärd lösning, reservdel till väderstation. För endast 245 kr fick jag en komplett vindmätare med både hastighet och riktning. Dock idag när jag fick den insåg jag att jag missat en viktig del, den kopplades inte in med sladd som jag trodde utan trådlöst 🙁 Så började söka på nätet och hittade ett projekt till av en svensk kitare som verkar använt precis samma mätare. Har skickat ett mail så får vi se om han kan hjälpa till att koppla in den jag köpte från Classe.

Mätaren från Classe har ett par lödpunkter på kretskortet som skulle tyda på att man kan få ut seriedata direkt från kretskortet och inte behöver bygga en radiomottagare. Så här ser kretskortet ut:

Kretskortet med lödpunkter utmärkta

Får se när jag får svar på mailen jag skickat iväg men nästa steg blir nog i vilket fall att koppla ihop GSM kort och Arduino och prova biblioteket för att posta in lite data i en enkel web app jag hackat ihop.

Timelapses and video

Last week we where hiking in the Swedish mountains and as usual I brought the camera and a GorillaPod. Earlier this summer I saw Sean Stiegemeiers amazing timelapse from Iceland and got interested in creating these kinds of videos. One of the evenings we had some really nice clouds coming in over us and passing some peaks closeby. I put up the camera and shot a number of sequences. Found out that I could generate timelapses directly from Lightroom(following Sean McCormack on Twitter) so started experimenting with it. I wanted to merge several of them into one video and the only video editing tool I have is iMovie or Windows Movie Maker. I decided to use iMovie since I have used it mostly lately. Here is the result.

Doing this and converting another video also shot earlier this summer I learned a number of things that I wanted to share.

  1. When making timelapses take many photos!
    In a video a second or two is a very short clip and aim for 24 frames per second so if you want a 10 second clip, you have to take 240 photos!
  2. Black first frame?
    The generated videos from Lightroom all have a first black frame. I do not know how to turn that off but neither have I found anyone having this issue. When I imported the videos to iMovie it didnt become a problem but it might be due to the cross fading transitions I use.
  3. Compression settings. What are good values and how do you avoid getting a 500 Mb file?
    The details is of course very depending on which software you use but in general it should apply to any. In iMovie you have a couple of options. The one that I have noticed influences the file size the most is the maximum bitrate. Of course Quality is a major factor but if you want high quality but not huge size then its the bitrate. After googling a bit I found out that for a 720p movie 6Mbit/s is good. You could go a bit lower but I tired 4.5 Mbit/s and saw some compression artifacts that I didn’t wanted. The rest of the settings I left on default, see image below.