Commit c7adbfc6 authored by Corentin Mors's avatar Corentin Mors
Browse files

Change encryption system and make first working chat

parent 80a7d948
......@@ -12,6 +12,7 @@ import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Base64;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
......@@ -27,9 +28,20 @@ import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;
import java.util.ArrayList;
import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
......@@ -39,7 +51,7 @@ import io.socket.emitter.Emitter;
*/
public class ChatFragment extends Fragment {
private static final String TAG = "ChatFragment";
private static final String TAG = "OM_ChatFragment";
private static final int REQUEST_LOGIN = 0;
......@@ -54,6 +66,8 @@ public class ChatFragment extends Fragment {
private String mUsername;
private Socket mSocket;
private String mPassword = "azerty";
private Boolean isConnected = true;
public ChatFragment() {
......@@ -89,8 +103,8 @@ public class ChatFragment extends Fragment {
mSocket.on("new message", onNewMessage);
mSocket.on("user joined", onUserJoined);
mSocket.on("user left", onUserLeft);
mSocket.on("typing", onTyping);
mSocket.on("stop typing", onStopTyping);
//mSocket.on("typing", onTyping);
//mSocket.on("stop typing", onStopTyping);
mSocket.connect();
startSignIn();
......@@ -232,17 +246,23 @@ public class ChatFragment extends Fragment {
mTyping = false;
String message = mInputMessageView.getText().toString().trim();
if (TextUtils.isEmpty(message)) {
mInputMessageView.requestFocus();
return;
}
String message = null;
try {
message = mInputMessageView.getText().toString().trim();
if (TextUtils.isEmpty(message)) {
mInputMessageView.requestFocus();
return;
}
mInputMessageView.setText("");
addMessage(mUsername, message);
mInputMessageView.setText("");
addMessage(mUsername, message);
// perform the sending message attempt.
mSocket.emit("new message", sencrypt(mPassword, message));
} catch (Exception e) {
e.printStackTrace();
}
// perform the sending message attempt.
mSocket.emit("new message", message);
}
private void startSignIn() {
......@@ -263,6 +283,44 @@ public class ChatFragment extends Fragment {
mMessagesView.scrollToPosition(mAdapter.getItemCount() - 1);
}
private static String encrypt(String raw, String clear) throws Exception {
byte[] salt = new String("12345678").getBytes("Utf8");
int iterationCount = 2048;
int keyStrength = 256;
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(raw.toCharArray(), salt, iterationCount, keyStrength);
SecretKey tmp = factory.generateSecret(spec);
//SecretKeySpec skeySpec = new SecretKeySpec(raw.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, tmp);
byte[] encrypted = cipher.doFinal(clear.getBytes());
return encrypted.toString();
}
private static String sencrypt(String password, String data) throws Exception {
CryptLib cryptLib = new CryptLib();
String iv = "1234123412341234";
return cryptLib.encryptPlainText(data, password, iv);
}
private static String sdecrypt(String password, String data) throws Exception {
CryptLib cryptLib = new CryptLib();
String iv = "1234123412341234";
return cryptLib.decryptCipherText(data, password, iv);
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
private Emitter.Listener onConnect = new Emitter.Listener() {
@Override
public void call(Object... args) {
......@@ -328,7 +386,11 @@ public class ChatFragment extends Fragment {
}
removeTyping(username);
addMessage(username, message);
try {
addMessage(username, sdecrypt(mPassword, message));
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
......
package fr.pixelswap.onmap.onmap;
/*
* MIT License
*
* Copyright (c) 2017 Kavin Varnan
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import android.util.Base64;
public class CryptLib {
/**
* Encryption mode enumeration
*/
private enum EncryptMode {
ENCRYPT, DECRYPT
}
// cipher to be used for encryption and decryption
private Cipher _cx;
// encryption key and initialization vector
private byte[] _key, _iv;
public CryptLib() throws NoSuchAlgorithmException, NoSuchPaddingException {
// initialize the cipher with transformation AES/CBC/PKCS5Padding
_cx = Cipher.getInstance("AES/CBC/PKCS5Padding");
_key = new byte[32]; //256 bit key space
_iv = new byte[16]; //128 bit IV
}
/**
*
* @param inputText Text to be encrypted or decrypted
* @param encryptionKey Encryption key to used for encryption / decryption
* @param mode specify the mode encryption / decryption
* @param initVector Initialization vector
* @return encrypted or decrypted bytes based on the mode
* @throws UnsupportedEncodingException
* @throws InvalidKeyException
* @throws InvalidAlgorithmParameterException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
private byte[] encryptDecrypt(String inputText, String encryptionKey,
EncryptMode mode, String initVector) throws UnsupportedEncodingException,
InvalidKeyException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException {
int len = encryptionKey.getBytes("UTF-8").length; // length of the key provided
if (encryptionKey.getBytes("UTF-8").length > _key.length)
len = _key.length;
int ivlength = initVector.getBytes("UTF-8").length;
if(initVector.getBytes("UTF-8").length > _iv.length)
ivlength = _iv.length;
System.arraycopy(encryptionKey.getBytes("UTF-8"), 0, _key, 0, len);
System.arraycopy(initVector.getBytes("UTF-8"), 0, _iv, 0, ivlength);
SecretKeySpec keySpec = new SecretKeySpec(_key, "AES"); // Create a new SecretKeySpec for the specified key data and algorithm name.
IvParameterSpec ivSpec = new IvParameterSpec(_iv); // Create a new IvParameterSpec instance with the bytes from the specified buffer iv used as initialization vector.
// encryption
if (mode.equals(EncryptMode.ENCRYPT)) {
// Potentially insecure random numbers on Android 4.3 and older. Read for more info.
// https://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html
_cx.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);// Initialize this cipher instance
return _cx.doFinal(inputText.getBytes("UTF-8")); // Finish multi-part transformation (encryption)
} else {
_cx.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);// Initialize this cipher instance
byte[] decodedValue = Base64.decode(inputText.getBytes(), Base64.DEFAULT);
return _cx.doFinal(decodedValue); // Finish multi-part transformation (decryption)
}
}
/***
* This function computes the SHA256 hash of input string
* @param text input text whose SHA256 hash has to be computed
* @param length length of the text to be returned
* @return returns SHA256 hash of input text
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
private static String SHA256 (String text, int length) throws NoSuchAlgorithmException, UnsupportedEncodingException {
String resultString;
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(text.getBytes("UTF-8"));
byte[] digest = md.digest();
StringBuilder result = new StringBuilder();
for (byte b : digest) {
result.append(String.format("%02x", b)); //convert to hex
}
if(length > result.toString().length()) {
resultString = result.toString();
} else {
resultString = result.toString().substring(0, length);
}
return resultString;
}
public String encryptPlainText(String plainText, String key, String iv) throws Exception {
byte[] bytes = encryptDecrypt(plainText, CryptLib.SHA256(key, 32), EncryptMode.ENCRYPT, iv);
return Base64.encodeToString(bytes, Base64.DEFAULT);
}
public String decryptCipherText(String cipherText, String key, String iv) throws Exception {
byte[] bytes = encryptDecrypt(cipherText, CryptLib.SHA256(key, 32), EncryptMode.DECRYPT, iv);
return new String(bytes);
}
public String encryptPlainTextWithRandomIV(String plainText, String key) throws Exception {
byte[] bytes = encryptDecrypt(generateRandomIV16() + plainText, CryptLib.SHA256(key, 32), EncryptMode.ENCRYPT, generateRandomIV16());
return Base64.encodeToString(bytes, Base64.DEFAULT);
}
public String decryptCipherTextWithRandomIV(String cipherText, String key) throws Exception {
byte[] bytes = encryptDecrypt(cipherText, CryptLib.SHA256(key, 32), EncryptMode.DECRYPT, generateRandomIV16());
String out = new String(bytes);
return out.substring(16, out.length());
}
/**
* Generate IV with 16 bytes
* @return
*/
public String generateRandomIV16() {
SecureRandom ranGen = new SecureRandom();
byte[] aesKey = new byte[16];
ranGen.nextBytes(aesKey);
StringBuilder result = new StringBuilder();
for (byte b : aesKey) {
result.append(String.format("%02x", b)); //convert to hex
}
if (16 > result.toString().length()) {
return result.toString();
} else {
return result.toString().substring(0, 16);
}
}
}
\ No newline at end of file
......@@ -28,7 +28,7 @@ public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.ViewHold
layout = R.layout.item_message;
break;
case Message.TYPE_LOG:
//layout = R.layout.item_log;
layout = R.layout.item_log;
break;
case Message.TYPE_ACTION:
//layout = R.layout.item_action;
......
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="8dp">
<TextView
android:id="@+id/message"
style="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"/>
</LinearLayout>
\ No newline at end of file
......@@ -4,6 +4,14 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@skavinvarnan/cryptlib": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@skavinvarnan/cryptlib/-/cryptlib-1.0.3.tgz",
"integrity": "sha512-vOD8wOjhp1ONfIfCqVl9HNF1rTsNmLwncoeZPM796+5NCczYWnaHk7CNIfelARppXKd/xu9YoA4dhoIVNJ4GXg==",
"requires": {
"bl": "1.0.0"
}
},
"a-sync-waterfall": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz",
......@@ -173,6 +181,44 @@
"integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==",
"optional": true
},
"bl": {
"version": "1.0.0",
"resolved": "http://registry.npmjs.org/bl/-/bl-1.0.0.tgz",
"integrity": "sha1-ramoqJptesYIYvfex9sgeHPgw/U=",
"requires": {
"readable-stream": "~2.0.0"
},
"dependencies": {
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"readable-stream": {
"version": "2.0.6",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"string_decoder": "~0.10.x",
"util-deprecate": "~1.0.1"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"blob": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
......@@ -386,8 +432,7 @@
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"optional": true
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"debug": {
"version": "4.1.0",
......@@ -2409,8 +2454,7 @@
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"optional": true
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"utils-merge": {
"version": "1.0.1",
......
......@@ -7,6 +7,7 @@
"start": "node app.js"
},
"dependencies": {
"@skavinvarnan/cryptlib": "^1.0.3",
"cookie-parser": "~1.3.3",
"debug": "^4.1.0",
"express": "^4.16.4",
......
This diff is collapsed.
......@@ -72,8 +72,14 @@ $(function() {
var $usernameDiv = $('<span class="username"/>')
.text(data.username)
.css('color', getUsernameColor(data.username));
var $messageBodyDiv = $('<span class="messageBody">')
.text(decrypt(data.message, password));
var $messageBodyDiv = $('<span class="messageBody">');
if(data.typing){
$messageBodyDiv.text(data.message);
}
else{
$messageBodyDiv.text(decrypt(data.message, password));
}
var typingClass = data.typing ? 'typing' : '';
var $messageDiv = $('<li class="message"/>')
......@@ -266,18 +272,23 @@ $(function() {
// Crypto functions
var cryptoLib = require('@skavinvarnan/cryptlib');
var iv = "1234123412341234";
function encrypt(data, password){
try {
return CryptoJS.AES.encrypt(data, password).toString();
shaKey = cryptoLib.getHashSha256(password, 32);
return cryptoLib.encrypt(data, shaKey, iv);
} catch (exception) {
throw new Error(exception.message);
}
}
function decrypt(data, password){
console.log(data);
try {
let bytes = CryptoJS.AES.decrypt(data, password);
return bytes.toString(CryptoJS.enc.Utf8);
shaKey = cryptoLib.getHashSha256(password, 32);
return cryptoLib.decrypt(data, shaKey, iv);
} catch (exception) {
throw new Error(exception.message);
}
......
......@@ -34,5 +34,5 @@
<script src="assets/openlayer.min.js"></script>
<script src="bower_components/crypto-js/crypto-js.js"></script>
<script>var username = "{{ username | escape }}"; var room = "{{ room | escape }}"; var password = "{{ password | escape }}";</script>
<script src="assets/main.js"></script>
<script src="assets/main-bundle.js"></script>
{% endblock %}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment