You will learn to:
– create key-pairs.
– encrypt and decrypt strings in python.
– send and receive encrypted messages with Azure Service Bus with python.
The Internet of Things is going to grow much much bigger than the Internet of humans very soon. Some machines already talk to each other using different communication protocols. Tesla automobiles update their firmware just like your smart phone does. Homes can lock doors, turn on/off lights remotely, etc. More and more devices are getting connected to the Cloud and this is great.
But, what if someone tells your house to lock you in and turn off the heater in the middle of the winter? How would the house know that someone other than you is controlling it?
Maybe you are on vacation and you tell the house to enter into “sleep” mode. Someone could read this and realise that nobody’s home…
Secure communication protocols for the internet of things are not utilised that often!
This tutorial gives an example of how to communicate a message from A to B with a basic level of protection. This is not a tutorial for high end cryptography and it shouldn’t be used for 007 missions.
>>> Get started: Encryption
To hide the content of a message or a file you can encrypt it. You need a key to decrypt the message, a key only you keep.
There are many encryption options that you can find. In this case we are going to use GnuPG, it is open source and free. They recommend simple software to handle keys and perform basic en/de-cryption of files:
There are different types of encryption, in this example we will use something called public key encryption. It means that you need two keys, one for the public and one only for yourself. The public key acts as an open safe, where anyone can input data and lock it (encrypt). Then they can send the encrypted data freely and only you know the combination (private key) to decrypt the data.
>>> Creating keys is the first step. In this case we will create a key-pair using a tool rather than using the python libraries, if you already have keys, jump to the next section.
>>> Create a key in Windows using gpg4win.
Click on File>New Certificate…
Choose to create an OpenPGP key pair.
Enter a name and an email, the comment is optional.
You will be asked for a password.
Once you have created your private key it is time to get the public key out of it.
File>Export Certificates… and save it with a simpler name such as bob.asc
You can share this public key and and even upload it to public servers.
>>> Create a key pair on a Mac.
Click in New and type a name, email and password:
You have now a new pair of private and public keys, lets export the public key to share with the world.
Click export and save it with your name.
>>> Encrypt data using Python
Now that you have your private and public key it is time to encrypt a message.
Since the idea behind the internet of things is to have an embedded computer such as a Raspberry Pi or BeagleBone to send and/or receive the messages and make it easy, we will use python on Linux.
Make sure you have downloaded and installed Python in your system.
For installation in Mac, open Terminal and type (in bash):
sudo pip install python-gnupg
Once installed we can add the library to our python script in parts:
(The entire code can also be found below)
import gnupg gpg = gnupg.GPG() from pprint import pprint
I also added pprint which helps to visualize data easier, this is optional. More about pprint module.
Next, tell the computer where your keys are:
gpg = gnupg.GPG(gnupghome='/Users/Bob/GPG/keys/')
Choose your own path, I recommend to create your own folder and export your keys in a separate private and public folder, keep them safe.
Now import your keys by uncommenting (removing the ‘ ‘ ‘ at the top and bottom of each section):
#import ''' print '------------import------------' key_data = open('/Users/Bob/GPG/keys/private/alice_roberts.asc').read() print key_data import_result = gpg.import_keys(key_data) pprint(import_result.results) '''
Make sure to import the public key of your recipient but also your private key to be able to decrypt incoming messages, so run this for each key at least once.
To encrypt a string:
#encrypt string unencrypted_string = 'Hello, secret friend!' encrypted_data = gpg.encrypt(unencrypted_string, 'email@example.com', always_trust = True) encrypted_string = str(encrypted_data) print 'encrypt ok: ', encrypted_data.ok print 'status: ', encrypted_data.status print 'stderr: ', encrypted_data.stderr print 'unencrypted_string: ', unencrypted_string print 'encrypted_string: ', encrypted_string
In this example the recipient is the key I just created (firstname.lastname@example.org), but you can put here the recipients email or name. I set the option always_trust = True because I know that the creator of the key is legit and not fake, make sure you validate this too.
You will see the encrypted message:
—–BEGIN PGP MESSAGE—–
Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
—–END PGP MESSAGE—–
We know it actually says: ‘ Hello, secret friend! ’ but nobody else in the world does.
To decrypt the message use:
#decrypt string decrypted_data = gpg.decrypt(encrypted_string, passphrase='password') print 'ok: ', decrypted_data.ok print 'status: ', decrypted_data.status print 'stderr: ', decrypted_data.stderr print 'decrypted string: ', decrypted_data.data
Replace the password with your own. You will see the result:
status: decryption ok
stderr: [GNUPG:] ENC_TO 9984602FB3FD98E6 1 0
[GNUPG:] USERID_HINT 9984602FB3FD98E6 alice roberts <email@example.com>
[GNUPG:] NEED_PASSPHRASE 9984602FB3FD98E6 08C2B4985C75852E 1 0
gpg: encrypted with 2048-bit RSA key, ID B3FD98E6, created 2014-09-09
“alice roberts <firstname.lastname@example.org>”
[GNUPG:] DECRYPTION_INFO 2 9
[GNUPG:] PLAINTEXT 62 1410391068
[GNUPG:] PLAINTEXT_LENGTH 21
decrypted string: Hello, secret friend!
Process finished with exit code 0
You have created a key, imported it, encrypted and decrypted a message!
Here is the code as a whole:
import gnupg gpg = gnupg.GPG() from pprint import pprint #create path to store keys gpg = gnupg.GPG(gnupghome='/Users/Bob/GPG/keys/') #import ''' print '------------import------------' key_data = open('/Users/Bob/GPG/keys/public/alice_roberts.asc').read() print key_data import_result = gpg.import_keys(key_data) pprint(import_result.results) ''' #list keys ''' print '-----------list----------' gpg = gnupg.GPG(gnupghome='/Users/Bob/GPG/keys/') public_keys = gpg.list_keys() private_keys = gpg.list_keys(True) print 'public keys:' pprint(public_keys) print 'private keys:' pprint(private_keys) ''' #encrypt string ''' unencrypted_string = 'Hello, secret friend!' encrypted_data = gpg.encrypt(unencrypted_string, 'email@example.com', always_trust = True) encrypted_string = str(encrypted_data) print 'encrypt ok: ', encrypted_data.ok print 'status: ', encrypted_data.status print 'stderr: ', encrypted_data.stderr print 'unencrypted_string: ', unencrypted_string print 'encrypted_string: ', encrypted_string ''' #decrypt string ''' decrypted_data = gpg.decrypt(encrypted_string, passphrase='password') print 'ok: ', decrypted_data.ok print 'status: ', decrypted_data.status print 'stderr: ', decrypted_data.stderr print 'decrypted string: ', decrypted_data.data '''
Uncomment the required parts.
>>> Sending encrypted messages through Azure Service Bus.
Once you have successfully created the tools to encrypt and decrypt messages in python we can simply add the required lines of code to send the encrypted messages through the Cloud to anywhere you want.
Azure Service Bus is a Microsoft service that lets you send information contained in messages no larger than 64kB (Iver 64k is possible but it counts as multiple messages!), you can send millions if you want either in a queue format or a subscription. To learn more about Azure Service bus click here.
Follow this instructions to set up an Azure account.
You will learn about how to set up an account and then a queue, read it through to get the idea.
The following is the code as a whole, I will explain each part below:
from azure.servicebus import * import gnupg #gpg = gnupg.GPG() from pprint import pprint #create path to store keys gpg = gnupg.GPG(gnupghome='/Users/Bob/GPG/keys') #import key ''' key_data = open('/Users/Bob/GPG/keys/public/alice_roberts.asc').read() print key_data import_result = gpg.import_keys(key_data) pprint(import_result.results) ''' bus_service = ServiceBusService(service_namespace='sensornetwork', account_key='s8S0GXhTNLOHrfsEdww/QE0+UYZIVxss8TK7CQkg29Y=', issuer='owner') queuename = 'taskqueue' #bus_service.create_queue(queuename) #uncomment to create a queue, only once #encrypt unencrypted_string = "End of SB Session" encrypted_data = gpg.encrypt(unencrypted_string, 'firstname.lastname@example.org', always_trust = True) encrypted_string = str(encrypted_data) print 'successful encryption: ', encrypted_data.ok
#send through service bus encrypted_msg = Message(encrypted_string) bus_service.send_queue_message(queuename, encrypted_msg) print 'Message sent to the queue:', queuename print 'Body:' , encrypted_string #receive messages while True: #msg = bus_service.read_delete_queue_message('taskqueue') msg = bus_service.receive_queue_message ('taskqueue') #peek_lock=True print 'Body: ',(msg.body) decrypted_data = gpg.decrypt(msg.body, passphrase='password') print 'successful decryption: ', decrypted_data.ok print 'Message Content: ', decrypted_data.data msg.delete() if (decrypted_data.data == 'End of SB Session'): print 'Received message: "End of SB Session"' break print 'python script finished.'
First you import both libraries, one for the Service Bus, and the other for the GnuPG.
After importing the keys you find the service bus settings. This is where you must add your own namespace, account_key (not related with the encryption), and issuer.
Create a queue to target your messages. You can have many different queues or topics for different themes. If you want to have specific topics that specific recipients should read, then don’t use queues and check out Service Bus Topics and Subscriptions.
The encryption is the same as before.
Then we send the encrypted string via the Service bus to our queue, make sure you create one queue first.
The encrypted message gets added into a Message which is sent to the cloud and stored in the cloud until you retrieve it.
To receive the message I created a “while True”, this will then run until a break is sent.
The code will fetch messages, decrypt them, print them, delete them and check if they match a specific string that I called ‘End of SB Session’.
To read the message only once, you can remove msg.delete(), otherwise the messages will stray in the cloud, you need to manage this.
Congratulations, you can now send and receive encrypted messages through the cloud. Add some sensors and report the data confidentially. Take a look at the Geiger Counter example,
by Martin Garcia (plusmartin.com) & Steven Johnston