Encrypted vCards on server

Matrix codes appear everywhere. They often represent a URL pointing to a web page where more information can be found. Matrix codes can be scanned and decoded using a smart phone camera combined with an appropriate application. I can print a matrix code on my card which points to my vCard file on a server. A person I gave my card can scan the code and get more up to date and complete contact information than that printed in clear text. But I don’t like the idea of leaving my contact information openly on a server ready for search robots and other snoopers to take. Therefore the need for encryption.

Examples of QR matrix and Datamatrix codes

Left: QR matrix, right: Datamatrix

Modern encryption is based on pubilic/private key pairs, but is in this setting not practical. The key itself must be available to the person holding the card. The easy way to do this is by including the in the URL of the matrix code.
As an example the URL given by the matrix codes you can see in this post is

http://oao.no/cgi-bin/card.vcf?gump=123456.

Here ‘gump’ is the vCard file name and ‘123456’ is the key. It is important to restrict the key to a reasonable length else the matrix will be very large.

I want to write the en/de-cryption programs in Python. The Python standard libraries are weak when it comes to encryption and the usable ones may not be present on the server. Instead of using a crypt library I chose to use a method which only needs one line of code: exclusive-or. Exclusive-or is a very secure method if the key is random and as long as the message. However, I must keep the key short. I could have produced a long key by repeating a short key. vCard files contain many long and well known strings and would therefore be trivial to decrypt if encrypted by a short repeating key. Based on the short key found in the URL I therefore create a long key string by SHA-hashing. The hash is always 20 bytes long. To make the key as long as the vCard file, I add as many hashes as are needed. I generate the hashes by adding a letter to the key for each hash. These hashes are not related (one can not find the hash of ‘key+a letter’ if the hash of ‘key’ is known but not ‘key’). I thus get a long not-repeating key. Note, however, that the security of this method is not better than that given by the key length, the hashing only makes it more difficult to find the key based on the known strings within the file.

Encryption program

This is the encryption Python program I run on my PC. It asks for the original vCard file name and outputs the result in the ./c-directory. I then copy this file to the server under a vcf-directory.

import sys
import sha
import string

print "vcf-file: "
fstr= sys.stdin.readline().strip()
fi= open(fstr, "r")
card= fi.read()
fi.close()
secret="123456"
key= ''
i= 0
while len(key) <len(card):
      hash= sha.new()
      secret= secret + string.letters[i%26]
      hash.update(secret)
      key= key + hash.digest()
      print secret, hash.hexdigest()
      i= i+1
print "keylen: ", len(key), len(card)#, key
crypted=''.join(chr(ord(a)^ord(b)) for a,b in zip(key, card))
fstr= "c/" + fstr.split("/")[-1] + '.cr'
print "fstr: <%s>"%fstr
fo= open(fstr, "w")
fo.write(crypted)
fo.close()

cgi- program

On the server the following python cgi-script gets the query string and from that the file name and key. Then reads the encrypted vCard file, decrypts and returns the file to the browser. Many browsers will ask if you want to import the file into a contact application; or you may save the file.

#!/usr/bin/python
try:
      import os
      import sha
      import string
except:
      print "Content-type: text/html\n\n"
      print "<html><head></head><body>"
      print "Import error"
      print "</body></html>"
try:
     par= os.environ.get("QUERY_STRING")
     name, secret= par.split('=')
     fi= open("../vcf/%s.vcf.cr"%name, "r")
     card= fi.read()
     fi.close()
except:
     print "Content-type: text/html\n\n"
     print "<html><head></head><body>"
     print "Query string problem or error opening vcf-file", par, name, secret
     print "</body></html>"
else:
     key= ""
     i= 0
     while len(key) < len(card):
          hash= sha.new()
          secret= secret + string.letters[i%26]
          hash.update(secret)
          key= key + hash.digest()
          i= i+1
     plain= ''.join(chr(ord(a)^ord(b)) for a,b in zip(key, card))
     print "Content-type: text/x-vcard\n\n"
     print plain

The name of this script is card.vcf which will help some web browser to recognize the response as a vCard file. Remember to set the execute-bits of the script permissions, you may also have to specify a server execute handle for ‘.vcf’ files.

You can get to an example vCard on my server by this URL:
http://oao.no/cgi-bin/card.vcf?gump=123456
which is also the URL you get if you scan the matrix codes above.

Create keyword

This Python program will create a random eight character long string  for you

import string
import random
avail= string.letters + string.digits + string.digits
key=""
for i in range(8):
        key= key + random.choice(avail)
print key

0 Responses to “Encrypted vCards on server”


  • No Comments

Leave a Reply