aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main')
-rw-r--r--OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/SessionKeySecretKeyDecryptorBuilder.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ComparableS2K.java40
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java22
5 files changed, 72 insertions, 14 deletions
diff --git a/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/SessionKeySecretKeyDecryptorBuilder.java b/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/SessionKeySecretKeyDecryptorBuilder.java
index 49282230f..36fe06dfa 100644
--- a/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/SessionKeySecretKeyDecryptorBuilder.java
+++ b/OpenKeychain/src/main/java/org/spongycastle/openpgp/operator/jcajce/SessionKeySecretKeyDecryptorBuilder.java
@@ -1,3 +1,9 @@
+/**
+ * Copyright (c) 2016 Vincent Breitmoser
+ *
+ * Licensed under the Bouncy Castle License (MIT license). See LICENSE file for details.
+ */
+
package org.spongycastle.openpgp.operator.jcajce;
@@ -18,6 +24,9 @@ import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
+/** This is a builder for a special PBESecretKeyDecryptor which is parametrized by a
+ * fixed session key, which is used in place of the one obtained from a passphrase.
+ */
public class SessionKeySecretKeyDecryptorBuilder
{
private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper());
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
index 95a0d41cc..012a7e4e6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
@@ -38,6 +38,7 @@ import org.spongycastle.openpgp.operator.jcajce.SessionKeySecretKeyDecryptorBuil
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Passphrase;
@@ -120,8 +121,13 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
}
- // This method can potentially take a LONG time (i.e. seconds), so it should only
- // ever be called by ProviderHelper to be cached in the database.
+ /** This method returns the SecretKeyType for this secret key, testing for an empty
+ * passphrase in the process.
+ *
+ * This method can potentially take a LONG time (i.e. seconds), so it should only
+ * ever be called by {@link ProviderHelper} for the purpose of caching its output
+ * in the database.
+ */
public SecretKeyType getSecretKeyTypeSuperExpensive() {
S2K s2k = mSecretKey.getS2K();
if (s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K) {
@@ -175,13 +181,13 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
}
byte[] sessionKey;
- sessionKey = passphrase.getCachedSessionKeyForAlgorithm(keyEncryptionAlgorithm, s2k);
+ sessionKey = passphrase.getCachedSessionKeyForParameters(keyEncryptionAlgorithm, s2k);
if (sessionKey == null) {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
// this operation is EXPENSIVE, so we cache its result in the passed Passphrase object!
sessionKey = keyDecryptor.makeKeyFromPassPhrase(keyEncryptionAlgorithm, s2k);
- passphrase.addCachedSessionKey(keyEncryptionAlgorithm, s2k, sessionKey);
+ passphrase.addCachedSessionKeyForParameters(keyEncryptionAlgorithm, s2k, sessionKey);
}
PBESecretKeyDecryptor keyDecryptor = new SessionKeySecretKeyDecryptorBuilder()
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ComparableS2K.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ComparableS2K.java
index 5c92008e5..31faa233c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ComparableS2K.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ComparableS2K.java
@@ -1,3 +1,20 @@
+/*
+ * Copyright (C) 2016 Vincent Breitmoser <look@my.amazin.horse>
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
package org.sufficientlysecure.keychain.pgp;
@@ -9,13 +26,26 @@ import android.os.Parcelable;
import org.spongycastle.bcpg.S2K;
+/** This is an immutable and parcelable class which stores the full s2k parametrization
+ * of an encrypted secret key, i.e. all fields of the {@link S2K} class (type, hash algo,
+ * iteration count, iv) plus the encryptionAlgorithm. This class is intended to be used
+ * as key in a HashMap for session key caching purposes, and overrides the
+ * {@link #hashCode} and {@link #equals} methods in a suitable way.
+ *
+ * Note that although it is a rather unlikely scenario that secret keys of the same key
+ * are encrypted with different ciphers, the encryption algorithm still determines the
+ * length of the specific session key and thus needs to be considered for purposes of
+ * session key caching.
+ *
+ * @see org.spongycastle.bcpg.S2K
+ */
public class ComparableS2K implements Parcelable {
- int encryptionAlgorithm;
- int s2kType;
- int s2kHashAlgo;
- long s2kItCount;
- byte[] s2kIV;
+ private final int encryptionAlgorithm;
+ private final int s2kType;
+ private final int s2kHashAlgo;
+ private final long s2kItCount;
+ private final byte[] s2kIV;
Integer cachedHashCode;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java
index 3fc020aa7..f7a69612a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org>
+ * Copyright (C) 2015-2016 Vincent Breitmoser <look@my.amazin.horse>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java
index bb54f8024..d47aefdfd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2016 Vincent Breitmoser <look@my.amazin.horse>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,8 +33,13 @@ import java.util.Map.Entry;
/**
- * Passwords should not be stored as Strings in memory.
- * This class wraps a char[] that can be erased after it is no longer used.
+ * This class wraps a char[] array that is overwritten before the object is freed, to avoid
+ * keeping passphrases in memory as much as possible.
+ *
+ * In addition to the raw passphrases, this class can cache the session key output of an applied
+ * S2K algorithm for a given set of S2K parameters. Since S2K operations are very expensive, this
+ * mechanism should be used to cache session keys whenever possible.
+ *
* See also:
* <p/>
* http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#PBEEx
@@ -43,7 +49,7 @@ import java.util.Map.Entry;
*/
public class Passphrase implements Parcelable {
private char[] mPassphrase;
- HashMap<ComparableS2K, byte[]> mCachedSessionKeys;
+ private HashMap<ComparableS2K, byte[]> mCachedSessionKeys;
/**
* According to http://stackoverflow.com/a/15844273 EditText is not using String internally
@@ -93,14 +99,20 @@ public class Passphrase implements Parcelable {
return mPassphrase.length;
}
- public byte[] getCachedSessionKeyForAlgorithm(int keyEncryptionAlgorithm, S2K s2k) {
+ /** @return A cached session key, or null if none exists for the given parameters. */
+ public byte[] getCachedSessionKeyForParameters(int keyEncryptionAlgorithm, S2K s2k) {
if (mCachedSessionKeys == null) {
return null;
}
return mCachedSessionKeys.get(new ComparableS2K(keyEncryptionAlgorithm, s2k));
}
- public void addCachedSessionKey(int keyEncryptionAlgorithm, S2K s2k, byte[] sessionKey) {
+ /** Adds a session key for a set of s2k parameters to this Passphrase object's
+ * cache. The caller should make sure that the supplied session key is the result
+ * of an S2K operation applied to exactly the passphrase stored by this object
+ * with the given parameters.
+ */
+ public void addCachedSessionKeyForParameters(int keyEncryptionAlgorithm, S2K s2k, byte[] sessionKey) {
if (mCachedSessionKeys == null) {
mCachedSessionKeys = new HashMap<>();
}