Droidcon London 2014 - Running Your Own Software Licensing System
-
Upload
al-sutton -
Category
Technology
-
view
344 -
download
1
description
Transcript of Droidcon London 2014 - Running Your Own Software Licensing System
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
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
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
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);