/* * Copyright (c) 2015 Jarrad Hope * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package io.syng.util; import android.util.Base64; import android.util.Log; import java.security.SecureRandom; import java.security.spec.KeySpec; import java.util.regex.Pattern; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; public class Encryption { private static final String TAG = "Encryption"; private static SecureRandom random = new SecureRandom(); private static String delimiter = "}"; private static int keyLength = 256; private static int saltLength = keyLength / 8; private static int iterationCount = 20000; public static String encrypt(String text, String password) { Log.d(TAG, "Encrypting: " + text); String encryptedText = ""; byte[] salt = generateSalt(saltLength); SecretKey key = generateKey(password, salt); if (key != null) { try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); byte[] iv = new byte[cipher.getBlockSize()]; random.nextBytes(iv); IvParameterSpec ivParams = new IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, key, ivParams); byte[] encryptedKey = cipher.doFinal(text.getBytes("UTF-8")); encryptedText = Base64.encodeToString(salt, Base64.NO_WRAP); encryptedText += delimiter + Base64.encodeToString(iv, Base64.NO_WRAP); encryptedText += delimiter + Base64.encodeToString(encryptedKey, Base64.NO_WRAP); Log.d(TAG, "Encrypted: " + encryptedText); return encryptedText; } catch (Exception e) { Log.e(TAG, "encrypt(): " + e.toString()); } } return null; } private static byte[] generateSalt(int saltLength) { byte[] salt = new byte[saltLength]; random.nextBytes(salt); return salt; } private static SecretKey generateKey(String password, byte[] salt) { try { KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, keyLength); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); return new SecretKeySpec(keyBytes, "AES"); } catch (Exception e) { Log.e(TAG, "generateKey(): " + e.toString()); } return null; } public static String decrypt(String encryptedText, String password) { Log.d(TAG, "Decrypting: " + encryptedText); String[] parts = encryptedText.split(Pattern.quote(delimiter)); byte[] salt = Base64.decode(parts[0], Base64.NO_WRAP); byte[] iv = Base64.decode(parts[1], Base64.NO_WRAP); byte[] cipherBytes = Base64.decode(parts[2], Base64.NO_WRAP); SecretKey key = generateKey(password, salt); if (key != null) { try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); IvParameterSpec ivParams = new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, key, ivParams); byte[] decrypted = cipher.doFinal(cipherBytes); String decryptedText = new String(decrypted, "UTF-8"); Log.d(TAG, "Decrypted: " + decryptedText); return decryptedText; } catch (Exception e) { Log.e(TAG, "decrypt(): " + e.toString()); } } return null; } }