performance: add license headers and some documentation
This commit is contained in:
@@ -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;
|
package org.spongycastle.openpgp.operator.jcajce;
|
||||||
|
|
||||||
|
|
||||||
@@ -18,6 +24,9 @@ import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
|||||||
import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
|
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
|
public class SessionKeySecretKeyDecryptorBuilder
|
||||||
{
|
{
|
||||||
private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper());
|
private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper());
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import org.spongycastle.openpgp.operator.jcajce.SessionKeySecretKeyDecryptorBuil
|
|||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||||
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
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
|
/** This method returns the SecretKeyType for this secret key, testing for an empty
|
||||||
// ever be called by ProviderHelper to be cached in the database.
|
* 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() {
|
public SecretKeyType getSecretKeyTypeSuperExpensive() {
|
||||||
S2K s2k = mSecretKey.getS2K();
|
S2K s2k = mSecretKey.getS2K();
|
||||||
if (s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K) {
|
if (s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K) {
|
||||||
@@ -175,13 +181,13 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] sessionKey;
|
byte[] sessionKey;
|
||||||
sessionKey = passphrase.getCachedSessionKeyForAlgorithm(keyEncryptionAlgorithm, s2k);
|
sessionKey = passphrase.getCachedSessionKeyForParameters(keyEncryptionAlgorithm, s2k);
|
||||||
if (sessionKey == null) {
|
if (sessionKey == null) {
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
|
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
|
||||||
// this operation is EXPENSIVE, so we cache its result in the passed Passphrase object!
|
// this operation is EXPENSIVE, so we cache its result in the passed Passphrase object!
|
||||||
sessionKey = keyDecryptor.makeKeyFromPassPhrase(keyEncryptionAlgorithm, s2k);
|
sessionKey = keyDecryptor.makeKeyFromPassPhrase(keyEncryptionAlgorithm, s2k);
|
||||||
passphrase.addCachedSessionKey(keyEncryptionAlgorithm, s2k, sessionKey);
|
passphrase.addCachedSessionKeyForParameters(keyEncryptionAlgorithm, s2k, sessionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
PBESecretKeyDecryptor keyDecryptor = new SessionKeySecretKeyDecryptorBuilder()
|
PBESecretKeyDecryptor keyDecryptor = new SessionKeySecretKeyDecryptorBuilder()
|
||||||
|
|||||||
@@ -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;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
|
|
||||||
@@ -9,13 +26,26 @@ import android.os.Parcelable;
|
|||||||
import org.spongycastle.bcpg.S2K;
|
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 {
|
public class ComparableS2K implements Parcelable {
|
||||||
|
|
||||||
int encryptionAlgorithm;
|
private final int encryptionAlgorithm;
|
||||||
int s2kType;
|
private final int s2kType;
|
||||||
int s2kHashAlgo;
|
private final int s2kHashAlgo;
|
||||||
long s2kItCount;
|
private final long s2kItCount;
|
||||||
byte[] s2kIV;
|
private final byte[] s2kIV;
|
||||||
|
|
||||||
Integer cachedHashCode;
|
Integer cachedHashCode;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||||
* Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org>
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
* 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
|
* 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
|
* 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[] array that is overwritten before the object is freed, to avoid
|
||||||
* This class wraps a char[] that can be erased after it is no longer used.
|
* 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:
|
* See also:
|
||||||
* <p/>
|
* <p/>
|
||||||
* http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#PBEEx
|
* 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 {
|
public class Passphrase implements Parcelable {
|
||||||
private char[] mPassphrase;
|
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
|
* 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;
|
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) {
|
if (mCachedSessionKeys == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return mCachedSessionKeys.get(new ComparableS2K(keyEncryptionAlgorithm, s2k));
|
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) {
|
if (mCachedSessionKeys == null) {
|
||||||
mCachedSessionKeys = new HashMap<>();
|
mCachedSessionKeys = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user