droidcon london 2014 - running your own software licensing system

Post on 02-Jul-2015

344 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

This talks takes you through the steps you should think about when running a software licensing system and provides some code examples of the cryptographic methods you may want to use to create and read secure license information

TRANSCRIPT

Funky Android Ltd.http://www.funkyandroid.com/

Running your own software licensing system

www.funkyandroid.com

Why?

• Give your users cross-store purchases

• Provision purchases from other channels

• Isolate yourself from any single sales channel

www.funkyandroid.com

Things to remember

• Perfect security isn’t currently feasible

• The aim is to make the cost of cracking greater than the value gained from the crack

• It’s up to you how much you want any cracker to have to “pay” to crack your app

www.funkyandroid.com

How does it work?

www.funkyandroid.com

What are we doing?

Securing information between two places

www.funkyandroid.com

What are we doing?

Securing information between two places

Validate Contents?

www.funkyandroid.com

Validate Contents

• Make sure this is a current, valid license.

• Replay attacks; Old data getting a second, third, fourth, ….. outing.

• Add a timestamp to both request and response and reject “old” responses.

• Add a random one-time ID in the request which the server adds to the response.

www.funkyandroid.com

What are we doing?

Securing information between two places

Verify Sender?Validate Contents?

www.funkyandroid.com

Verify Sender

• SSL - one option, but has to be done securely (e.g. certificate pinning)

• Asymmetric Crypto - Public/Private key

• If the keys don’t match then the data won’t decrypt correctly.

www.funkyandroid.com

What do you need?

www.funkyandroid.com

A Server

www.funkyandroid.com

A Server

www.funkyandroid.com

A License Source

www.funkyandroid.com

License Source

• Could be a server.

• Could be your desktop.

• Could even be an Android device.

• It’s all about capacity!

www.funkyandroid.com

A key pair

• Asymmetric Cryptography.

• The private key is…. well…. private.

• The public key is in your application.

• Use the private key to encrypt the license, and the public key can decrypt it.

www.funkyandroid.com

A standard format

• Create one yourself

• You can use multiple forms of cryptography

• You can checksum blocks

www.funkyandroid.com

Hidden decryption

• In-App license verification code shouldn’t be easy to find.

• The more effort you put into hiding it, the harder it is to crack

• Think about using time limited licenses that need refreshing.

www.funkyandroid.com

Hidden decryption

Evading Pirates and Stopping Vampires

http://www.youtube.com/watch?v=TnSNCXR9fbY

www.funkyandroid.com

Long licenses• Asymmetric Cryptography tends to be

relatively slow, so may not make sense for lots of data

• Asymmetrically Encrypt a “session key” - A key for that license

• Asymmetrically Encrypt a checksum of the data encrypted using the session data

• Use AES encryption for speed.

www.funkyandroid.com

The Code

www.funkyandroid.com

Key Generation

import java.security.*;

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");

kpg.initialize(2048, new SecureRandom());

KeyPair keys = kpg.generateKeyPair();

www.funkyandroid.com

Key -> byte[ ]

PrivateKey privateKey = keys.getPrivate();

byte[] privBytes = privateKey.getEncoded();

PublicKey publicKey = keys.getPublic();

byte[] pubBytes = publicKey.getEncoded();

www.funkyandroid.com

byte[ ] -> Private Key

PKCS8EncodedKeySpec skeySpec = new PKCS8EncodedKeySpec(privBytes);

KeyFactory keyFactory = KeyFactory.getInstance(“RSA”);

PrivateKey privateKey = keyFactory.generatePrivate(skeySpec);

www.funkyandroid.com

Encrypt License

Cipher cipher = Cipher.getInstance(“RSA”);

cipher.init(Cipher.ENCRYPT_MODE, privateKey);

byte[] encryptedLicense = cipher.doFinal(licenseBytes);

www.funkyandroid.com

byte[ ] -> Public Key

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubBytes);

KeyFactory factory = KeyFactory.getInstance(“RSA");

PublicKey publicKey = factory.generatePublic(keySpec);

www.funkyandroid.com

Decrypt License

Cipher cipher = Cipher.getInstance(“RSA”);

cipher.init(Cipher.DECRYPT_MODE, publicKey);

byte[] licenseBytes = cipher.doFinal(encryptedLicense);

www.funkyandroid.com

“Session Key”import java.security.*;

KeyGenerator keyGen = KeyGenerator.getInstance("AES");

keyGen.init(128);

SecretKey key = keyGen.generateKey();

* 128 bit key because that’s Oracle’s default maximum AES key length.

www.funkyandroid.com

key -> byte [ ]

byte[] sessionKeyBytes = key.getEncoded()

www.funkyandroid.com

byte[ ] -> key

SecretKeySpec skeySpec =  new SecretKeySpec(sessionKeyBytes, "AES"); 

www.funkyandroid.com

AES/CBC/PKCS5Padding

• AES - Can encrypt blocks of data (1 block is 128 bits - 16 bytes)

• CBC - Cipher Block Chaining - One block relies on the previous block

• PKCS5Padding - Ensure blocks of data are the right size to be chained.

www.funkyandroid.com

Encrypt Data

Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

byte[] encryptedData = cipher.doFinal(data);

byte[] initialisationVector = cipher.getIV();

www.funkyandroid.com

Decrypt DataCipher cipher = Cipher.getInstance(“AES/CBC/PKCS5Padding");

cipher.init( Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec( initialisationVector ) );

byte[] data = cipher.doFinal(encryptedData);

Funky Android Ltd.http://www.funkyandroid.com/

Questions ?

top related