Skip to content

Commit

Permalink
added DES encryption to Android shared preferences based on pull requ…
Browse files Browse the repository at this point in the history
…est from darko1002001.
  • Loading branch information
pegli committed Aug 7, 2012
1 parent bd8ab87 commit bf5d5c3
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 105 deletions.
33 changes: 22 additions & 11 deletions mobile/android/example/app.js
Expand Up @@ -7,7 +7,9 @@
// open a single window
var window = Ti.UI.createWindow({
backgroundColor:'white',
layout: 'vertical'
});

var label = Ti.UI.createLabel({
top: 20,
height: 30,
Expand All @@ -19,48 +21,57 @@ window.add(label);

var button1 = Ti.UI.createButton({
title: 'set account',
top: 60,
top: 10,
height: 30,
width: 100,
width: 200,
});
button1.addEventListener('click', function() {
keychainItem.account = 'pegli';
Ti.API.info("new account = "+keychainItem.account);
label.text = "new account = "+keychainItem.account;
});
window.add(button1);

var button2 = Ti.UI.createButton({
title: 'set password',
top: 100,
top: 10,
height: 30,
width: 100,
width: 200,
});
button2.addEventListener('click', function() {
keychainItem.valueData = 'supersecret';
Ti.API.info("new password = "+keychainItem.valueData);
label.text = "new password = "+keychainItem.valueData;
});
window.add(button2);

var button3 = Ti.UI.createButton({
title: 'reset keychain item',
top: 140,
top: 10,
height: 30,
width: 100,
width: 200,
});
button3.addEventListener('click', function() {
keychainItem.reset();
Ti.API.info("reset item, account = "+keychainItem.account);
label.text = "reset item, account = "+keychainItem.account;
});
window.add(button3);

var button4 = Ti.UI.createButton({
title: 'get keychain item',
top: 10,
height: 30,
width: 200,
});
button4.addEventListener('click', function() {
label.text = "account = " + keychainItem.account + "; password = " + keychainItem.valueData;
});
window.add(button4);


window.open();

// TODO: write your module tests here
var keychain = require('com.obscure.keychain');
Ti.API.info("module is => " + keychain);

var keychainItem = keychain.createKeychainItem('mylogin');
Ti.API.info("account = " + keychainItem.account + "; password = " + keychainItem.valueData);
var keychainItem = keychain.createKeychainItem('mylogin', 'supersecretpassphrase');
Ti.API.info("account = " + keychainItem.account + "; password = " + keychainItem.valueData);
48 changes: 48 additions & 0 deletions mobile/android/src/com/obscure/keychain/DesEncryptor.java
@@ -0,0 +1,48 @@
package com.obscure.keychain;

import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import android.util.Base64;

/**
* This class defines methods for encrypting and decrypting using the Triple DES
* algorithm and for generating, reading and writing Triple DES keys. It also
* defines a main() method that allows these methods to be used from the command
* line.
*/
public class DesEncryptor {

Cipher ecipher;

Cipher dcipher;

byte[] salt = { (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03 };

public DesEncryptor(String passPhrase) throws Exception {
int iterationCount = 2;
KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
ecipher = Cipher.getInstance(key.getAlgorithm());
dcipher = Cipher.getInstance(key.getAlgorithm());

AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);

ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
}

public String encrypt(String str) throws Exception {
return Base64.encodeToString(ecipher.doFinal(str.getBytes()), Base64.DEFAULT);
}

public String decrypt(String str) throws Exception {
return new String(dcipher.doFinal(Base64.decode(str, Base64.DEFAULT)));
}
}
159 changes: 98 additions & 61 deletions mobile/android/src/com/obscure/keychain/KeychainItemProxy.java
Expand Up @@ -4,72 +4,109 @@
import org.appcelerator.kroll.KrollProxy;
import org.appcelerator.kroll.annotations.Kroll;
import org.appcelerator.titanium.TiContext;
import org.appcelerator.titanium.util.TiConfig;

import android.content.ContextWrapper;
import android.content.SharedPreferences;
import android.util.Log;

// This proxy can be created by calling Keychain.createExample({message: "hello world"})
@Kroll.proxy(creatableInModule = KeychainModule.class)
public class KeychainItemProxy extends KrollProxy {
// Standard Debugging variables
private static final String LCAT = "KeychainItemProxy";
private static final boolean DBG = TiConfig.LOGD;

private static final String ACCOUNT_KEY = "keychain.account";
private static final String VALUE_DATA_KEY = "keychain.valueData";

private SharedPreferences sharedPrefs;
private ContextWrapper androidContext;

// Constructor
public KeychainItemProxy(TiContext tiContext) {
super(tiContext);
androidContext = tiContext.getAndroidContext();
}

@Override
public void handleCreationArgs(KrollModule createdInModule, Object[] args) {
super.handleCreationArgs(createdInModule, args);
if (args != null && args.length > 0) {
String name = String.format("keychain.%s", (String) args[0]);
sharedPrefs = androidContext.getSharedPreferences(name, 0);
}
}

@Kroll.getProperty
@Kroll.method
public String getAccount() {
return sharedPrefs.getString(ACCOUNT_KEY, null);
}

@Kroll.setProperty
@Kroll.method
public void setAccount(String value) {
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putString(ACCOUNT_KEY, value);
editor.commit();
}

@Kroll.getProperty
@Kroll.method
public String getValueData() {
return sharedPrefs.getString(VALUE_DATA_KEY, null);
}

@Kroll.setProperty
@Kroll.method
public void setValueData(String value) {
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putString(VALUE_DATA_KEY, value);
editor.commit();
}

@Kroll.method
public void reset() {
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.remove(ACCOUNT_KEY);
editor.remove(VALUE_DATA_KEY);
editor.commit();
}

private static final String ACCOUNT_KEY = "keychain.account";

private static final String LCAT = "KeychainItemProxy";

private static final String VALUE_DATA_KEY = "keychain.valueData";

private ContextWrapper androidContext;

private DesEncryptor encryptor;

private SharedPreferences sharedPrefs;

// Constructor
public KeychainItemProxy(TiContext tiContext) {
super(tiContext);
androidContext = tiContext.getAndroidContext();
}

private String fetchValueForKey(String key) {
String value = sharedPrefs.getString(key, null);
if (encryptor != null && value != null) {
try {
value = encryptor.decrypt(value);
}
catch (Exception e) {
e.printStackTrace();
}
}
return value;
}

@Kroll.getProperty
@Kroll.method
public String getAccount() {
return fetchValueForKey(ACCOUNT_KEY);
}

@Kroll.getProperty
@Kroll.method
public String getValueData() {
return fetchValueForKey(VALUE_DATA_KEY);
}

@Override
public void handleCreationArgs(KrollModule createdInModule, Object[] args) {
super.handleCreationArgs(createdInModule, args);
if (args != null) {

if (args.length > 0) {
String name = String.format("keychain.%s", (String) args[0]);
sharedPrefs = androidContext.getSharedPreferences(name, 0);
}
if (args.length > 1) {
try {
encryptor = new DesEncryptor((String) args[1]);
}
catch (Exception e) {
Log.d(LCAT, "error creating keystore", e);
}
}
}
}

@Kroll.method
public void reset() {
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.remove(ACCOUNT_KEY);
editor.remove(VALUE_DATA_KEY);
editor.commit();
}

@Kroll.setProperty
@Kroll.method
public void setAccount(String value) {
storeValueForKey(ACCOUNT_KEY, value);
}

@Kroll.setProperty
@Kroll.method
public void setValueData(String value) {
storeValueForKey(VALUE_DATA_KEY, value);
}

private void storeValueForKey(String key, String value) {
if (encryptor != null) {
try {
value = encryptor.encrypt(value);
}
catch (Exception e) {
Log.d(LCAT, "", e);
}
}
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putString(key, value);
editor.commit();
}
}
35 changes: 2 additions & 33 deletions mobile/android/src/com/obscure/keychain/KeychainModule.java
Expand Up @@ -10,44 +10,13 @@

import org.appcelerator.kroll.KrollModule;
import org.appcelerator.kroll.annotations.Kroll;

import org.appcelerator.titanium.TiContext;
import org.appcelerator.titanium.util.Log;
import org.appcelerator.titanium.util.TiConfig;

@Kroll.module(name="Keychain", id="com.obscure.keychain")
public class KeychainModule extends KrollModule
{

// Standard Debugging variables
private static final String LCAT = "KeychainModule";
private static final boolean DBG = TiConfig.LOGD;
@Kroll.module(name = "Keychain", id = "com.obscure.keychain")
public class KeychainModule extends KrollModule {

// You can define constants with @Kroll.constant, for example:
// @Kroll.constant public static final String EXTERNAL_NAME = value;

public KeychainModule(TiContext tiContext) {
super(tiContext);
}

// Methods
@Kroll.method
public String example() {
Log.d(LCAT, "example called");
return "hello world";
}

// Properties
@Kroll.getProperty
public String getExampleProp() {
Log.d(LCAT, "get example property");
return "hello world";
}


@Kroll.setProperty
public void setExampleProp(String value) {
Log.d(LCAT, "set example property: " + value);
}

}

0 comments on commit bf5d5c3

Please sign in to comment.