mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Fix small crypto code
This commit is contained in:
@@ -68,7 +68,7 @@ public class AESTest extends TestCase {
|
||||
mRand.nextBytes(ivArray);
|
||||
IvParameterSpec iv = new IvParameterSpec(ivArray);
|
||||
|
||||
Cipher android = CipherFactory.getInstance("AES/CBC/PKCS5Padding", true);
|
||||
Cipher android = CipherFactory.INSTANCE.getInstance("AES/CBC/PKCS5Padding", true);
|
||||
android.init(Cipher.ENCRYPT_MODE, key, iv);
|
||||
byte[] outAndroid = android.doFinal(input, 0, dataSize);
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public class CipherTest extends TestCase {
|
||||
rand.nextBytes(iv);
|
||||
rand.nextBytes(plaintext);
|
||||
|
||||
CipherEngine aes = CipherFactory.getInstance(AesEngine.CIPHER_UUID);
|
||||
CipherEngine aes = CipherFactory.INSTANCE.getInstance(AesEngine.CIPHER_UUID);
|
||||
Cipher encrypt = aes.getCipher(Cipher.ENCRYPT_MODE, key, iv);
|
||||
Cipher decrypt = aes.getCipher(Cipher.DECRYPT_MODE, key, iv);
|
||||
|
||||
@@ -78,7 +78,7 @@ public class CipherTest extends TestCase {
|
||||
rand.nextBytes(iv);
|
||||
rand.nextBytes(plaintext);
|
||||
|
||||
CipherEngine aes = CipherFactory.getInstance(AesEngine.CIPHER_UUID);
|
||||
CipherEngine aes = CipherFactory.INSTANCE.getInstance(AesEngine.CIPHER_UUID);
|
||||
Cipher encrypt = aes.getCipher(Cipher.ENCRYPT_MODE, key, iv);
|
||||
Cipher decrypt = aes.getCipher(Cipher.DECRYPT_MODE, key, iv);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ class KeyFileHelper {
|
||||
|
||||
override fun onClick(v: View) {
|
||||
try {
|
||||
if (StorageAF.useStorageFramework(activity)) {
|
||||
if (activity != null && StorageAF.useStorageFramework(activity!!)) {
|
||||
openActivityWithActionOpenDocument()
|
||||
} else {
|
||||
openActivityWithActionGetContent()
|
||||
@@ -173,7 +173,7 @@ class KeyFileHelper {
|
||||
if (data != null) {
|
||||
var uri = data.data
|
||||
if (uri != null) {
|
||||
if (StorageAF.useStorageFramework(activity)) {
|
||||
if (activity != null && StorageAF.useStorageFramework(activity!!)) {
|
||||
try {
|
||||
// try to persist read and write permissions
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
@@ -185,7 +185,6 @@ class KeyFileHelper {
|
||||
} catch (e: Exception) {
|
||||
// nop
|
||||
}
|
||||
|
||||
}
|
||||
if (requestCode == GET_CONTENT) {
|
||||
uri = UriUtil.translate(activity, uri)
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
* KeePass DX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePass DX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.crypto;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import com.kunzisoft.keepass.crypto.engine.AesEngine;
|
||||
import com.kunzisoft.keepass.crypto.engine.ChaCha20Engine;
|
||||
import com.kunzisoft.keepass.crypto.engine.CipherEngine;
|
||||
import com.kunzisoft.keepass.crypto.engine.TwofishEngine;
|
||||
|
||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Security;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
public class CipherFactory {
|
||||
private static boolean blacklistInit = false;
|
||||
private static boolean blacklisted;
|
||||
|
||||
static {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
public static Cipher getInstance(String transformation) throws NoSuchAlgorithmException, NoSuchPaddingException {
|
||||
return getInstance(transformation, false);
|
||||
}
|
||||
|
||||
public static Cipher getInstance(String transformation, boolean androidOverride) throws NoSuchAlgorithmException, NoSuchPaddingException {
|
||||
// Return the native AES if it is possible
|
||||
if ( (!deviceBlacklisted()) && (!androidOverride) && hasNativeImplementation(transformation) && NativeLib.INSTANCE.loaded() ) {
|
||||
return Cipher.getInstance(transformation, new AESProvider());
|
||||
} else {
|
||||
return Cipher.getInstance(transformation);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean deviceBlacklisted() {
|
||||
if (!blacklistInit) {
|
||||
blacklistInit = true;
|
||||
|
||||
// The Acer Iconia A500 is special and seems to always crash in the native crypto libraries
|
||||
blacklisted = Build.MODEL.equals("A500");
|
||||
}
|
||||
return blacklisted;
|
||||
}
|
||||
|
||||
private static boolean hasNativeImplementation(String transformation) {
|
||||
return transformation.equals("AES/CBC/PKCS5Padding");
|
||||
}
|
||||
|
||||
|
||||
/** Generate appropriate cipher based on KeePass 2.x UUID's
|
||||
* @param uuid
|
||||
* @return
|
||||
* @throws NoSuchPaddingException
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws InvalidAlgorithmParameterException
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public static CipherEngine getInstance(UUID uuid) throws NoSuchAlgorithmException {
|
||||
if ( uuid.equals(AesEngine.Companion.getCIPHER_UUID()) ) {
|
||||
return new AesEngine();
|
||||
} else if ( uuid.equals(TwofishEngine.Companion.getCIPHER_UUID()) ) {
|
||||
return new TwofishEngine();
|
||||
} else if ( uuid.equals(ChaCha20Engine.Companion.getCIPHER_UUID())) {
|
||||
return new ChaCha20Engine();
|
||||
}
|
||||
throw new NoSuchAlgorithmException("UUID unrecognized.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
* KeePass DX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePass DX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.crypto
|
||||
|
||||
import android.os.Build
|
||||
import com.kunzisoft.keepass.crypto.engine.AesEngine
|
||||
import com.kunzisoft.keepass.crypto.engine.ChaCha20Engine
|
||||
import com.kunzisoft.keepass.crypto.engine.CipherEngine
|
||||
import com.kunzisoft.keepass.crypto.engine.TwofishEngine
|
||||
import org.spongycastle.jce.provider.BouncyCastleProvider
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.security.Security
|
||||
import java.util.*
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.NoSuchPaddingException
|
||||
|
||||
object CipherFactory {
|
||||
|
||||
private var blacklistInit = false
|
||||
private var blacklisted: Boolean = false
|
||||
|
||||
init {
|
||||
Security.addProvider(BouncyCastleProvider())
|
||||
}
|
||||
|
||||
@Throws(NoSuchAlgorithmException::class, NoSuchPaddingException::class)
|
||||
@JvmOverloads
|
||||
fun getInstance(transformation: String, androidOverride: Boolean = false): Cipher {
|
||||
// Return the native AES if it is possible
|
||||
return if (!deviceBlacklisted() && !androidOverride && hasNativeImplementation(transformation) && NativeLib.loaded()) {
|
||||
Cipher.getInstance(transformation, AESProvider())
|
||||
} else {
|
||||
Cipher.getInstance(transformation)
|
||||
}
|
||||
}
|
||||
|
||||
fun deviceBlacklisted(): Boolean {
|
||||
if (!blacklistInit) {
|
||||
blacklistInit = true
|
||||
// The Acer Iconia A500 is special and seems to always crash in the native crypto libraries
|
||||
blacklisted = Build.MODEL == "A500"
|
||||
}
|
||||
return blacklisted
|
||||
}
|
||||
|
||||
private fun hasNativeImplementation(transformation: String): Boolean {
|
||||
return transformation == "AES/CBC/PKCS5Padding"
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate appropriate cipher based on KeePass 2.x UUID's
|
||||
*/
|
||||
@Throws(NoSuchAlgorithmException::class)
|
||||
fun getInstance(uuid: UUID): CipherEngine {
|
||||
return when (uuid) {
|
||||
AesEngine.CIPHER_UUID -> AesEngine()
|
||||
TwofishEngine.CIPHER_UUID -> TwofishEngine()
|
||||
ChaCha20Engine.CIPHER_UUID -> ChaCha20Engine()
|
||||
else -> throw NoSuchAlgorithmException("UUID unrecognized.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,15 +59,12 @@ public class CryptoUtil {
|
||||
byte[] part = hmac.doFinal(pbR);
|
||||
|
||||
int copy = Math.min(cbOut - pos, part.length);
|
||||
assert(copy > 0);
|
||||
|
||||
System.arraycopy(part, 0, ret, pos, copy);
|
||||
pos += copy;
|
||||
r++;
|
||||
|
||||
Arrays.fill(part, (byte)0);
|
||||
}
|
||||
assert(pos == cbOut);
|
||||
}
|
||||
|
||||
Arrays.fill(hash, (byte)0);
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.kunzisoft.keepass.crypto.CipherFactory;
|
||||
public class FinalKeyFactory {
|
||||
public static FinalKey createFinalKey() {
|
||||
// Prefer the native final key implementation
|
||||
if ( !CipherFactory.deviceBlacklisted() && NativeFinalKey.availble() ) {
|
||||
if ( !CipherFactory.INSTANCE.deviceBlacklisted() && NativeFinalKey.availble() ) {
|
||||
return new NativeFinalKey();
|
||||
} else {
|
||||
// Fall back on the android crypto implementation
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
* KeePass DX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePass DX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.fileselect;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.kunzisoft.keepass.R;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Created by bpellin on 3/10/16.
|
||||
*/
|
||||
public class StorageAF {
|
||||
|
||||
public static String ACTION_OPEN_DOCUMENT;
|
||||
|
||||
static {
|
||||
try {
|
||||
Field openDocument = Intent.class.getField("ACTION_OPEN_DOCUMENT");
|
||||
ACTION_OPEN_DOCUMENT = (String) openDocument.get(null);
|
||||
} catch (Exception e) {
|
||||
ACTION_OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean supportsStorageFramework() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; }
|
||||
|
||||
public static boolean useStorageFramework(Context ctx) {
|
||||
if (!supportsStorageFramework()) { return false; }
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
|
||||
return prefs.getBoolean(ctx.getString(R.string.saf_key), ctx.getResources().getBoolean(R.bool.settings_saf_default));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
* KeePass DX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePass DX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.fileselect
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.preference.PreferenceManager
|
||||
import com.kunzisoft.keepass.R
|
||||
|
||||
object StorageAF {
|
||||
|
||||
var ACTION_OPEN_DOCUMENT: String
|
||||
|
||||
init {
|
||||
ACTION_OPEN_DOCUMENT = try {
|
||||
val openDocument = Intent::class.java.getField("ACTION_OPEN_DOCUMENT")
|
||||
openDocument.get(null) as String
|
||||
} catch (e: Exception) {
|
||||
"android.intent.action.OPEN_DOCUMENT"
|
||||
}
|
||||
}
|
||||
|
||||
fun useStorageFramework(context: Context): Boolean {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
return false
|
||||
}
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return prefs.getBoolean(context.getString(R.string.saf_key),
|
||||
context.resources.getBoolean(R.bool.settings_saf_default))
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public class UriUtil {
|
||||
*/
|
||||
public static Uri translate(Context ctx, Uri uri) {
|
||||
// StorageAF provides nice URIs
|
||||
if (StorageAF.useStorageFramework(ctx) || hasWritableContentUri(uri)) { return uri; }
|
||||
if (StorageAF.INSTANCE.useStorageFramework(ctx) || hasWritableContentUri(uri)) { return uri; }
|
||||
|
||||
String scheme = uri.getScheme();
|
||||
if (EmptyUtils.INSTANCE.isNullOrEmpty(scheme)) { return uri; }
|
||||
|
||||
Reference in New Issue
Block a user