HTTPS/SSL calls with Lua and LuaSec

LuaSec module integrates with LuaSocket and provides HTTPS/SSL support for Lua socket operations. After you install LuaSocket and LuaSec, it only takes a couple of lines of code to make a call:

require("socket")
local https = require("ssl.https")
local body, code, headers, status = https.request("https://www.google.com")
print(status)

This should print HTTP/1.1 200 OK if your call is successful. If you need more control over the SSL configuration and the handshake steps, you can implement those steps yourself:

require("socket")
local ssl = require("ssl")

-- TLS/SSL client parameters (omitted)
local params = {
  mode = "client",
  protocol = "tlsv1",
  verify = "none",
  options = "all",
}

local conn = socket.tcp()
conn:connect("www.google.com", 443)

-- TLS/SSL initialization
conn = ssl.wrap(conn, params)
conn:dohandshake()

conn:send("GET / HTTP/1.1\n\n")
local line, err = conn:receive()
print(err or line)
conn:close()

Again, the steps are simple: open a TCP connection on port 443 (this is a default port for HTTPS), wrap a socket connection into SSL with specified parameters, do a handshake, and then use regular send/receive methods. This code should print HTTP/1.1 200 OK if the request is successful or an error, if not.

This code doesn't use certificate verification as we explicitly specified verify="none" in the parameter list. Certificate verification allows the client (your script in this case) to confirm that the site it is connected to has access to a valid certificate, signed by a certificate authority. This is the same process that your web browser does for you when you connect to a website over https:. To enable certificate verification in SSL verify="none" needs to be replaced with verify="peer". This is not enough, however: if you run this code with verify="peer", you will get: certificate verify failed error.

This error indicates that we requested certificate verification, but have no means to verify this certificate as we don't have any certificate authority certificates we can use to validate the signature on the certificate provided by the website we are connecting to. To do that, we need to find and download the file with these certificates; it comes with your browser, but can also be found online. For example, this site has the file with certificates used by mozilla.org and included with Firefox. You can download the file, save it, and then specify the location of the saved file as one of the parameters for SSL:

local params = {
  mode = "client",
  protocol = "tlsv1",
  cafile = "/path/to/downloaded/cacert.pem", --<-- added cafile parameters
  verify = "peer", --<-- changed "none" to "peer"
  options = "all",
}

You can now use the same script to connect to google.com (and other sites) over HTTPS and your script will verify the certificate provided by the site you are connected to.

You should get a copy of my slick ZeroBrane Studio IDE and follow me on twitter here.

7 Comments

Great tutorial! Just what I was searching! Thanks :)

there is error: code: wrong version number

@icreator, you'll need to provide more information if you want me to investigate. I just tried both of the scripts and they work for me. I did find couple of references to "wrong version number" errors, which may be related to the difference between protocols used by the client or the server: 1 and 2. You may want to try changing "protocol" to "sslv3".

I was wondering if there was a way for using Lua to communicate with a binary interface like Apple Push Notification Service which expects data in binary format and fixed byte length and order.

@Parveen, this is most definitely possible. All you need is some library that would allow you to pack binary structures into strings as luasocket itself simply sends bytes. You may use something like vstruct (https://github.com/toxicfrog/vstruct/) to generate proper structures; more alternatives are listed on this page: http://lua-users.org/wiki/StructurePacking

Hey, is it possible to import this on Corona SDK? Someone on the coronalabs forums suggested this method, I've tried importing the libraries to my project. However, I'm getting an error that I'm missing ssl.core.lu package.

Any help is appreciated, thanks!

Hi Yury, judging by the error message, Corona is trying to load ssl.code.lua file while it should be loading ssl/core.dll or ssl/core.so. Make sure you have correct settings as describe here: http://docs.coronalabs.com/daily/plugin/openssl/. You may also try network.request, which supports both http and https (http://docs.coronalabs.com/daily/api/library/network/request.html).

Leave a comment

what will you say?
(required)
(required)

About

I am Paul Kulchenko.
I live in Kirkland, WA with my wife and three kids.
I do consulting as a software developer.
I study robotics and artificial intelligence.
I write books and open-source software.
I teach introductory computer science.
I develop a slick Lua IDE and debugger.

Recommended

Close