diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ComparableS2K.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ComparableS2K.java deleted file mode 100644 index 99b9cdab2..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ComparableS2K.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2016 Vincent Breitmoser - * - * 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 . - */ - -package org.sufficientlysecure.keychain.pgp; - - -import java.util.Arrays; - -import android.os.Parcel; -import android.os.Parcelable; - -import org.bouncycastle.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.bouncycastle.bcpg.S2K - */ -public class ComparableS2K implements Parcelable { - - private final int encryptionAlgorithm; - private final int s2kType; - private final int s2kHashAlgo; - private final long s2kItCount; - private final byte[] s2kIV; - - Integer cachedHashCode; - - public ComparableS2K(int encryptionAlgorithm, S2K s2k) { - this.encryptionAlgorithm = encryptionAlgorithm; - this.s2kType = s2k.getType(); - this.s2kHashAlgo = s2k.getHashAlgorithm(); - this.s2kItCount = s2k.getIterationCount(); - this.s2kIV = s2k.getIV(); - } - - protected ComparableS2K(Parcel in) { - encryptionAlgorithm = in.readInt(); - s2kType = in.readInt(); - s2kHashAlgo = in.readInt(); - s2kItCount = in.readLong(); - s2kIV = in.createByteArray(); - } - - @Override - public int hashCode() { - if (cachedHashCode == null) { - cachedHashCode = encryptionAlgorithm; - cachedHashCode = 31 * cachedHashCode + s2kType; - cachedHashCode = 31 * cachedHashCode + s2kHashAlgo; - cachedHashCode = 31 * cachedHashCode + (int) (s2kItCount ^ (s2kItCount >>> 32)); - cachedHashCode = 31 * cachedHashCode + Arrays.hashCode(s2kIV); - } - - return cachedHashCode; - } - - @Override - public boolean equals(Object o) { - boolean isComparableS2K = o instanceof ComparableS2K; - if (!isComparableS2K) { - return false; - } - ComparableS2K other = (ComparableS2K) o; - return encryptionAlgorithm == other.encryptionAlgorithm - && s2kType == other.s2kType - && s2kHashAlgo == other.s2kHashAlgo - && s2kItCount == other.s2kItCount - && Arrays.equals(s2kIV, other.s2kIV); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(encryptionAlgorithm); - dest.writeInt(s2kType); - dest.writeInt(s2kHashAlgo); - dest.writeLong(s2kItCount); - dest.writeByteArray(s2kIV); - } - - public static final Creator CREATOR = new Creator() { - @Override - public ComparableS2K createFromParcel(Parcel in) { - return new ComparableS2K(in); - } - - @Override - public ComparableS2K[] newArray(int size) { - return new ComparableS2K[size]; - } - }; - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ParcelableS2K.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ParcelableS2K.java new file mode 100644 index 000000000..78b72e90b --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/ParcelableS2K.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2016 Vincent Breitmoser + * + * 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 . + */ + +package org.sufficientlysecure.keychain.pgp; + + +import android.os.Parcelable; + +import com.google.auto.value.AutoValue; +import com.google.auto.value.extension.memoized.Memoized; +import org.bouncycastle.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.bouncycastle.bcpg.S2K + */ +@AutoValue +public abstract class ParcelableS2K implements Parcelable { + abstract int getEncryptionAlgorithm(); + abstract int getS2kType(); + abstract int getS2kHashAlgo(); + abstract long getS2kItCount(); + abstract byte[] getS2kIV(); + + @Memoized + @Override + public abstract int hashCode(); + + public static ParcelableS2K fromS2K(int encryptionAlgorithm, S2K s2k) { + return new AutoValue_ParcelableS2K(encryptionAlgorithm, + s2k.getType(), s2k.getHashAlgorithm(), s2k.getIterationCount(), s2k.getIV()); + } +} 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 b49b30d1d..b3f06b0f7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java @@ -25,7 +25,7 @@ import android.widget.EditText; import org.bouncycastle.bcpg.S2K; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.ComparableS2K; +import org.sufficientlysecure.keychain.pgp.ParcelableS2K; import java.util.Arrays; import java.util.HashMap; @@ -49,7 +49,7 @@ import java.util.Map.Entry; */ public class Passphrase implements Parcelable { private char[] mPassphrase; - private HashMap mCachedSessionKeys; + private HashMap mCachedSessionKeys; /** * According to http://stackoverflow.com/a/15844273 EditText is not using String internally @@ -104,7 +104,7 @@ public class Passphrase implements Parcelable { if (mCachedSessionKeys == null) { return null; } - return mCachedSessionKeys.get(new ComparableS2K(keyEncryptionAlgorithm, s2k)); + return mCachedSessionKeys.get(ParcelableS2K.fromS2K(keyEncryptionAlgorithm, s2k)); } /** Adds a session key for a set of s2k parameters to this Passphrase object's @@ -116,7 +116,7 @@ public class Passphrase implements Parcelable { if (mCachedSessionKeys == null) { mCachedSessionKeys = new HashMap<>(); } - mCachedSessionKeys.put(new ComparableS2K(keyEncryptionAlgorithm, s2k), sessionKey); + mCachedSessionKeys.put(ParcelableS2K.fromS2K(keyEncryptionAlgorithm, s2k), sessionKey); } /** @@ -184,7 +184,7 @@ public class Passphrase implements Parcelable { } mCachedSessionKeys = new HashMap<>(size); for (int i = 0; i < size; i++) { - ComparableS2K cachedS2K = source.readParcelable(getClass().getClassLoader()); + ParcelableS2K cachedS2K = source.readParcelable(getClass().getClassLoader()); byte[] cachedSessionKey = source.createByteArray(); mCachedSessionKeys.put(cachedS2K, cachedSessionKey); } @@ -197,7 +197,7 @@ public class Passphrase implements Parcelable { return; } dest.writeInt(mCachedSessionKeys.size()); - for (Entry entry : mCachedSessionKeys.entrySet()) { + for (Entry entry : mCachedSessionKeys.entrySet()) { dest.writeParcelable(entry.getKey(), 0); dest.writeByteArray(entry.getValue()); }