Skip to content

Commit

Permalink
Security Module basics complete. Added security.Master
Browse files Browse the repository at this point in the history
  • Loading branch information
sasinda committed Aug 1, 2012
1 parent 1682536 commit e0c73ef
Show file tree
Hide file tree
Showing 6 changed files with 803 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@


import org.xwiki.android.rest.reference.DocumentReference;
import org.xwiki.android.security.Master;

import org.xwiki.android.xmodel.entity.Document;
import com.j256.ormlite.dao.Dao;

Expand All @@ -20,13 +22,16 @@
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
/**
* class for test purposes .
* @author xwiki gsoc 2012
*
*/
public class QuickTest extends Activity {
@Override
private static final String TAG = "Quikc TEST";

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Expand All @@ -39,7 +44,7 @@ public void onClick(DialogInterface arg0, int arg1){}
});
alertbox.show();

XWikiApplicationContext ctx=(XWikiApplicationContext)getApplicationContext();
/*XWikiApplicationContext ctx=(XWikiApplicationContext)getApplicationContext();
EntityManager em=ctx.newEntityManager();
try {
Dao<SyncOutEntity,Integer> dao=em.getDao(SyncOutEntity.class);
Expand All @@ -55,10 +60,14 @@ public void onClick(DialogInterface arg0, int arg1){}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// RESTfulManager mngr=new XmlRESTFulManager();
// } // mngr.getDocumentRao(new DocumentRaoCallback(){});
}*/

//test enc
Master secMstr=new Master();
String cipher=secMstr.encryptPassword("abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()");
Log.d( TAG, cipher);
Log.d(TAG, secMstr.decryptPassword(cipher));

}

}
53 changes: 34 additions & 19 deletions xwiki-android-core/src/org/xwiki/android/entity/User.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.xwiki.android.entity;

import org.xwiki.android.security.Master;

import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;

Expand All @@ -22,15 +24,34 @@ public class User implements Cloneable
@DatabaseField(canBeNull = false, uniqueCombo = true, useGetSet = true)
private String userName;

@DatabaseField(useGetSet = true)
private String password;// todo: when enc enable. Use pers field encPwd instead of pwd and make getPassword()
// decrypt and store val in pwd field
@DatabaseField()
private String encPassword;

private String password;

@DatabaseField(useGetSet = true)
private String email;

@DatabaseField(uniqueCombo = true, useGetSet = true)
private String wikiRealm;

// constructors
public User()
{
}

public User(String firstName, String lastName, String userName, String password, String wikiRealm, String email)
{
super();
this.firstName = firstName;
this.lastName = lastName;
this.userName = userName;
this.password = password;
this.email = email;
this.wikiRealm = wikiRealm;
}



public String getWikiRealm()
{
Expand Down Expand Up @@ -84,12 +105,18 @@ public void setUserName(String userName)
}

/**
* use security utils to decrypt the pwd. return The decrypted pwd. null if not stored
* uses security utils to decrypt the pwd. return The decrypted pwd. null if not stored
*
* @return encrypted Password
*/
public String getPassword()
{
if (password == null) {
Master m = new Master();
if (encPassword != null) {
password = m.decryptPassword(encPassword);
}
}
return password;
}

Expand All @@ -99,6 +126,8 @@ public String getPassword()
public void setPassword(String password)
{
this.password = password;
this.encPassword = new Master().encryptPassword(password);

}

public String getEmail()
Expand All @@ -123,20 +152,6 @@ public User clone()
return u;
}

// constructors
public User()
{
}

public User(String firstName, String lastName, String userName, String password, String wikiRealm, String email)
{
super();
this.firstName = firstName;
this.lastName = lastName;
this.userName = userName;
this.password = password;
this.email = email;
this.wikiRealm = wikiRealm;
}


}
171 changes: 171 additions & 0 deletions xwiki-android-core/src/org/xwiki/android/security/Master.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package org.xwiki.android.security;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;

import org.xwiki.android.security.util.Base64;

import android.util.Log;

/**
* @author xwiki gsoc 2012
* This is the Master class that will encrypt decrypt all user passwords.
* This has methods to generate private keys for users and keep them safe.
* All user's private secret keys are encrypted using the master key.
*/
public class Master
{

private static final String TAG = "Security";
SecretKeySpec masterKey;
Cipher masterCipher;


public Master()
{
masterKey = getMasterKey();
try {
masterCipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "ENC algo missing: pwds will be saved in plaintext", e);
} catch (NoSuchPaddingException e) {
Log.e(TAG, "Padding scheme missing: pwds will be saved in plaintext", e);
}


}

/**
* Encrypt a secret string.
* @param plainTextPwd
* @return BASE64 encoded password cypher text string.
*/
public String encryptPassword(String plainTextPwd)
{
if (masterCipher == null)
return plainTextPwd;

byte[] input = null;

try {
input = plainTextPwd.getBytes("UTF8");
masterCipher.init(Cipher.ENCRYPT_MODE, masterKey);
byte[] output = new byte[masterCipher.getOutputSize(input.length)];
int outputLen = masterCipher.update(input, 0, input.length, output, 0);
masterCipher.doFinal(output, outputLen);
String out=Base64.encodeToString(output, true);
return out;
} catch (InvalidKeyException e) {
Log.e(TAG, "invalid key. In Master");
} catch (ShortBufferException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
Log.d(TAG, "", e);

} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
Log.e(TAG, "UTF8 not supported ?");
}
return plainTextPwd;
}

/**
*
* @param pwdCipherText : base 64 encoded cypher text.
* @return UTF8 encoded plain text.
*/
public String decryptPassword(String pwdCipherText)
{
if (masterCipher == null)
return pwdCipherText;

byte[] input = null;

try {
input =Base64.decode(pwdCipherText);
masterCipher.init(Cipher.DECRYPT_MODE, masterKey);
/*byte[] output = new byte[masterCipher.getOutputSize(input.length)];
int outputLen = masterCipher.update(input, 0, input.length, output, 0);
masterCipher.doFinal(output, outputLen);*/
byte[] output=masterCipher.doFinal(input);
return new String(output, "UTF8");
} catch (InvalidKeyException e) {
Log.e(TAG, "invalid key. In Master");
// } catch (ShortBufferException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "UTF8 not supported ?");
}
return pwdCipherText;
}
/**
* Encrypt a secret key.
* @param key as a encoded String.
* @return BASE64 encoded password cypher text string.
*/
public String encryptKey(String key){
return encryptPassword(key);
}
/**
*
* @param keyCipher should be a base64 encoded string.
* @return key base64 coded key String coded again with UTF8.
*/
public String decryptKey(String keyCipher){
return decryptPassword(keyCipher);
}

public byte[] generateRawKey(String algorithm){
// Generate a key
KeyGenerator keyGen;
try {
keyGen = KeyGenerator.getInstance(algorithm);
SecretKey key = keyGen.generateKey();

// Get the bytes of the key
byte[] keyBytes = key.getEncoded();
return keyBytes;
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}

public String generateEncKey(String algorithm){
byte[] keyBytes=generateRawKey(algorithm);
return Base64.encodeToString(keyBytes, true);
}

private SecretKeySpec getMasterKey()
{
byte[] keyBytes =
new byte[] {0x01, 0x05, 0x07, 0x03, 0x04, 0x08, 0x05, 0x12, 0x17, 0x09, 0x0a, 0x0c, 0x05, 0x09, 0x1e, 0x1a,
0x1a, 0x11, 0x14, 0x13, 0x14, 0x19, 0x16, 0x17};
// TODO save this somewhere safe ;-)
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
return key;
}

}
Loading

1 comment on commit e0c73ef

@sasinda
Copy link
Contributor Author

@sasinda sasinda commented on e0c73ef Aug 1, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now user passwords are encrypted and saved in the SQLite DB.

Please sign in to comment.