From 2443bc9f5d843565a6d2d093d2bd5e2eb74cdad9 Mon Sep 17 00:00:00 2001 From: Lukas Zorich Date: Tue, 3 Mar 2015 16:23:43 -0300 Subject: Implemented Matt Allen password strength indicator I used most of Matt Allen password strength indicator code available here https://github.com/matt-allen/android-password-strength-indicator, but modified it a little bit in order to customize the view's colors through the xml. --- .../PasswordStrengthBarView.java | 94 ++++++ .../PasswordStrengthView.java | 326 +++++++++++++++++++++ OpenKeychain/src/main/res/values/attr.xml | 14 + 3 files changed, 434 insertions(+) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java new file mode 100644 index 000000000..ad431875e --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java @@ -0,0 +1,94 @@ +package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.util.AttributeSet; + +/** + * Created by matt on 04/07/2014. + * https://github.com/matt-allen/android-password-strength-indicator + * + */ +public class PasswordStrengthBarView extends PasswordStrengthView { + + public PasswordStrengthBarView(Context context, AttributeSet attrs) { + super(context, attrs); + mMinHeight = 80; + mMinWidth = 300; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + generateIndicatorColor(); + // Default to full width + int indWidth = mIndicatorWidth; + // If score, leave it as full - can cause it to become + // less than full width in this calculation + if (mCurrentScore < 20) indWidth = (mIndicatorWidth / 20) * mCurrentScore; + // Draw indicator + canvas.drawRect( + getPaddingLeft(), + getPaddingTop(), + indWidth, + mIndicatorHeight, + mIndicatorPaint + ); + // Draw guides if true + if (mShowGuides) { + // TODO: Try and do this with a loop, for efficiency + // Draw bottom guide border + float positionY = getHeight()-getPaddingBottom()-getPaddingTop(); + float notchHeight = (float)(positionY * 0.8); + canvas.drawLine( + getPaddingLeft(), + positionY, + getWidth()-getPaddingRight(), + positionY, + mGuidePaint); + // Show left-most notch + canvas.drawLine( + getPaddingLeft(), + positionY, + getPaddingLeft(), + notchHeight, + mGuidePaint + ); + // Show middle-left notch + canvas.drawLine( + (float)(mIndicatorWidth*0.25)+getPaddingLeft(), + positionY, + (float)(mIndicatorWidth*0.25)+getPaddingLeft(), + notchHeight, + mGuidePaint + ); + // Show the middle notch + canvas.drawLine( + (float)(mIndicatorWidth*0.5)+getPaddingLeft(), + positionY, + (float)(mIndicatorWidth*0.5)+getPaddingLeft(), + notchHeight, + mGuidePaint + ); + // Show the middle-right notch + canvas.drawLine( + (float)(mIndicatorWidth*0.75)+getPaddingLeft(), + positionY, + (float)(mIndicatorWidth*0.75)+getPaddingLeft(), + notchHeight, + mGuidePaint + ); + // Show the right-most notch + canvas.drawLine( + mIndicatorWidth+getPaddingLeft(), + positionY, + mIndicatorWidth+getPaddingLeft(), + notchHeight, + mGuidePaint + ); + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java new file mode 100644 index 000000000..da7b0b5d5 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java @@ -0,0 +1,326 @@ +package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.view.View; + +import org.sufficientlysecure.keychain.R; + +/** + * Created by Matt Allen + * 01/07/14 + * http://www.mattallensoftware.co.uk + * mattallen092@gmail.com + * + * https://github.com/matt-allen/android-password-strength-indicator + * + *

+ * This View is designed to indicate how secure a user-entered password is in a visual way to + * relay to the user if they need to make it stronger. The strength of the password can be set + * at creation (or after) which will decide whether their password is strong enough. + *

+ * + *

+ * The password strength is decided by an index of 20. The minimum score needed to pass is 10 + * which means the String has met the conditions imposed by the strength test, but can be improved. + * If the password scores 10-19 it is considered weak, and only if it scores 20 will it be + * considered strong. + *

+ */ +public class PasswordStrengthView extends View { + + protected static final int COLOR_FAIL = Color.parseColor("#e74c3c"); + protected static final int COLOR_WEAK = Color.parseColor("#e67e22"); + protected static final int COLOR_STRONG = Color.parseColor("#2ecc71"); + + protected int mMinWidth; + protected int mMinHeight; + + protected Paint mIndicatorPaint; + protected Paint mGuidePaint; + + protected int mIndicatorHeight; + protected int mIndicatorWidth; + protected int mCurrentScore; + + protected int mColorFail; + protected int mColorWeak; + protected int mColorStrong; + + protected boolean mShowGuides = true; + + /** + * Used to define that the indicator should only be looking + * for a weak password. The bare minimum is used here to let + * the user continue. + */ + public static final int STRENGTH_WEAK = 0; + + /** + * A fairly strict rule for generating a password. It encourages a password that is + * less easy to crack. + */ + public static final int STRENGTH_MEDIUM = 1; + + /** + * A strong algorithm that encourages very strong passwords that should be fairly long, with + * non-alphanumeric, numbers, and upper case. + */ + public static final int STRENGTH_STRONG = 2; + + private int mStrengthRequirement = -1; + protected String mPassword; + + public PasswordStrengthView(Context context, AttributeSet attrs) { + super(context, attrs); + TypedArray style = context.getTheme().obtainStyledAttributes( + attrs, + R.styleable.PasswordStrengthView, + 0, 0); + + try { + mStrengthRequirement = style.getInteger(R.styleable.PasswordStrengthView_strength, + STRENGTH_MEDIUM); + mShowGuides = style.getBoolean(R.styleable.PasswordStrengthView_showGuides, true); + mColorFail = style.getColor(R.styleable.PasswordStrengthView_color_fail, COLOR_FAIL); + mColorWeak = style.getColor(R.styleable.PasswordStrengthView_color_weak, COLOR_WEAK); + mColorStrong = style.getColor(R.styleable.PasswordStrengthView_color_strong, + COLOR_STRONG); + } catch (Exception e){ + e.printStackTrace(); + } + // Create and style the paint used for drawing the guide on the indicator + mGuidePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mGuidePaint.setStyle(Paint.Style.FILL_AND_STROKE); + mGuidePaint.setColor(Color.BLACK); + // Create and style paint for indicator + mIndicatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mIndicatorPaint.setStyle(Paint.Style.FILL); + } + + /** + * This view can determine if the password entered by the user is acceptable for + * use by your use case. This is based on the strength requirement you have set. + * @return True if requirement has been met + */ + public boolean isStrengthRequirementMet() { + return (mCurrentScore >= 10); + } + + /** + * Change the strength requirement of the password entered by the user. This will also + * re-check the password already entered against these new requirements. + * @param requiredStrength Use the public constants of this class to set + */ + public void setStrengthRequirement(int requiredStrength) { + if(requiredStrength >= 0 && requiredStrength <= 2){ + mStrengthRequirement = requiredStrength; + if (mPassword != null && mPassword.length() > 0) { + generatePasswordScore(); + // Update view with new score + invalidate(); + requestLayout(); + } + } else { + throw new IndexOutOfBoundsException("Input out of expected range"); + } + } + + /** + * Update the password string to check strength of + * @param passwordString String representation of user-input + */ + public void setPassword(String passwordString) { + if(passwordString != null && passwordString.length() > 0) { + mPassword = passwordString; + generatePasswordScore(); + } else { + mPassword = ""; + mCurrentScore = 0; + } + + // Update view with new score + invalidate(); + requestLayout(); + } + + /** + * Private convenience method for adding to the password score + * @param score Amount to be added to current score + */ + protected void addToPasswordScore(int score) { + int newScore = mCurrentScore + score; + + // Limit max score + if (newScore > 20){ + mCurrentScore = 20; + } else { + mCurrentScore = newScore; + } + } + + /** + * Call this to determine the current strength requirement set on the algorithm + * @return Int representation of the current strength set for the indicator + */ + public int getStrengthRequirement() { + return mStrengthRequirement; + } + + /** + * Generate a score based on the password. The password will already need to be stored + * as a class member before running this. + */ + protected void generatePasswordScore() { + mCurrentScore = 0; + int upperCase = getUppercaseCount(mPassword); + int nonAlpha = getNonAlphanumericCount(mPassword); + int numbers = getNumberCount(mPassword); + switch (mStrengthRequirement){ + case STRENGTH_WEAK: + addToPasswordScore(mPassword.length()*2); + addToPasswordScore(upperCase*2); + addToPasswordScore(nonAlpha*2); + addToPasswordScore(numbers*2); + break; + + case STRENGTH_MEDIUM: + addToPasswordScore(mPassword.length()); + addToPasswordScore(upperCase); + addToPasswordScore(nonAlpha*2); + addToPasswordScore(numbers); + break; + + case STRENGTH_STRONG: + addToPasswordScore(mPassword.length()/2); + // Cut the score in half to make this a very high requirement + addToPasswordScore(upperCase); + addToPasswordScore(nonAlpha); + addToPasswordScore(numbers); + break; + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldW, int oldH) { + super.onSizeChanged(w, h, oldW, oldH); + int paddingX = getPaddingLeft(); + int paddingY = getPaddingTop(); + mIndicatorHeight = h - paddingY; + mIndicatorWidth = w - paddingX; + } + + /** + * The standard parts of the onMeasure needed to create the password strength + * indicator. Subclasses should call super.onMeasure, but also need to set + * the minimum height and width in the constructor. + * @param widthMeasureSpec The measurement given by the system + * @param heightMeasureSpec The measurement given by the system + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Set minimum space for the view to do it's thing + int minW = getPaddingLeft() + getPaddingRight() + mMinWidth; + int w = resolveSizeAndState(minW, widthMeasureSpec, 1); + // And give it enough height so it's visible + int minH = mMinHeight + getPaddingBottom() + getPaddingTop(); + int h = resolveSizeAndState(minH, heightMeasureSpec, 0); + // Feed these back into UIKit + setMeasuredDimension(w, h); + } + + /** + * Set the colour of the indicator {@code Paint} to one that is appropriate + * for the strength of the password. + */ + protected void generateIndicatorColor() { + int color = mColorFail; + if (mCurrentScore >= 18) { + color = mColorStrong; + } + else if (mCurrentScore >= 10) { + color = mColorWeak; + } + mIndicatorPaint.setColor(color); + } + + /** + * Quick method to determine how many of the characters in a given string are upper case + * @param stringToCheck The string to examine + * @return Number of upper case characters + */ + protected int getUppercaseCount(String stringToCheck) { + int score = 0; + int loops = stringToCheck.length()-1; + for (int i=0;i<=loops;i++){ + if(Character.isUpperCase(stringToCheck.charAt(i))) { + score++; + } + } + return score; + } + + /** + * A convenience method to determine how many characters in the given String aren't + * letters or numbers. + * @param stringToCheck + * @return Number of characters that aren't numbers or letters + */ + protected int getNonAlphanumericCount(String stringToCheck) { + int score = 0; + int loops = stringToCheck.length()-1; + for (int i=0;i<=loops;i++) { + if(!Character.isLetter(stringToCheck.charAt(i)) && + !Character.isDigit(stringToCheck.charAt(i))){ + score++; + } + } + return score; + } + + /** + * A convenience method for returning the count of numbers in a given String. + * @param stringToCheck + * @return The numbers of digits in the String + */ + protected int getNumberCount(String stringToCheck) { + int score = 0; + int loops = stringToCheck.length()-1; + for (int i=0;i<=loops;i++) { + if(Character.isDigit(stringToCheck.charAt(i))) { + score++; + } + } + return score; + } + + /** + * Set the guides to show on the view.
+ * On the line style, the guides will show underneath
+ * On the rounded style, the guides will be shown on the outer edges.
+ * The view will be redrawn after the method is called. + * @param showGuides True if you want the guides to be shown + */ + public void setShowGuides(boolean showGuides) { + mShowGuides = showGuides; + if (mPassword != null && mPassword.length() > 0) { + generatePasswordScore(); + } else { + mCurrentScore = 0; + } + + invalidate(); + requestLayout(); + } + + /** + * Determine whether the view is showing the guides for the password score + * @return True if the guides are being shown + */ + public boolean isShowingGuides() { + return mShowGuides; + } +} diff --git a/OpenKeychain/src/main/res/values/attr.xml b/OpenKeychain/src/main/res/values/attr.xml index 98ce1c364..7a2f3054e 100644 --- a/OpenKeychain/src/main/res/values/attr.xml +++ b/OpenKeychain/src/main/res/values/attr.xml @@ -15,4 +15,18 @@ + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 7f9c663033f843b43eb36f72fcace658ad25bac3 Mon Sep 17 00:00:00 2001 From: Lukas Zorich Date: Tue, 3 Mar 2015 18:51:06 -0300 Subject: Add license to password strength view classes --- .../keychain/ui/CreateKeyInputFragment.java | 20 ++++++++++++++++++ .../PasswordStrengthBarView.java | 24 ++++++++++++++++++++++ .../PasswordStrengthView.java | 24 ++++++++++++++++++++++ .../main/res/layout/create_key_input_fragment.xml | 13 +++++++++++- 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java index 8aa9fa6db..d3b6cb36c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java @@ -32,6 +32,7 @@ import android.widget.AutoCompleteTextView; import android.widget.EditText; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthView; import org.sufficientlysecure.keychain.util.ContactHelper; import java.util.regex.Matcher; @@ -40,6 +41,7 @@ public class CreateKeyInputFragment extends Fragment { CreateKeyActivity mCreateKeyActivity; + PasswordStrengthView mPassphraseStrengthView; AutoCompleteTextView mNameEdit; AutoCompleteTextView mEmailEdit; EditText mPassphraseEdit; @@ -68,6 +70,8 @@ public class CreateKeyInputFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.create_key_input_fragment, container, false); + mPassphraseStrengthView = (PasswordStrengthView) view.findViewById(R.id + .create_key_passphrase_strength); mNameEdit = (AutoCompleteTextView) view.findViewById(R.id.create_key_name); mEmailEdit = (AutoCompleteTextView) view.findViewById(R.id.create_key_email); mPassphraseEdit = (EditText) view.findViewById(R.id.create_key_passphrase); @@ -130,6 +134,22 @@ public class CreateKeyInputFragment extends Fragment { ) ); + mPassphraseEdit.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable editable) { + String passphrase = editable.toString(); + mPassphraseStrengthView.setPassword(passphrase); + } + }); + mCreateButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java index ad431875e..c1db823b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java @@ -1,3 +1,27 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014 Matt Allen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator; import android.content.Context; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java index da7b0b5d5..47e6d9527 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java @@ -1,3 +1,27 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2014 Matt Allen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator; import android.content.Context; diff --git a/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml index f678825aa..76a58acb1 100644 --- a/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml +++ b/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml @@ -1,5 +1,6 @@ @@ -63,13 +64,23 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:layout_marginBottom="8dp" android:imeOptions="actionNext" android:inputType="textPassword" android:hint="@string/label_passphrase" android:ems="10" android:layout_gravity="center_horizontal" /> + + Date: Tue, 3 Mar 2015 18:52:10 -0300 Subject: Integrates passphrase strength indicator to create key wizard. This commit patches issue #1050. The padding set in the passphrase edit text is set programmatically because there is a bug in appcompat-v7 where padding via xml doesn't work: http://code.google.com/p/android/issues/detail?id=77982 --- .../keychain/ui/CreateKeyInputFragment.java | 6 +++ .../main/res/layout/create_key_input_fragment.xml | 43 +++++++++++++--------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java index d3b6cb36c..091418304 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java @@ -134,6 +134,12 @@ public class CreateKeyInputFragment extends Fragment { ) ); + // Edit text padding doesn't work via xml (http://code.google.com/p/android/issues/detail?id=77982) + // so we set the right padding programmatically. + mPassphraseEdit.setPadding(mPassphraseEdit.getPaddingLeft(), + mPassphraseEdit.getPaddingTop(), + (int) (56 * getResources().getDisplayMetrics().density), + mPassphraseEdit.getPaddingBottom()); mPassphraseEdit.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { diff --git a/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml index 76a58acb1..d59cd7b86 100644 --- a/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml +++ b/OpenKeychain/src/main/res/layout/create_key_input_fragment.xml @@ -59,27 +59,34 @@ android:layout_height="wrap_content" android:text="@string/label_passphrase" /> - - - + android:layout_marginBottom="8dp"> + + + + + + Date: Thu, 5 Mar 2015 10:49:57 +0100 Subject: Better selection of preferred algorithm --- .../org/sufficientlysecure/keychain/Constants.java | 14 ++++++-- .../keychain/pgp/CanonicalizedSecretKey.java | 38 ++++++++++++++------ .../keychain/pgp/CanonicalizedSecretKeyRing.java | 4 +-- .../keychain/pgp/PgpKeyOperation.java | 2 +- .../keychain/pgp/PgpSignEncryptInput.java | 4 +-- .../keychain/pgp/PgpSignEncryptOperation.java | 12 ++++--- .../keychain/remote/OpenPgpService.java | 9 ++--- .../keychain/ui/EncryptFilesActivity.java | 2 ++ .../keychain/ui/EncryptTextActivity.java | 2 ++ .../keychain/ui/SettingsActivity.java | 42 +++++++++++++++------- .../keychain/util/Preferences.java | 10 +++++- 11 files changed, 99 insertions(+), 40 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 2d3ee6188..9f8226c05 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -19,6 +19,8 @@ package org.sufficientlysecure.keychain; import android.os.Environment; +import org.spongycastle.bcpg.HashAlgorithmTags; +import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; import org.spongycastle.jce.provider.BouncyCastleProvider; import java.io.File; @@ -77,16 +79,24 @@ public final class Constants { public static final String SEARCH_KEYSERVER = "search_keyserver_pref"; public static final String SEARCH_KEYBASE = "search_keybase_pref"; public static final String USE_DEFAULT_YUBIKEY_PIN = "useDefaultYubikeyPin"; - public static final String USE_NUMKEYPAD_FOR_YUBIKEY_PIN="useNumKeypadForYubikeyPin"; + public static final String USE_NUMKEYPAD_FOR_YUBIKEY_PIN = "useNumKeypadForYubikeyPin"; } public static final class Defaults { public static final String KEY_SERVERS = "hkps://hkps.pool.sks-keyservers.net, hkps://pgp.mit.edu"; - public static final int PREF_VERSION = 4; + public static final int PREF_VERSION = 5; } public static final class key { public static final int none = 0; public static final int symmetric = -1; } + + public static interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags { + public static final int USE_PREFERRED = -1; + } + + public static interface OpenKeychainHashAlgorithmTags extends HashAlgorithmTags { + public static final int USE_PREFERRED = -1; + } } 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 40f2f48ad..0fab4c747 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.bcpg.S2K; +import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.PGPPublicKey; @@ -137,7 +138,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { // It means the passphrase is empty return SecretKeyType.PASSPHRASE_EMPTY; } catch (PGPException e) { - HashMap notation = getRing().getLocalNotationData(); + HashMap notation = getRing().getLocalNotationData(); if (notation.containsKey("unlock.pin@sufficientlysecure.org") && "1".equals(notation.get("unlock.pin@sufficientlysecure.org"))) { return SecretKeyType.PIN; @@ -179,7 +180,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { * Returns a list of all supported hash algorithms. This list is currently hardcoded to return * a limited set of algorithms supported by Yubikeys. * - * @return + * TODO: look into preferred algos of this key? */ public LinkedList getSupportedHashAlgorithms() { LinkedList supported = new LinkedList<>(); @@ -187,24 +188,41 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) { // No support for MD5 supported.add(HashAlgorithmTags.RIPEMD160); - supported.add(HashAlgorithmTags.SHA1); + // don't allow SHA1 supported.add(HashAlgorithmTags.SHA224); - supported.add(HashAlgorithmTags.SHA256); supported.add(HashAlgorithmTags.SHA384); - supported.add(HashAlgorithmTags.SHA512); // preferred is latest + supported.add(HashAlgorithmTags.SHA512); + supported.add(HashAlgorithmTags.SHA256); // preferred is latest } else { - supported.add(HashAlgorithmTags.MD5); + // NOTE: List of hash algorithms OpenKeychain wants to support! + + // don't allow MD5 supported.add(HashAlgorithmTags.RIPEMD160); - supported.add(HashAlgorithmTags.SHA1); + // don't allow SHA1 supported.add(HashAlgorithmTags.SHA224); - supported.add(HashAlgorithmTags.SHA256); supported.add(HashAlgorithmTags.SHA384); - supported.add(HashAlgorithmTags.SHA512); // preferred is latest + supported.add(HashAlgorithmTags.SHA512); + supported.add(HashAlgorithmTags.SHA256); // preferred is latest + // some application don't support SHA512, thus preferred is SHA-256 (Mailvelope?) } return supported; } + /** + * TODO: look into preferred algos of this key? + */ + public static LinkedList getSupportedEncryptionAlgorithms() { + LinkedList supported = new LinkedList<>(); + + supported.add(SymmetricKeyAlgorithmTags.TWOFISH); + supported.add(SymmetricKeyAlgorithmTags.AES_128); + supported.add(SymmetricKeyAlgorithmTags.AES_192); + supported.add(SymmetricKeyAlgorithmTags.AES_256); // preferred is latest + + return supported; + } + private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo, byte[] nfcSignedHash, Date nfcCreationTimestamp) { if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) { @@ -358,7 +376,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { } // HACK, for TESTING ONLY!! - PGPPrivateKey getPrivateKey () { + PGPPrivateKey getPrivateKey() { return mPrivateKey; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java index b5f6a5b09..97b5fa6fe 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java @@ -19,11 +19,11 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.PGPSignature; +import org.spongycastle.openpgp.jcajce.JcaPGPObjectFactory; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.util.IterableIterator; @@ -45,7 +45,7 @@ public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing { public CanonicalizedSecretKeyRing(byte[] blob, boolean isRevoked, int verified) { super(verified); - PGPObjectFactory factory = new PGPObjectFactory(blob); + JcaPGPObjectFactory factory = new JcaPGPObjectFactory(blob); PGPKeyRing keyRing = null; try { if ((keyRing = (PGPKeyRing) factory.nextObject()) == null) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index da0394573..a54fa189a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -95,7 +95,7 @@ public class PgpKeyOperation { SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192, SymmetricKeyAlgorithmTags.AES_128, - SymmetricKeyAlgorithmTags.CAST5 + SymmetricKeyAlgorithmTags.TWOFISH }; private static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{ HashAlgorithmTags.SHA512, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java index 9318be006..f22d107e4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java @@ -12,10 +12,10 @@ public class PgpSignEncryptInput { protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED; protected long[] mEncryptionMasterKeyIds = null; protected String mSymmetricPassphrase = null; - protected int mSymmetricEncryptionAlgorithm = 0; + protected int mSymmetricEncryptionAlgorithm = Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED; protected long mSignatureMasterKeyId = Constants.key.none; protected Long mSignatureSubKeyId = null; - protected int mSignatureHashAlgorithm = 0; + protected int mSignatureHashAlgorithm = Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED; protected String mSignaturePassphrase = null; protected long mAdditionalEncryptId = Constants.key.none; protected byte[] mNfcSignedHash = null; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index 2fa01d241..d420ddb5a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -25,7 +25,6 @@ import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.BCPGOutputStream; import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.openpgp.PGPCompressedDataGenerator; -import org.spongycastle.openpgp.PGPEncryptedData; import org.spongycastle.openpgp.PGPEncryptedDataGenerator; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPLiteralData; @@ -206,10 +205,10 @@ public class PgpSignEncryptOperation extends BaseOperation { return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } - // check if hash algo is supported + // Use preferred hash algo int requestedAlgorithm = input.getSignatureHashAlgorithm(); LinkedList supported = signingKey.getSupportedHashAlgorithms(); - if (requestedAlgorithm == 0) { + if (requestedAlgorithm == Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) { // get most preferred input.setSignatureHashAlgorithm(supported.getLast()); } else if (!supported.contains(requestedAlgorithm)) { @@ -222,9 +221,12 @@ public class PgpSignEncryptOperation extends BaseOperation { /* Initialize PGPEncryptedDataGenerator for later usage */ PGPEncryptedDataGenerator cPk = null; if (enableEncryption) { + + // Use preferred encryption algo int algo = input.getSymmetricEncryptionAlgorithm(); - if (algo == 0) { - algo = PGPEncryptedData.AES_128; + if (algo == Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) { + // get most preferred + algo = CanonicalizedSecretKey.getSupportedEncryptionAlgorithms().getLast(); } // has Integrity packet enabled! JcePGPDataEncryptorBuilder encryptorBuilder = diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 1a65b1bee..5db382174 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -52,6 +52,7 @@ import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; import org.sufficientlysecure.keychain.ui.ViewKeyActivity; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Preferences; import java.io.IOException; import java.io.InputStream; @@ -259,7 +260,7 @@ public class OpenPgpService extends RemoteService { .setCleartextSignature(cleartextSign) .setDetachedSignature(!cleartextSign) .setVersionHeader(PgpHelper.getVersionForHeader(this)) - .setSignatureHashAlgorithm(accSettings.getHashAlgorithm()) + .setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm()) .setSignatureMasterKeyId(accSettings.getKeyId()) .setNfcState(nfcSignedHash, nfcCreationDate); @@ -357,8 +358,8 @@ public class OpenPgpService extends RemoteService { PgpSignEncryptInput pseInput = new PgpSignEncryptInput(); pseInput.setEnableAsciiArmorOutput(asciiArmor) .setVersionHeader(PgpHelper.getVersionForHeader(this)) - .setCompressionId(accSettings.getCompression()) - .setSymmetricEncryptionAlgorithm(accSettings.getEncryptionAlgorithm()) + .setCompressionId(Preferences.getPreferences(this).getDefaultFileCompression()) + .setSymmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) .setEncryptionMasterKeyIds(keyIds) .setFailOnMissingEncryptionKeyIds(true) .setAdditionalEncryptId(accSettings.getKeyId()); // add acc key for encryption @@ -374,7 +375,7 @@ public class OpenPgpService extends RemoteService { } // sign and encrypt - pseInput.setSignatureHashAlgorithm(accSettings.getHashAlgorithm()) + pseInput.setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm()) .setSignatureMasterKeyId(accSettings.getKeyId()) .setNfcState(nfcSignedHash, nfcCreationDate); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java index 1286617d3..fab6c19f9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -197,6 +197,8 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi data.addOutputUris(mOutputUris); data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression()); + data.setSymmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()); + data.setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm()); // Always use armor for messages data.setEnableAsciiArmorOutput(mUseArmor); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 2dd861d07..05da7a3ba 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -190,6 +190,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv data.setCleartextSignature(true); data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression()); + data.setSymmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()); + data.setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm()); // Always use armor for messages data.setEnableAsciiArmorOutput(true); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java index 53986a392..d82be2571 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java @@ -33,8 +33,6 @@ import android.view.ViewGroup; import android.widget.LinearLayout; import org.spongycastle.bcpg.CompressionAlgorithmTags; -import org.spongycastle.bcpg.HashAlgorithmTags; -import org.spongycastle.openpgp.PGPEncryptedData; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference; @@ -345,12 +343,20 @@ public class SettingsActivity extends PreferenceActivity { } private static void initializeEncryptionAlgorithm(final IntegerListPreference mEncryptionAlgorithm) { - int valueIds[] = {PGPEncryptedData.AES_128, PGPEncryptedData.AES_192, - PGPEncryptedData.AES_256, PGPEncryptedData.BLOWFISH, PGPEncryptedData.TWOFISH, - PGPEncryptedData.CAST5, PGPEncryptedData.DES, PGPEncryptedData.TRIPLE_DES, - PGPEncryptedData.IDEA,}; - String entries[] = {"AES-128", "AES-192", "AES-256", "Blowfish", "Twofish", "CAST5", - "DES", "Triple DES", "IDEA",}; + int valueIds[] = { + Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED, + Constants.OpenKeychainSymmetricKeyAlgorithmTags.AES_256, + Constants.OpenKeychainSymmetricKeyAlgorithmTags.AES_192, + Constants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128, + Constants.OpenKeychainSymmetricKeyAlgorithmTags.TWOFISH, + }; + String entries[] = { + "Use preferred algorithm", + "AES-256", + "AES-192", + "AES-128", + "Twofish", + }; String values[] = new String[valueIds.length]; for (int i = 0; i < values.length; ++i) { values[i] = "" + valueIds[i]; @@ -372,11 +378,21 @@ public class SettingsActivity extends PreferenceActivity { } private static void initializeHashAlgorithm(final IntegerListPreference mHashAlgorithm) { - int[] valueIds = new int[]{HashAlgorithmTags.RIPEMD160, - HashAlgorithmTags.SHA1, HashAlgorithmTags.SHA224, HashAlgorithmTags.SHA256, - HashAlgorithmTags.SHA384, HashAlgorithmTags.SHA512,}; - String[] entries = new String[]{"RIPEMD-160", "SHA-1", "SHA-224", "SHA-256", "SHA-384", - "SHA-512",}; + int[] valueIds = new int[]{ + Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED, + Constants.OpenKeychainHashAlgorithmTags.SHA512, + Constants.OpenKeychainHashAlgorithmTags.SHA384, + Constants.OpenKeychainHashAlgorithmTags.SHA256, + Constants.OpenKeychainHashAlgorithmTags.SHA224, + Constants.OpenKeychainHashAlgorithmTags.RIPEMD160, + }; + String[] entries = new String[]{ + "Use preferred algorithm", + "SHA-512", + "SHA-384", + "SHA-256", + "SHA-224", + "RIPEMD-160"}; String[] values = new String[valueIds.length]; for (int i = 0; i < values.length; ++i) { values[i] = "" + valueIds[i]; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java index a36af5c87..f1e9ccb28 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java @@ -210,6 +210,7 @@ public class Preferences { } return servers.toArray(chunks); } + public String getPreferredKeyserver() { return getKeyServers()[0]; } @@ -246,6 +247,7 @@ public class Preferences { editor.putBoolean(Pref.SEARCH_KEYSERVER, searchKeyserver); editor.commit(); } + public void setSearchKeybase(boolean searchKeybase) { SharedPreferences.Editor editor = mSharedPreferences.edit(); editor.putBoolean(Pref.SEARCH_KEYBASE, searchKeybase); @@ -253,7 +255,7 @@ public class Preferences { } public CloudSearchPrefs getCloudSearchPrefs() { - return new CloudSearchPrefs(mSharedPreferences.getBoolean(Pref.SEARCH_KEYSERVER, true), + return new CloudSearchPrefs(mSharedPreferences.getBoolean(Pref.SEARCH_KEYSERVER, true), mSharedPreferences.getBoolean(Pref.SEARCH_KEYBASE, true), getPreferredKeyserver()); } @@ -322,6 +324,12 @@ public class Preferences { setDefaultHashAlgorithm(HashAlgorithmTags.SHA256); } } + // fall through + case 5: { + // use preferred hash and encryption algo setting + setDefaultHashAlgorithm(Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED); + setDefaultEncryptionAlgorithm(Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); + } } // write new preference version -- cgit v1.2.3 From c0aabbeb3c9288c33ffe8b8fd8f1a708f4075dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 10:56:27 +0100 Subject: Use no compression in API for now --- .../java/org/sufficientlysecure/keychain/remote/OpenPgpService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 5db382174..38f7aa685 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -30,6 +30,7 @@ import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.util.OpenPgpApi; +import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; @@ -358,7 +359,7 @@ public class OpenPgpService extends RemoteService { PgpSignEncryptInput pseInput = new PgpSignEncryptInput(); pseInput.setEnableAsciiArmorOutput(asciiArmor) .setVersionHeader(PgpHelper.getVersionForHeader(this)) - .setCompressionId(Preferences.getPreferences(this).getDefaultFileCompression()) + .setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED) .setSymmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) .setEncryptionMasterKeyIds(keyIds) .setFailOnMissingEncryptionKeyIds(true) -- cgit v1.2.3 From 18a827eeed042ffb43338e06f408b78b0a6a3394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 11:06:17 +0100 Subject: Design fixes for decryption screen --- Graphics/get-material-icons.sh | 1 + .../sufficientlysecure/keychain/ui/DecryptFragment.java | 2 +- .../src/main/res/drawable-hdpi/ic_action_accounts.png | Bin 669 -> 0 bytes .../src/main/res/drawable-hdpi/ic_vpn_key_grey_24dp.png | Bin 0 -> 391 bytes .../src/main/res/drawable-mdpi/ic_action_accounts.png | Bin 499 -> 0 bytes .../src/main/res/drawable-mdpi/ic_vpn_key_grey_24dp.png | Bin 0 -> 301 bytes .../src/main/res/drawable-xhdpi/ic_action_accounts.png | Bin 827 -> 0 bytes .../src/main/res/drawable-xhdpi/ic_vpn_key_grey_24dp.png | Bin 0 -> 463 bytes .../src/main/res/drawable-xxhdpi/ic_action_accounts.png | Bin 1212 -> 0 bytes .../main/res/drawable-xxhdpi/ic_vpn_key_grey_24dp.png | Bin 0 -> 714 bytes .../src/main/res/drawable-xxxhdpi/ic_action_accounts.png | Bin 1663 -> 0 bytes .../main/res/drawable-xxxhdpi/ic_vpn_key_grey_24dp.png | Bin 0 -> 825 bytes .../src/main/res/layout/decrypt_result_include.xml | 2 +- OpenKeychain/src/main/res/values/strings.xml | 2 +- 14 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 OpenKeychain/src/main/res/drawable-hdpi/ic_action_accounts.png create mode 100644 OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_grey_24dp.png delete mode 100644 OpenKeychain/src/main/res/drawable-mdpi/ic_action_accounts.png create mode 100644 OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_grey_24dp.png delete mode 100644 OpenKeychain/src/main/res/drawable-xhdpi/ic_action_accounts.png create mode 100644 OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_grey_24dp.png delete mode 100644 OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_accounts.png create mode 100644 OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_grey_24dp.png delete mode 100644 OpenKeychain/src/main/res/drawable-xxxhdpi/ic_action_accounts.png create mode 100644 OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_grey_24dp.png diff --git a/Graphics/get-material-icons.sh b/Graphics/get-material-icons.sh index 95df5ca9d..d34e572fc 100755 --- a/Graphics/get-material-icons.sh +++ b/Graphics/get-material-icons.sh @@ -35,6 +35,7 @@ python copy OpenKeychain navigation grey close 24 python copy OpenKeychain social grey person 24 python copy OpenKeychain social grey person_add 24 python copy OpenKeychain social grey share 24 +python copy OpenKeychain communication grey vpn_key 24 # navigation drawer sections python copy OpenKeychain communication black vpn_key 24 diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index 7d8fd1388..60103f344 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -243,7 +243,7 @@ public abstract class DecryptFragment extends Fragment { private void setShowAction(final long signatureKeyId) { mSignatureAction.setText(R.string.decrypt_result_action_show); - mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_accounts, 0); + mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_vpn_key_grey_24dp, 0); mSignatureLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_accounts.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_action_accounts.png deleted file mode 100644 index 10c77d07d..000000000 Binary files a/OpenKeychain/src/main/res/drawable-hdpi/ic_action_accounts.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_grey_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_grey_24dp.png new file mode 100644 index 000000000..cbc93ca36 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_vpn_key_grey_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_accounts.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_action_accounts.png deleted file mode 100644 index 41b89b5b6..000000000 Binary files a/OpenKeychain/src/main/res/drawable-mdpi/ic_action_accounts.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_grey_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_grey_24dp.png new file mode 100644 index 000000000..7acfab4f4 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_vpn_key_grey_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_accounts.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_accounts.png deleted file mode 100644 index ee8067c7d..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xhdpi/ic_action_accounts.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_grey_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_grey_24dp.png new file mode 100644 index 000000000..49a44704c Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_vpn_key_grey_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_accounts.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_accounts.png deleted file mode 100644 index d9b5cc007..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_action_accounts.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_grey_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_grey_24dp.png new file mode 100644 index 000000000..6e1aa32c4 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_vpn_key_grey_24dp.png differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_action_accounts.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_action_accounts.png deleted file mode 100644 index be1bc9ef4..000000000 Binary files a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_action_accounts.png and /dev/null differ diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_grey_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_grey_24dp.png new file mode 100644 index 000000000..2ea2bf77c Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_vpn_key_grey_24dp.png differ diff --git a/OpenKeychain/src/main/res/layout/decrypt_result_include.xml b/OpenKeychain/src/main/res/layout/decrypt_result_include.xml index 7317e7742..9d47009b9 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_result_include.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_result_include.xml @@ -118,7 +118,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:text="Show" - android:drawableRight="@drawable/ic_action_accounts" + android:drawableRight="@drawable/ic_vpn_key_grey_24dp" android:drawablePadding="8dp" android:gravity="center_vertical" style="@style/SelectableItem" /> diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 88eb89ec6..207553620 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -1002,7 +1002,7 @@ "Encountered OpenPGP Exception during operation!" "Integrity check OK!" "Only metadata was requested, skipping decryption" - "OK" + "Decryption/Verification finished" "Using passphrase from cache" "NFC token required, requesting user input…" "Passphrase required, requesting user input…" -- cgit v1.2.3 From 7ccdd7d38ed1c7d2152b914be5d08323ebf434e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 11:14:19 +0100 Subject: Debug options --- .../src/main/java/org/sufficientlysecure/keychain/Constants.java | 2 ++ .../org/sufficientlysecure/keychain/provider/KeychainProvider.java | 2 +- .../main/java/org/sufficientlysecure/keychain/util/ContactHelper.java | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 9f8226c05..574f16c27 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -28,6 +28,8 @@ import java.io.File; public final class Constants { public static final boolean DEBUG = BuildConfig.DEBUG; + public static final boolean DEBUG_LOG_DB_QUERIES = false; + public static final boolean DEBUG_SYNC_REMOVE_CONTACTS = false; public static final String TAG = "Keychain"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 2601c1f69..4ccfc3cd9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -650,7 +650,7 @@ public class KeychainProvider extends ContentProvider { cursor.setNotificationUri(getContext().getContentResolver(), uri); } - if (Constants.DEBUG) { + if (Constants.DEBUG && Constants.DEBUG_LOG_DB_QUERIES) { Log.d(Constants.TAG, "Query: " + qb.buildQuery(projection, selection, selectionArgs, null, null, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java index 44bcc52a5..c66dc04d0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java @@ -296,7 +296,9 @@ public class ContactHelper { ContentResolver resolver = context.getContentResolver(); Set deletedKeys = getRawContactMasterKeyIds(resolver); -// debugDeleteRawContacts(resolver); + if (Constants.DEBUG_SYNC_REMOVE_CONTACTS) { + debugDeleteRawContacts(resolver); + } // ContentProviderClient client = resolver.acquireContentProviderClient(ContactsContract.AUTHORITY_URI); // ContentValues values = new ContentValues(); -- cgit v1.2.3 From 1576a76ecca8298f95c951abe94668c40bbaba89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 12:53:51 +0100 Subject: Remove false comment in list fragment --- .../main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index a44eef216..43d893fa6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -678,9 +678,6 @@ public class KeyListFragment extends LoaderFragment /** * Bind cursor data to the item list view - *

- * NOTE: CursorAdapter already implements the ViewHolder pattern in its getView() method. - * Thus no ViewHolder is required here. */ @Override public void bindView(View view, Context context, Cursor cursor) { -- cgit v1.2.3 From 8b7684baf78b01592777a1ccb29293a4b59bdf14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 15:12:59 +0100 Subject: Remove preferences multi process min sdk check --- .../java/org/sufficientlysecure/keychain/util/Preferences.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java index f1e9ccb28..089702de6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java @@ -59,12 +59,8 @@ public class Preferences { } public void updateSharedPreferences(Context context) { - // multi-process preferences - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - mSharedPreferences = context.getSharedPreferences("APG.main", Context.MODE_MULTI_PROCESS); - } else { - mSharedPreferences = context.getSharedPreferences("APG.main", Context.MODE_PRIVATE); - } + // multi-process safe preferences + mSharedPreferences = context.getSharedPreferences("APG.main", Context.MODE_MULTI_PROCESS); } public String getLanguage() { -- cgit v1.2.3 From e45f000cb458e8608ad851ce7ecca0045e5ac6b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 16:57:57 +0100 Subject: Remove advanced preferences, move compression as menu item in encrypt activites, select hash and encryption algo based on hardcoded preferred lists --- .../org/sufficientlysecure/keychain/Constants.java | 16 +- .../keychain/operations/ImportExportOperation.java | 8 - .../keychain/pgp/CanonicalizedSecretKey.java | 42 +----- .../sufficientlysecure/keychain/pgp/PgpHelper.java | 20 --- .../keychain/pgp/PgpKeyOperation.java | 93 ++++-------- .../keychain/pgp/PgpSignEncryptInput.java | 4 +- .../keychain/pgp/PgpSignEncryptOperation.java | 9 +- .../keychain/provider/ProviderHelper.java | 3 +- .../keychain/remote/OpenPgpService.java | 12 +- .../keychain/ui/EncryptActivityInterface.java | 1 + .../keychain/ui/EncryptFilesActivity.java | 41 +++-- .../keychain/ui/EncryptTextActivity.java | 29 +++- .../keychain/ui/SettingsActivity.java | 165 --------------------- .../keychain/util/Preferences.java | 91 ------------ .../src/main/res/menu/encrypt_file_activity.xml | 5 + .../src/main/res/menu/encrypt_text_activity.xml | 5 + OpenKeychain/src/main/res/values/strings.xml | 1 + OpenKeychain/src/main/res/xml/adv_preferences.xml | 71 +++------ .../src/main/res/xml/preference_headers.xml | 2 +- 19 files changed, 134 insertions(+), 484 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 574f16c27..30d855a74 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -64,19 +64,12 @@ public final class Constants { } public static final class Pref { - public static final String DEFAULT_ENCRYPTION_ALGORITHM = "defaultEncryptionAlgorithm"; - public static final String DEFAULT_HASH_ALGORITHM = "defaultHashAlgorithm"; - public static final String DEFAULT_ASCII_ARMOR = "defaultAsciiArmor"; - public static final String DEFAULT_MESSAGE_COMPRESSION = "defaultMessageCompression"; - public static final String DEFAULT_FILE_COMPRESSION = "defaultFileCompression"; public static final String PASSPHRASE_CACHE_TTL = "passphraseCacheTtl"; public static final String PASSPHRASE_CACHE_SUBS = "passphraseCacheSubs"; public static final String LANGUAGE = "language"; public static final String KEY_SERVERS = "keyServers"; public static final String PREF_DEFAULT_VERSION = "keyServersDefaultVersion"; - public static final String WRITE_VERSION_HEADER = "writeVersionHeader"; public static final String FIRST_TIME = "firstTime"; - public static final String SHOW_ADVANCED_TABS = "showAdvancedTabs"; public static final String CACHED_CONSOLIDATE = "cachedConsolidate"; public static final String SEARCH_KEYSERVER = "search_keyserver_pref"; public static final String SEARCH_KEYBASE = "search_keybase_pref"; @@ -86,7 +79,7 @@ public final class Constants { public static final class Defaults { public static final String KEY_SERVERS = "hkps://hkps.pool.sks-keyservers.net, hkps://pgp.mit.edu"; - public static final int PREF_VERSION = 5; + public static final int PREF_VERSION = 4; } public static final class key { @@ -94,11 +87,4 @@ public final class Constants { public static final int symmetric = -1; } - public static interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags { - public static final int USE_PREFERRED = -1; - } - - public static interface OpenKeychainHashAlgorithmTags extends HashAlgorithmTags { - public static final int USE_PREFERRED = -1; - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java index 8f10377cd..20dba95e9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java @@ -505,10 +505,6 @@ public class ImportExportOperation extends BaseOperation { // Create an output stream try { arOutStream = new ArmoredOutputStream(outStream); - String version = PgpHelper.getVersionForHeader(mContext); - if (version != null) { - arOutStream.setHeader("Version", version); - } log.add(LogType.MSG_EXPORT_PUBLIC, 1, KeyFormattingUtils.beautifyKeyId(keyId)); @@ -533,10 +529,6 @@ public class ImportExportOperation extends BaseOperation { if (exportSecret && cursor.getInt(3) > 0) { try { arOutStream = new ArmoredOutputStream(outStream); - String version = PgpHelper.getVersionForHeader(mContext); - if (version != null) { - arOutStream.setHeader("Version", version); - } // export secret key part log.add(LogType.MSG_EXPORT_SECRET, 2, KeyFormattingUtils.beautifyKeyId(keyId)); 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 0fab4c747..9c74cf9a8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -177,52 +177,20 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { } /** - * Returns a list of all supported hash algorithms. This list is currently hardcoded to return - * a limited set of algorithms supported by Yubikeys. - * - * TODO: look into preferred algos of this key? + * Returns a list of all supported hash algorithms. */ public LinkedList getSupportedHashAlgorithms() { LinkedList supported = new LinkedList<>(); - if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) { - // No support for MD5 - supported.add(HashAlgorithmTags.RIPEMD160); - // don't allow SHA1 - supported.add(HashAlgorithmTags.SHA224); - supported.add(HashAlgorithmTags.SHA384); - supported.add(HashAlgorithmTags.SHA512); - supported.add(HashAlgorithmTags.SHA256); // preferred is latest - } else { - // NOTE: List of hash algorithms OpenKeychain wants to support! - - // don't allow MD5 - supported.add(HashAlgorithmTags.RIPEMD160); - // don't allow SHA1 - supported.add(HashAlgorithmTags.SHA224); - supported.add(HashAlgorithmTags.SHA384); - supported.add(HashAlgorithmTags.SHA512); - supported.add(HashAlgorithmTags.SHA256); // preferred is latest - // some application don't support SHA512, thus preferred is SHA-256 (Mailvelope?) + // TODO: intersection between preferred hash algos of this key and PgpConstants.PREFERRED_HASH_ALGORITHMS + // choose best algo + for (int currentInt : PgpConstants.PREFERRED_HASH_ALGORITHMS) { + supported.add(currentInt); } return supported; } - /** - * TODO: look into preferred algos of this key? - */ - public static LinkedList getSupportedEncryptionAlgorithms() { - LinkedList supported = new LinkedList<>(); - - supported.add(SymmetricKeyAlgorithmTags.TWOFISH); - supported.add(SymmetricKeyAlgorithmTags.AES_128); - supported.add(SymmetricKeyAlgorithmTags.AES_192); - supported.add(SymmetricKeyAlgorithmTags.AES_256); // preferred is latest - - return supported; - } - private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo, byte[] nfcSignedHash, Date nfcCreationTimestamp) { if (mPrivateKeyState == PRIVATE_KEY_STATE_DIVERT_TO_CARD) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java index 12de2f637..d8b86a18c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java @@ -47,26 +47,6 @@ public class PgpHelper { ".*?(-----BEGIN PGP PUBLIC KEY BLOCK-----.*?-----END PGP PUBLIC KEY BLOCK-----).*", Pattern.DOTALL); - public static String getVersion(Context context) { - String version; - try { - PackageInfo pi = context.getPackageManager().getPackageInfo(Constants.PACKAGE_NAME, 0); - version = pi.versionName; - return version; - } catch (NameNotFoundException e) { - Log.e(Constants.TAG, "Version could not be retrieved!", e); - return "0.0"; - } - } - - public static String getVersionForHeader(Context context) { - if(Preferences.getPreferences(context).getWriteVersionHeader()){ - return "OpenKeychain v" + getVersion(context); - } else { - return null; - } - } - /** * Deletes file securely by overwriting it with random data before deleting it. *

diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index a54fa189a..ac9acd41b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -18,9 +18,7 @@ package org.sufficientlysecure.keychain.pgp; -import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; -import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; import org.spongycastle.bcpg.sig.Features; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.jce.spec.ElGamalParameterSpec; @@ -90,49 +88,6 @@ public class PgpKeyOperation { private Stack mProgress; private AtomicBoolean mCancelled; - // most preferred is first - private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{ - SymmetricKeyAlgorithmTags.AES_256, - SymmetricKeyAlgorithmTags.AES_192, - SymmetricKeyAlgorithmTags.AES_128, - SymmetricKeyAlgorithmTags.TWOFISH - }; - private static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{ - HashAlgorithmTags.SHA512, - HashAlgorithmTags.SHA384, - HashAlgorithmTags.SHA256, - HashAlgorithmTags.SHA224, - HashAlgorithmTags.RIPEMD160 - }; - private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{ - CompressionAlgorithmTags.ZLIB, - CompressionAlgorithmTags.BZIP2, - CompressionAlgorithmTags.ZIP - }; - - /* - * Note: s2kcount is a number between 0 and 0xff that controls the - * number of times to iterate the password hash before use. More - * iterations are useful against offline attacks, as it takes more - * time to check each password. The actual number of iterations is - * rather complex, and also depends on the hash function in use. - * Refer to Section 3.7.1.3 in rfc4880.txt. Bigger numbers give - * you more iterations. As a rough rule of thumb, when using - * SHA256 as the hashing function, 0x10 gives you about 64 - * iterations, 0x20 about 128, 0x30 about 256 and so on till 0xf0, - * or about 1 million iterations. The maximum you can go to is - * 0xff, or about 2 million iterations. - * from http://kbsriram.com/2013/01/generating-rsa-keys-with-bouncycastle.html - * - * Bouncy Castle default: 0x60 - * kbsriram proposes 0xc0 - * we use 0x90, a good trade-off between usability and security against offline attacks - */ - private static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0x90; - private static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA256; - private static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256; - private static final int SECRET_KEY_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA256; - public PgpKeyOperation(Progressable progress) { super(); if (progress != null) { @@ -346,14 +301,14 @@ public class PgpKeyOperation { // Build key encrypter and decrypter based on passphrase PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder() - .build().get(SECRET_KEY_ENCRYPTOR_HASH_ALGO); + .build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO); PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( - SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, SECRET_KEY_ENCRYPTOR_S2K_COUNT) + PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, + encryptorHashCalc, PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray()); - // NOTE: only SHA1 is supported for key checksum calculations. PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder() - .build().get(HashAlgorithmTags.SHA1); + .build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO); PGPSecretKey masterSecretKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(), sha1Calc, true, keyEncryptor); @@ -880,14 +835,14 @@ public class PgpKeyOperation { PGPSecretKey sKey; { // Build key encrypter and decrypter based on passphrase PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder() - .build().get(SECRET_KEY_ENCRYPTOR_HASH_ALGO); + .build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO); PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( - SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, SECRET_KEY_ENCRYPTOR_S2K_COUNT) + PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, + PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); - // NOTE: only SHA1 is supported for key checksum calculations. PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder() - .build().get(HashAlgorithmTags.SHA1); + .build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO); sKey = new PGPSecretKey(keyPair.getPrivateKey(), pKey, sha1Calc, false, keyEncryptor); } @@ -1026,7 +981,8 @@ public class PgpKeyOperation { // add packet with EMPTY notation data (updates old one, but will be stripped later) PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO) + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), + PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); { // set subpackets @@ -1052,7 +1008,8 @@ public class PgpKeyOperation { // add packet with "pin" notation data PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO) + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), + PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); { // set subpackets @@ -1099,12 +1056,13 @@ public class PgpKeyOperation { OperationLog log, int indent) throws PGPException { PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build() - .get(SECRET_KEY_ENCRYPTOR_HASH_ALGO); + .get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO); PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); // Build key encryptor based on new passphrase PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder( - SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, SECRET_KEY_ENCRYPTOR_S2K_COUNT) + PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc, + PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( newPassphrase.toCharArray()); @@ -1237,7 +1195,8 @@ public class PgpKeyOperation { int flags, long expiry) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO) + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), + PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); @@ -1254,9 +1213,9 @@ public class PgpKeyOperation { * error than be ignored. */ /* non-critical subpackets: */ - hashedPacketsGen.setPreferredSymmetricAlgorithms(false, PREFERRED_SYMMETRIC_ALGORITHMS); - hashedPacketsGen.setPreferredHashAlgorithms(false, PREFERRED_HASH_ALGORITHMS); - hashedPacketsGen.setPreferredCompressionAlgorithms(false, PREFERRED_COMPRESSION_ALGORITHMS); + hashedPacketsGen.setPreferredSymmetricAlgorithms(false, PgpConstants.PREFERRED_SYMMETRIC_ALGORITHMS); + hashedPacketsGen.setPreferredHashAlgorithms(false, PgpConstants.PREFERRED_HASH_ALGORITHMS); + hashedPacketsGen.setPreferredCompressionAlgorithms(false, PgpConstants.PREFERRED_COMPRESSION_ALGORITHMS); hashedPacketsGen.setPrimaryUserID(false, primary); /* critical subpackets: we consider those important for a modern pgp implementation */ @@ -1280,7 +1239,8 @@ public class PgpKeyOperation { PGPUserAttributeSubpacketVector vector) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO) + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), + PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); @@ -1299,7 +1259,8 @@ public class PgpKeyOperation { PGPPrivateKey masterPrivateKey, PGPPublicKey pKey, String userId) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO) + masterPrivateKey.getPublicKeyPacket().getAlgorithm(), + PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); @@ -1313,7 +1274,7 @@ public class PgpKeyOperation { PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPPublicKey pKey) throws IOException, PGPException, SignatureException { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPublicKey.getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO) + masterPublicKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); @@ -1357,7 +1318,7 @@ public class PgpKeyOperation { PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); subHashedPacketsGen.setSignatureCreationTime(false, creationTime); PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - pKey.getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO) + pKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey); @@ -1378,7 +1339,7 @@ public class PgpKeyOperation { } PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPublicKey.getAlgorithm(), SECRET_KEY_SIGNATURE_HASH_ALGO) + masterPublicKey.getAlgorithm(), PgpConstants.SECRET_KEY_SIGNATURE_HASH_ALGO) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); sGen.init(PGPSignature.SUBKEY_BINDING, masterPrivateKey); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java index f22d107e4..1ed0a4720 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java @@ -12,10 +12,10 @@ public class PgpSignEncryptInput { protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED; protected long[] mEncryptionMasterKeyIds = null; protected String mSymmetricPassphrase = null; - protected int mSymmetricEncryptionAlgorithm = Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED; + protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED; protected long mSignatureMasterKeyId = Constants.key.none; protected Long mSignatureSubKeyId = null; - protected int mSignatureHashAlgorithm = Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED; + protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED; protected String mSignaturePassphrase = null; protected long mAdditionalEncryptId = Constants.key.none; protected byte[] mNfcSignedHash = null; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index d420ddb5a..7d0949c6c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -208,9 +208,9 @@ public class PgpSignEncryptOperation extends BaseOperation { // Use preferred hash algo int requestedAlgorithm = input.getSignatureHashAlgorithm(); LinkedList supported = signingKey.getSupportedHashAlgorithms(); - if (requestedAlgorithm == Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) { + if (requestedAlgorithm == PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) { // get most preferred - input.setSignatureHashAlgorithm(supported.getLast()); + input.setSignatureHashAlgorithm(supported.getFirst()); } else if (!supported.contains(requestedAlgorithm)) { log.add(LogType.MSG_PSE_ERROR_HASH_ALGO, indent); return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); @@ -224,9 +224,10 @@ public class PgpSignEncryptOperation extends BaseOperation { // Use preferred encryption algo int algo = input.getSymmetricEncryptionAlgorithm(); - if (algo == Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) { + if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) { // get most preferred - algo = CanonicalizedSecretKey.getSupportedEncryptionAlgorithms().getLast(); + // TODO: get from recipients + algo = PgpConstants.PREFERRED_SYMMETRIC_ALGORITHMS[0]; } // has Integrity packet enabled! JcePGPDataEncryptorBuilder encryptorBuilder = diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index d947ae053..6366e8536 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1372,8 +1372,7 @@ public class ProviderHelper { UncachedKeyRing keyRing = UncachedKeyRing.decodeFromData(data); ByteArrayOutputStream bos = new ByteArrayOutputStream(); - String version = PgpHelper.getVersionForHeader(mContext); - keyRing.encodeArmored(bos, version); + keyRing.encodeArmored(bos, null); String armoredKey = bos.toString("UTF-8"); Log.d(Constants.TAG, "armoredKey:" + armoredKey); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 38f7aa685..03fa41984 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -36,8 +36,10 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; +import org.sufficientlysecure.keychain.pgp.PgpConstants; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; import org.sufficientlysecure.keychain.pgp.PgpHelper; +import org.sufficientlysecure.keychain.pgp.PgpKeyOperation; import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInput; import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; @@ -260,8 +262,8 @@ public class OpenPgpService extends RemoteService { .setEnableAsciiArmorOutput(asciiArmor) .setCleartextSignature(cleartextSign) .setDetachedSignature(!cleartextSign) - .setVersionHeader(PgpHelper.getVersionForHeader(this)) - .setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm()) + .setVersionHeader(null) + .setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) .setSignatureMasterKeyId(accSettings.getKeyId()) .setNfcState(nfcSignedHash, nfcCreationDate); @@ -358,9 +360,9 @@ public class OpenPgpService extends RemoteService { PgpSignEncryptInput pseInput = new PgpSignEncryptInput(); pseInput.setEnableAsciiArmorOutput(asciiArmor) - .setVersionHeader(PgpHelper.getVersionForHeader(this)) + .setVersionHeader(null) .setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED) - .setSymmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()) + .setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) .setEncryptionMasterKeyIds(keyIds) .setFailOnMissingEncryptionKeyIds(true) .setAdditionalEncryptId(accSettings.getKeyId()); // add acc key for encryption @@ -376,7 +378,7 @@ public class OpenPgpService extends RemoteService { } // sign and encrypt - pseInput.setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm()) + pseInput.setSignatureHashAlgorithm(PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) .setSignatureMasterKeyId(accSettings.getKeyId()) .setNfcState(nfcSignedHash, nfcCreationDate); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java index 54fe369a7..baf445293 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java @@ -28,6 +28,7 @@ public interface EncryptActivityInterface { } public boolean isUseArmor(); + public boolean isUseCompression(); public long getSignatureKey(); public long[] getEncryptionKeys(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java index fab6c19f9..ac12faa3d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -25,11 +25,13 @@ import android.support.v4.app.Fragment; import android.view.Menu; import android.view.MenuItem; +import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.api.OpenKeychainIntents; import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.PgpConstants; import org.sufficientlysecure.keychain.pgp.SignEncryptParcel; import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; import org.sufficientlysecure.keychain.ui.util.Notify; @@ -66,6 +68,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi private long mSigningKeyId = Constants.key.none; private String mPassphrase = ""; private boolean mUseArmor; + private boolean mUseCompression; private boolean mDeleteAfterEncrypt = false; private boolean mShareAfterEncrypt = false; private ArrayList mInputUris; @@ -81,6 +84,11 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi return mUseArmor; } + @Override + public boolean isUseCompression() { + return mUseCompression; + } + @Override public long getSignatureKey() { return mSigningKeyId; @@ -196,12 +204,13 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi data.addInputUris(mInputUris); data.addOutputUris(mOutputUris); - data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression()); - data.setSymmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()); - data.setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm()); - - // Always use armor for messages - data.setEnableAsciiArmorOutput(mUseArmor); + if (mUseCompression) { + data.setCompressionId(CompressionAlgorithmTags.ZLIB); + } else { + data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); + } + data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); + data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); if (isModeSymmetric()) { Log.d(Constants.TAG, "Symmetric encryption enabled!"); @@ -317,8 +326,6 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi // Handle intent actions handleActions(getIntent()); updateModeFragment(); - - mUseArmor = Preferences.getPreferences(this).getDefaultAsciiArmor(); } @Override @@ -329,7 +336,6 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.encrypt_file_activity, menu); - menu.findItem(R.id.check_use_armor).setChecked(mUseArmor); return super.onCreateOptionsMenu(menu); } @@ -350,21 +356,30 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi item.setChecked(!item.isChecked()); } switch (item.getItemId()) { - case R.id.check_use_symmetric: + case R.id.check_use_symmetric: { mCurrentMode = item.isChecked() ? MODE_SYMMETRIC : MODE_ASYMMETRIC; updateModeFragment(); notifyUpdate(); break; - case R.id.check_use_armor: + } + case R.id.check_use_armor: { mUseArmor = item.isChecked(); notifyUpdate(); break; - case R.id.check_delete_after_encrypt: + } + case R.id.check_delete_after_encrypt: { mDeleteAfterEncrypt = item.isChecked(); notifyUpdate(); break; - default: + } + case R.id.check_enable_compression: { + mUseCompression = item.isChecked(); + notifyUpdate(); + break; + } + default: { return super.onOptionsItemSelected(item); + } } return true; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 05da7a3ba..9ec0bdd33 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -25,12 +25,14 @@ import android.support.v4.app.Fragment; import android.view.Menu; import android.view.MenuItem; +import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.api.OpenKeychainIntents; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.operations.results.SignEncryptResult; import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.PgpConstants; import org.sufficientlysecure.keychain.pgp.SignEncryptParcel; import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; @@ -70,6 +72,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv private ArrayList mInputUris; private ArrayList mOutputUris; private String mMessage = ""; + private boolean mUseCompression; public boolean isModeSymmetric() { return MODE_SYMMETRIC == mCurrentMode; @@ -80,6 +83,11 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv return true; } + @Override + public boolean isUseCompression() { + return mUseCompression; + } + @Override public long getSignatureKey() { return mSigningKeyId; @@ -189,9 +197,13 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv data.setBytes(mMessage.getBytes()); data.setCleartextSignature(true); - data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression()); - data.setSymmetricEncryptionAlgorithm(Preferences.getPreferences(this).getDefaultEncryptionAlgorithm()); - data.setSignatureHashAlgorithm(Preferences.getPreferences(this).getDefaultHashAlgorithm()); + if (mUseCompression) { + data.setCompressionId(CompressionAlgorithmTags.ZLIB); + } else { + data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); + } + data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); + data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); // Always use armor for messages data.setEnableAsciiArmorOutput(true); @@ -330,13 +342,20 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv item.setChecked(!item.isChecked()); } switch (item.getItemId()) { - case R.id.check_use_symmetric: + case R.id.check_use_symmetric: { mCurrentMode = item.isChecked() ? MODE_SYMMETRIC : MODE_ASYMMETRIC; updateModeFragment(); notifyUpdate(); break; - default: + } + case R.id.check_enable_compression: { + mUseCompression = item.isChecked(); + notifyUpdate(); + break; + } + default: { return super.onOptionsItemSelected(item); + } } return true; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java index d82be2571..210960b65 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java @@ -91,12 +91,6 @@ public class SettingsActivity extends PreferenceActivity { initializePassphraseCacheTtl( (IntegerListPreference) findPreference(Constants.Pref.PASSPHRASE_CACHE_TTL)); - initializeEncryptionAlgorithm( - (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM)); - - initializeHashAlgorithm( - (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_HASH_ALGORITHM)); - int[] valueIds = new int[]{ CompressionAlgorithmTags.UNCOMPRESSED, CompressionAlgorithmTags.ZIP, @@ -113,20 +107,6 @@ public class SettingsActivity extends PreferenceActivity { values[i] = "" + valueIds[i]; } - initializeMessageCompression( - (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION), - entries, values); - - initializeFileCompression( - (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_FILE_COMPRESSION), - entries, values); - - initializeAsciiArmor( - (CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOR)); - - initializeWriteVersionHeader( - (CheckBoxPreference) findPreference(Constants.Pref.WRITE_VERSION_HEADER)); - initializeUseDefaultYubikeyPin( (CheckBoxPreference) findPreference(Constants.Pref.USE_DEFAULT_YUBIKEY_PIN)); @@ -263,12 +243,6 @@ public class SettingsActivity extends PreferenceActivity { initializePassphraseCacheTtl( (IntegerListPreference) findPreference(Constants.Pref.PASSPHRASE_CACHE_TTL)); - initializeEncryptionAlgorithm( - (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM)); - - initializeHashAlgorithm( - (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_HASH_ALGORITHM)); - int[] valueIds = new int[]{ CompressionAlgorithmTags.UNCOMPRESSED, CompressionAlgorithmTags.ZIP, @@ -288,20 +262,6 @@ public class SettingsActivity extends PreferenceActivity { values[i] = "" + valueIds[i]; } - initializeMessageCompression( - (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION), - entries, values); - - initializeFileCompression( - (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_FILE_COMPRESSION), - entries, values); - - initializeAsciiArmor( - (CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOR)); - - initializeWriteVersionHeader( - (CheckBoxPreference) findPreference(Constants.Pref.WRITE_VERSION_HEADER)); - initializeUseDefaultYubikeyPin( (CheckBoxPreference) findPreference(Constants.Pref.USE_DEFAULT_YUBIKEY_PIN)); @@ -342,131 +302,6 @@ public class SettingsActivity extends PreferenceActivity { }); } - private static void initializeEncryptionAlgorithm(final IntegerListPreference mEncryptionAlgorithm) { - int valueIds[] = { - Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED, - Constants.OpenKeychainSymmetricKeyAlgorithmTags.AES_256, - Constants.OpenKeychainSymmetricKeyAlgorithmTags.AES_192, - Constants.OpenKeychainSymmetricKeyAlgorithmTags.AES_128, - Constants.OpenKeychainSymmetricKeyAlgorithmTags.TWOFISH, - }; - String entries[] = { - "Use preferred algorithm", - "AES-256", - "AES-192", - "AES-128", - "Twofish", - }; - String values[] = new String[valueIds.length]; - for (int i = 0; i < values.length; ++i) { - values[i] = "" + valueIds[i]; - } - mEncryptionAlgorithm.setEntries(entries); - mEncryptionAlgorithm.setEntryValues(values); - mEncryptionAlgorithm.setValue("" + sPreferences.getDefaultEncryptionAlgorithm()); - mEncryptionAlgorithm.setSummary(mEncryptionAlgorithm.getEntry()); - mEncryptionAlgorithm - .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - public boolean onPreferenceChange(Preference preference, Object newValue) { - mEncryptionAlgorithm.setValue(newValue.toString()); - mEncryptionAlgorithm.setSummary(mEncryptionAlgorithm.getEntry()); - sPreferences.setDefaultEncryptionAlgorithm(Integer.parseInt(newValue - .toString())); - return false; - } - }); - } - - private static void initializeHashAlgorithm(final IntegerListPreference mHashAlgorithm) { - int[] valueIds = new int[]{ - Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED, - Constants.OpenKeychainHashAlgorithmTags.SHA512, - Constants.OpenKeychainHashAlgorithmTags.SHA384, - Constants.OpenKeychainHashAlgorithmTags.SHA256, - Constants.OpenKeychainHashAlgorithmTags.SHA224, - Constants.OpenKeychainHashAlgorithmTags.RIPEMD160, - }; - String[] entries = new String[]{ - "Use preferred algorithm", - "SHA-512", - "SHA-384", - "SHA-256", - "SHA-224", - "RIPEMD-160"}; - String[] values = new String[valueIds.length]; - for (int i = 0; i < values.length; ++i) { - values[i] = "" + valueIds[i]; - } - mHashAlgorithm.setEntries(entries); - mHashAlgorithm.setEntryValues(values); - mHashAlgorithm.setValue("" + sPreferences.getDefaultHashAlgorithm()); - mHashAlgorithm.setSummary(mHashAlgorithm.getEntry()); - mHashAlgorithm.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - public boolean onPreferenceChange(Preference preference, Object newValue) { - mHashAlgorithm.setValue(newValue.toString()); - mHashAlgorithm.setSummary(mHashAlgorithm.getEntry()); - sPreferences.setDefaultHashAlgorithm(Integer.parseInt(newValue.toString())); - return false; - } - }); - } - - private static void initializeMessageCompression(final IntegerListPreference mMessageCompression, - String[] entries, String[] values) { - mMessageCompression.setEntries(entries); - mMessageCompression.setEntryValues(values); - mMessageCompression.setValue("" + sPreferences.getDefaultMessageCompression()); - mMessageCompression.setSummary(mMessageCompression.getEntry()); - mMessageCompression - .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - public boolean onPreferenceChange(Preference preference, Object newValue) { - mMessageCompression.setValue(newValue.toString()); - mMessageCompression.setSummary(mMessageCompression.getEntry()); - sPreferences.setDefaultMessageCompression(Integer.parseInt(newValue - .toString())); - return false; - } - }); - } - - private static void initializeFileCompression - (final IntegerListPreference mFileCompression, String[] entries, String[] values) { - mFileCompression.setEntries(entries); - mFileCompression.setEntryValues(values); - mFileCompression.setValue("" + sPreferences.getDefaultFileCompression()); - mFileCompression.setSummary(mFileCompression.getEntry()); - mFileCompression.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - public boolean onPreferenceChange(Preference preference, Object newValue) { - mFileCompression.setValue(newValue.toString()); - mFileCompression.setSummary(mFileCompression.getEntry()); - sPreferences.setDefaultFileCompression(Integer.parseInt(newValue.toString())); - return false; - } - }); - } - - private static void initializeAsciiArmor(final CheckBoxPreference mAsciiArmor) { - mAsciiArmor.setChecked(sPreferences.getDefaultAsciiArmor()); - mAsciiArmor.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - public boolean onPreferenceChange(Preference preference, Object newValue) { - mAsciiArmor.setChecked((Boolean) newValue); - sPreferences.setDefaultAsciiArmor((Boolean) newValue); - return false; - } - }); - } - - private static void initializeWriteVersionHeader(final CheckBoxPreference mWriteVersionHeader) { - mWriteVersionHeader.setChecked(sPreferences.getWriteVersionHeader()); - mWriteVersionHeader.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - public boolean onPreferenceChange(Preference preference, Object newValue) { - mWriteVersionHeader.setChecked((Boolean) newValue); - sPreferences.setWriteVersionHeader((Boolean) newValue); - return false; - } - }); - } - private static void initializeSearchKeyserver(final CheckBoxPreference mSearchKeyserver) { Preferences.CloudSearchPrefs prefs = sPreferences.getCloudSearchPrefs(); mSearchKeyserver.setChecked(prefs.searchKeyserver); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java index 089702de6..44c1e6b6c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java @@ -20,11 +20,7 @@ package org.sufficientlysecure.keychain.util; import android.content.Context; import android.content.SharedPreferences; -import android.os.Build; -import org.spongycastle.bcpg.CompressionAlgorithmTags; -import org.spongycastle.bcpg.HashAlgorithmTags; -import org.spongycastle.openpgp.PGPEncryptedData; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants.Pref; @@ -99,60 +95,6 @@ public class Preferences { editor.commit(); } - public int getDefaultEncryptionAlgorithm() { - return mSharedPreferences.getInt(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM, - PGPEncryptedData.AES_256); - } - - public void setDefaultEncryptionAlgorithm(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM, value); - editor.commit(); - } - - public int getDefaultHashAlgorithm() { - return mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, - HashAlgorithmTags.SHA256); - } - - public void setDefaultHashAlgorithm(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, value); - editor.commit(); - } - - public int getDefaultMessageCompression() { - return mSharedPreferences.getInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION, - CompressionAlgorithmTags.ZLIB); - } - - public void setDefaultMessageCompression(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION, value); - editor.commit(); - } - - public int getDefaultFileCompression() { - return mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, - CompressionAlgorithmTags.UNCOMPRESSED); - } - - public void setDefaultFileCompression(int value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, value); - editor.commit(); - } - - public boolean getDefaultAsciiArmor() { - return mSharedPreferences.getBoolean(Constants.Pref.DEFAULT_ASCII_ARMOR, false); - } - - public void setDefaultAsciiArmor(boolean value) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Constants.Pref.DEFAULT_ASCII_ARMOR, value); - editor.commit(); - } - public boolean getCachedConsolidate() { return mSharedPreferences.getBoolean(Pref.CACHED_CONSOLIDATE, false); } @@ -228,16 +170,6 @@ public class Preferences { editor.commit(); } - public void setWriteVersionHeader(boolean conceal) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Constants.Pref.WRITE_VERSION_HEADER, conceal); - editor.commit(); - } - - public boolean getWriteVersionHeader() { - return mSharedPreferences.getBoolean(Constants.Pref.WRITE_VERSION_HEADER, false); - } - public void setSearchKeyserver(boolean searchKeyserver) { SharedPreferences.Editor editor = mSharedPreferences.edit(); editor.putBoolean(Pref.SEARCH_KEYSERVER, searchKeyserver); @@ -299,32 +231,9 @@ public class Preferences { } setKeyServers(servers.toArray(new String[servers.size()])); - - // migrate old uncompressed constant to new one - if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_FILE_COMPRESSION, 0) - == 0x21070001) { - setDefaultFileCompression(CompressionAlgorithmTags.UNCOMPRESSED); - } - - // migrate away from MD5 - if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, 0) - == HashAlgorithmTags.MD5) { - setDefaultHashAlgorithm(HashAlgorithmTags.SHA256); - } } // fall through case 4: { - // for compatibility: change from SHA512 to SHA256 - if (mSharedPreferences.getInt(Constants.Pref.DEFAULT_HASH_ALGORITHM, 0) - == HashAlgorithmTags.SHA512) { - setDefaultHashAlgorithm(HashAlgorithmTags.SHA256); - } - } - // fall through - case 5: { - // use preferred hash and encryption algo setting - setDefaultHashAlgorithm(Constants.OpenKeychainHashAlgorithmTags.USE_PREFERRED); - setDefaultEncryptionAlgorithm(Constants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); } } diff --git a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml index fd0a85d6c..9a26d1757 100644 --- a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml +++ b/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml @@ -12,4 +12,9 @@ android:id="@+id/check_delete_after_encrypt" android:title="@string/label_delete_after_encryption" android:checkable="true" /> + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml index 8deb59514..71d254bb9 100644 --- a/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml +++ b/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml @@ -4,4 +4,9 @@ android:id="@+id/check_use_symmetric" android:title="@string/label_symmetric" android:checkable="true" /> + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 207553620..147201bc4 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -161,6 +161,7 @@ "Set expiry date" "(First keyserver listed is preferred)" "preferred" + "Enable compression" "<no name>" "<none>" diff --git a/OpenKeychain/src/main/res/xml/adv_preferences.xml b/OpenKeychain/src/main/res/xml/adv_preferences.xml index 02986bdad..7dd649e5d 100644 --- a/OpenKeychain/src/main/res/xml/adv_preferences.xml +++ b/OpenKeychain/src/main/res/xml/adv_preferences.xml @@ -1,52 +1,23 @@ - - - - - - - - - - - - - - + + + + diff --git a/OpenKeychain/src/main/res/xml/preference_headers.xml b/OpenKeychain/src/main/res/xml/preference_headers.xml index 347394b06..e3447ff48 100644 --- a/OpenKeychain/src/main/res/xml/preference_headers.xml +++ b/OpenKeychain/src/main/res/xml/preference_headers.xml @@ -4,5 +4,5 @@ android:title="@string/section_cloud_search" />

+ android:title="@string/section_passphrase_cache" /> -- cgit v1.2.3 From 0300bce41f85ed0a77ba43cac9ef69971f516c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 16:58:15 +0100 Subject: Add missing file with PGP Constants --- .../keychain/pgp/PgpConstants.java | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java new file mode 100644 index 000000000..3ed1d9d11 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java @@ -0,0 +1,69 @@ +package org.sufficientlysecure.keychain.pgp; + +import org.spongycastle.bcpg.CompressionAlgorithmTags; +import org.spongycastle.bcpg.HashAlgorithmTags; +import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; + +public class PgpConstants { + + public static interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags { + public static final int USE_PREFERRED = -1; + } + + public static interface OpenKeychainHashAlgorithmTags extends HashAlgorithmTags { + public static final int USE_PREFERRED = -1; + } + + public static interface OpenKeychainCompressionAlgorithmTags extends CompressionAlgorithmTags { + public static final int USE_PREFERRED = -1; + } + + // most preferred is first + public static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{ + SymmetricKeyAlgorithmTags.AES_256, + SymmetricKeyAlgorithmTags.AES_192, + SymmetricKeyAlgorithmTags.AES_128, + SymmetricKeyAlgorithmTags.TWOFISH + }; + + public static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{ + HashAlgorithmTags.SHA256, + HashAlgorithmTags.SHA512, + HashAlgorithmTags.SHA384, + HashAlgorithmTags.SHA224, + HashAlgorithmTags.RIPEMD160 + }; + + public static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{ + CompressionAlgorithmTags.ZLIB, + CompressionAlgorithmTags.BZIP2, + CompressionAlgorithmTags.ZIP + }; + + /* + * Note: s2kcount is a number between 0 and 0xff that controls the + * number of times to iterate the password hash before use. More + * iterations are useful against offline attacks, as it takes more + * time to check each password. The actual number of iterations is + * rather complex, and also depends on the hash function in use. + * Refer to Section 3.7.1.3 in rfc4880.txt. Bigger numbers give + * you more iterations. As a rough rule of thumb, when using + * SHA256 as the hashing function, 0x10 gives you about 64 + * iterations, 0x20 about 128, 0x30 about 256 and so on till 0xf0, + * or about 1 million iterations. The maximum you can go to is + * 0xff, or about 2 million iterations. + * from http://kbsriram.com/2013/01/generating-rsa-keys-with-bouncycastle.html + * + * Bouncy Castle default: 0x60 + * kbsriram proposes 0xc0 + * we use 0x90, a good trade-off between usability and security against offline attacks + */ + public static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0x90; + public static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA256; + public static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256; + public static final int SECRET_KEY_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA256; + // NOTE: only SHA1 is supported for key checksum calculations. + public static final int SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO = HashAlgorithmTags.SHA1; + + +} -- cgit v1.2.3 From aeb0169f02a02df8d591550c397a492917a535a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 17:24:56 +0100 Subject: Use static linked lists instead of arrays --- .../keychain/pgp/CanonicalizedSecretKey.java | 7 +-- .../keychain/pgp/PgpConstants.java | 66 ++++++++++++++-------- .../keychain/pgp/PgpKeyOperation.java | 9 ++- .../keychain/pgp/PgpSignEncryptOperation.java | 2 +- .../keychain/ui/EncryptFilesActivity.java | 2 +- .../keychain/ui/EncryptTextActivity.java | 2 +- 6 files changed, 53 insertions(+), 35 deletions(-) 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 9c74cf9a8..e4ed50f8f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -180,15 +180,10 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { * Returns a list of all supported hash algorithms. */ public LinkedList getSupportedHashAlgorithms() { - LinkedList supported = new LinkedList<>(); - // TODO: intersection between preferred hash algos of this key and PgpConstants.PREFERRED_HASH_ALGORITHMS // choose best algo - for (int currentInt : PgpConstants.PREFERRED_HASH_ALGORITHMS) { - supported.add(currentInt); - } - return supported; + return PgpConstants.sPreferredHashAlgorithms; } private PGPContentSignerBuilder getContentSignerBuilder(int hashAlgo, byte[] nfcSignedHash, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java index 3ed1d9d11..2a6465232 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java @@ -4,6 +4,8 @@ import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; +import java.util.LinkedList; + public class PgpConstants { public static interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags { @@ -18,27 +20,45 @@ public class PgpConstants { public static final int USE_PREFERRED = -1; } - // most preferred is first - public static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[]{ - SymmetricKeyAlgorithmTags.AES_256, - SymmetricKeyAlgorithmTags.AES_192, - SymmetricKeyAlgorithmTags.AES_128, - SymmetricKeyAlgorithmTags.TWOFISH - }; + /* + * Most preferred is first + * These arrays are written as preferred algorithms into the keys on creation. + * Other implementations may choose to honor this selection. + * + * These lists also define the only algorithms which are used in OpenKeychain. + * We do not support algorithms such as MD5 + */ + + public static LinkedList sPreferredSymmetricAlgorithms = new LinkedList<>(); + public static LinkedList sPreferredHashAlgorithms = new LinkedList<>(); + public static LinkedList sPreferredCompressionAlgorithms = new LinkedList<>(); - public static final int[] PREFERRED_HASH_ALGORITHMS = new int[]{ - HashAlgorithmTags.SHA256, - HashAlgorithmTags.SHA512, - HashAlgorithmTags.SHA384, - HashAlgorithmTags.SHA224, - HashAlgorithmTags.RIPEMD160 - }; + static { + sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_256); + sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_192); + sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_128); + sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.TWOFISH); - public static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[]{ - CompressionAlgorithmTags.ZLIB, - CompressionAlgorithmTags.BZIP2, - CompressionAlgorithmTags.ZIP - }; + // NOTE: some implementations do not support SHA512, thus we choose SHA256 as default (Mailvelope?) + sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA256); + sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA512); + sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA384); + sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA224); + sPreferredHashAlgorithms.add(HashAlgorithmTags.SHA1); + sPreferredHashAlgorithms.add(HashAlgorithmTags.RIPEMD160); + + sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.ZLIB); + sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.BZIP2); + sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.ZIP); + } + + public static int[] getAsArray(LinkedList list) { + int[] array = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); // Watch out for NullPointerExceptions! + } + return array; + } /* * Note: s2kcount is a number between 0 and 0xff that controls the @@ -55,15 +75,15 @@ public class PgpConstants { * from http://kbsriram.com/2013/01/generating-rsa-keys-with-bouncycastle.html * * Bouncy Castle default: 0x60 - * kbsriram proposes 0xc0 - * we use 0x90, a good trade-off between usability and security against offline attacks + * kbsriram proposes: 0xc0 + * OpenKeychain: 0x90 */ public static final int SECRET_KEY_ENCRYPTOR_S2K_COUNT = 0x90; public static final int SECRET_KEY_ENCRYPTOR_HASH_ALGO = HashAlgorithmTags.SHA256; public static final int SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO = SymmetricKeyAlgorithmTags.AES_256; public static final int SECRET_KEY_SIGNATURE_HASH_ALGO = HashAlgorithmTags.SHA256; - // NOTE: only SHA1 is supported for key checksum calculations. + // NOTE: only SHA1 is supported for key checksum calculations in OpenPGP, + // see http://tools.ietf.org/html/rfc488 0#section-5.5.3 public static final int SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO = HashAlgorithmTags.SHA1; - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index ac9acd41b..8fb5392e3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -1213,9 +1213,12 @@ public class PgpKeyOperation { * error than be ignored. */ /* non-critical subpackets: */ - hashedPacketsGen.setPreferredSymmetricAlgorithms(false, PgpConstants.PREFERRED_SYMMETRIC_ALGORITHMS); - hashedPacketsGen.setPreferredHashAlgorithms(false, PgpConstants.PREFERRED_HASH_ALGORITHMS); - hashedPacketsGen.setPreferredCompressionAlgorithms(false, PgpConstants.PREFERRED_COMPRESSION_ALGORITHMS); + hashedPacketsGen.setPreferredSymmetricAlgorithms(false, + PgpConstants.getAsArray(PgpConstants.sPreferredSymmetricAlgorithms)); + hashedPacketsGen.setPreferredHashAlgorithms(false, + PgpConstants.getAsArray(PgpConstants.sPreferredHashAlgorithms)); + hashedPacketsGen.setPreferredCompressionAlgorithms(false, + PgpConstants.getAsArray(PgpConstants.sPreferredCompressionAlgorithms)); hashedPacketsGen.setPrimaryUserID(false, primary); /* critical subpackets: we consider those important for a modern pgp implementation */ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index 7d0949c6c..59b95bdba 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -227,7 +227,7 @@ public class PgpSignEncryptOperation extends BaseOperation { if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) { // get most preferred // TODO: get from recipients - algo = PgpConstants.PREFERRED_SYMMETRIC_ALGORITHMS[0]; + algo = PgpConstants.sPreferredSymmetricAlgorithms.getFirst(); } // has Integrity packet enabled! JcePGPDataEncryptorBuilder encryptorBuilder = diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java index ac12faa3d..8b18d9353 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -205,7 +205,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi data.addOutputUris(mOutputUris); if (mUseCompression) { - data.setCompressionId(CompressionAlgorithmTags.ZLIB); + data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.getFirst()); } else { data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 9ec0bdd33..0f92bbb41 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -198,7 +198,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv data.setCleartextSignature(true); if (mUseCompression) { - data.setCompressionId(CompressionAlgorithmTags.ZLIB); + data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.getFirst()); } else { data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); } -- cgit v1.2.3 From 3bc3e3e6f48235da680860f546fad32ab84e012f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 17:46:43 +0100 Subject: Check for insecure hash and symmetric encryption algos on decrypt --- .../operations/results/OperationResult.java | 2 ++ .../keychain/pgp/PgpDecryptVerify.java | 30 ++++++++++++++++++++++ OpenKeychain/src/main/res/values/strings.xml | 2 ++ 3 files changed, 34 insertions(+) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index 54cd9b1b4..a96cec8cf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -626,6 +626,7 @@ public abstract class OperationResult implements Parcelable { MSG_DC_ERROR_NO_DATA (LogLevel.ERROR, R.string.msg_dc_error_no_data), MSG_DC_ERROR_NO_KEY (LogLevel.ERROR, R.string.msg_dc_error_no_key), MSG_DC_ERROR_PGP_EXCEPTION (LogLevel.ERROR, R.string.msg_dc_error_pgp_exception), + MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO (LogLevel.ERROR, R.string.msg_dc_error_unsupported_hash_algo), MSG_DC_INTEGRITY_CHECK_OK (LogLevel.INFO, R.string.msg_dc_integrity_check_ok), MSG_DC_OK_META_ONLY (LogLevel.OK, R.string.msg_dc_ok_meta_only), MSG_DC_OK (LogLevel.OK, R.string.msg_dc_ok), @@ -640,6 +641,7 @@ public abstract class OperationResult implements Parcelable { MSG_DC_TRAIL_SYM (LogLevel.DEBUG, R.string.msg_dc_trail_sym), MSG_DC_TRAIL_UNKNOWN (LogLevel.DEBUG, R.string.msg_dc_trail_unknown), MSG_DC_UNLOCKING (LogLevel.INFO, R.string.msg_dc_unlocking), + MSG_DC_OLD_SYMMETRIC_ENCRYPTION_ALGO (LogLevel.WARN, R.string.msg_dc_old_symmetric_encryption_algo), // verify signed literal data MSG_VL (LogLevel.INFO, R.string.msg_vl), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 2ba0b6231..14bc56538 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -563,6 +563,7 @@ public class PgpDecryptVerify extends BaseOperation { log.add(LogType.MSG_DC_PREP_STREAMS, indent); // we made sure above one of these two would be true + int symmetricEncryptionAlgo; if (symmetricPacketFound) { currentProgress += 2; updateProgress(R.string.progress_preparing_streams, currentProgress, 100); @@ -576,6 +577,7 @@ public class PgpDecryptVerify extends BaseOperation { clear = encryptedDataSymmetric.getDataStream(decryptorFactory); encryptedData = encryptedDataSymmetric; + symmetricEncryptionAlgo = encryptedDataSymmetric.getSymmetricAlgorithm(decryptorFactory); } else if (asymmetricPacketFound) { currentProgress += 2; updateProgress(R.string.progress_extracting_key, currentProgress, 100); @@ -598,6 +600,8 @@ public class PgpDecryptVerify extends BaseOperation { PublicKeyDataDecryptorFactory decryptorFactory = secretEncryptionKey.getDecryptorFactory(mDecryptedSessionKey); clear = encryptedDataAsymmetric.getDataStream(decryptorFactory); + + symmetricEncryptionAlgo = encryptedDataAsymmetric.getSymmetricAlgorithm(decryptorFactory); } catch (NfcSyncPublicKeyDataDecryptorFactoryBuilder.NfcInteractionNeeded e) { log.add(LogType.MSG_DC_PENDING_NFC, indent + 1); DecryptVerifyResult result = @@ -614,6 +618,11 @@ public class PgpDecryptVerify extends BaseOperation { return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log); } + // Warn about old encryption algorithms! + if (!PgpConstants.sPreferredSymmetricAlgorithms.contains(symmetricEncryptionAlgo)) { + log.add(LogType.MSG_DC_OLD_SYMMETRIC_ENCRYPTION_ALGO, indent + 1); + } + JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear); Object dataChunk = plainFact.nextObject(); OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder(); @@ -811,6 +820,13 @@ public class PgpDecryptVerify extends BaseOperation { } else { log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1); } + + // Don't allow verification of old hash algorithms! + if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) { + validSignature = false; + log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1); + } + signatureResultBuilder.setValidSignature(validSignature); } @@ -936,6 +952,13 @@ public class PgpDecryptVerify extends BaseOperation { } else { log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1); } + + // Don't allow verification of old hash algorithms! + if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) { + validSignature = false; + log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1); + } + signatureResultBuilder.setValidSignature(validSignature); } catch (SignatureException e) { @@ -1024,6 +1047,13 @@ public class PgpDecryptVerify extends BaseOperation { } else { log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1); } + + // Don't allow verification of old hash algorithms! + if (!PgpConstants.sPreferredHashAlgorithms.contains(signature.getHashAlgorithm())) { + validSignature = false; + log.add(LogType.MSG_DC_ERROR_UNSUPPORTED_HASH_ALGO, indent + 1); + } + signatureResultBuilder.setValidSignature(validSignature); } diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 147201bc4..d9460882c 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -988,6 +988,7 @@ "File size is unknown" "Modification time: %s" "Signature check NOT OK!" + "Unsupported and potentially insecure hash algorithm!" "Verifying signature data" "Signature check OK" "Saving signature data for later" @@ -1015,6 +1016,7 @@ "Encountered trailing, symmetrically encrypted data" "Encountered trailing data of unknown type" "Unlocking secret key" + "Potentially insecure encryption algorithm has been used!" "Starting signature check" -- cgit v1.2.3 From afbb166de6ada76967cb671ba688445496cb24f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 17:52:12 +0100 Subject: Add missing header --- .../sufficientlysecure/keychain/pgp/PgpConstants.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java index 2a6465232..6c0a9bd48 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * + * 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 org.spongycastle.bcpg.CompressionAlgorithmTags; -- cgit v1.2.3 From 02084ba14a5d1055dbb99d9f068b993310e0b517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 17:53:14 +0100 Subject: Cleanup of PgpConstants --- .../keychain/pgp/PgpConstants.java | 46 +++++++++++----------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java index 6c0a9bd48..c0e254574 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java @@ -25,17 +25,9 @@ import java.util.LinkedList; public class PgpConstants { - public static interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags { - public static final int USE_PREFERRED = -1; - } - - public static interface OpenKeychainHashAlgorithmTags extends HashAlgorithmTags { - public static final int USE_PREFERRED = -1; - } - - public static interface OpenKeychainCompressionAlgorithmTags extends CompressionAlgorithmTags { - public static final int USE_PREFERRED = -1; - } + public static LinkedList sPreferredSymmetricAlgorithms = new LinkedList<>(); + public static LinkedList sPreferredHashAlgorithms = new LinkedList<>(); + public static LinkedList sPreferredCompressionAlgorithms = new LinkedList<>(); /* * Most preferred is first @@ -45,11 +37,6 @@ public class PgpConstants { * These lists also define the only algorithms which are used in OpenKeychain. * We do not support algorithms such as MD5 */ - - public static LinkedList sPreferredSymmetricAlgorithms = new LinkedList<>(); - public static LinkedList sPreferredHashAlgorithms = new LinkedList<>(); - public static LinkedList sPreferredCompressionAlgorithms = new LinkedList<>(); - static { sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_256); sPreferredSymmetricAlgorithms.add(SymmetricKeyAlgorithmTags.AES_192); @@ -69,14 +56,6 @@ public class PgpConstants { sPreferredCompressionAlgorithms.add(CompressionAlgorithmTags.ZIP); } - public static int[] getAsArray(LinkedList list) { - int[] array = new int[list.size()]; - for (int i = 0; i < list.size(); i++) { - array[i] = list.get(i); // Watch out for NullPointerExceptions! - } - return array; - } - /* * Note: s2kcount is a number between 0 and 0xff that controls the * number of times to iterate the password hash before use. More @@ -103,4 +82,23 @@ public class PgpConstants { // see http://tools.ietf.org/html/rfc488 0#section-5.5.3 public static final int SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO = HashAlgorithmTags.SHA1; + public static interface OpenKeychainSymmetricKeyAlgorithmTags extends SymmetricKeyAlgorithmTags { + public static final int USE_PREFERRED = -1; + } + + public static interface OpenKeychainHashAlgorithmTags extends HashAlgorithmTags { + public static final int USE_PREFERRED = -1; + } + + public static interface OpenKeychainCompressionAlgorithmTags extends CompressionAlgorithmTags { + public static final int USE_PREFERRED = -1; + } + + public static int[] getAsArray(LinkedList list) { + int[] array = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + return array; + } } -- cgit v1.2.3 From e50eda4e29e4618e29756f19ec67b1d5ac0e9733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 17:59:53 +0100 Subject: Use ArrayList instead of LinkedList --- .../keychain/pgp/CanonicalizedSecretKey.java | 3 ++- .../java/org/sufficientlysecure/keychain/pgp/PgpConstants.java | 10 +++++----- .../keychain/pgp/PgpSignEncryptOperation.java | 7 ++++--- .../sufficientlysecure/keychain/ui/EncryptFilesActivity.java | 2 +- .../sufficientlysecure/keychain/ui/EncryptTextActivity.java | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) 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 e4ed50f8f..fe5db8c6d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; @@ -179,7 +180,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { /** * Returns a list of all supported hash algorithms. */ - public LinkedList getSupportedHashAlgorithms() { + public ArrayList getSupportedHashAlgorithms() { // TODO: intersection between preferred hash algos of this key and PgpConstants.PREFERRED_HASH_ALGORITHMS // choose best algo diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java index c0e254574..ba2a54b1a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpConstants.java @@ -21,13 +21,13 @@ import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; -import java.util.LinkedList; +import java.util.ArrayList; public class PgpConstants { - public static LinkedList sPreferredSymmetricAlgorithms = new LinkedList<>(); - public static LinkedList sPreferredHashAlgorithms = new LinkedList<>(); - public static LinkedList sPreferredCompressionAlgorithms = new LinkedList<>(); + public static ArrayList sPreferredSymmetricAlgorithms = new ArrayList<>(); + public static ArrayList sPreferredHashAlgorithms = new ArrayList<>(); + public static ArrayList sPreferredCompressionAlgorithms = new ArrayList<>(); /* * Most preferred is first @@ -94,7 +94,7 @@ public class PgpConstants { public static final int USE_PREFERRED = -1; } - public static int[] getAsArray(LinkedList list) { + public static int[] getAsArray(ArrayList list) { int[] array = new int[list.size()]; for (int i = 0; i < list.size(); i++) { array[i] = list.get(i); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index 59b95bdba..81cc2c847 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -57,6 +57,7 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.security.SignatureException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.LinkedList; @@ -207,10 +208,10 @@ public class PgpSignEncryptOperation extends BaseOperation { // Use preferred hash algo int requestedAlgorithm = input.getSignatureHashAlgorithm(); - LinkedList supported = signingKey.getSupportedHashAlgorithms(); + ArrayList supported = signingKey.getSupportedHashAlgorithms(); if (requestedAlgorithm == PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED) { // get most preferred - input.setSignatureHashAlgorithm(supported.getFirst()); + input.setSignatureHashAlgorithm(supported.get(0)); } else if (!supported.contains(requestedAlgorithm)) { log.add(LogType.MSG_PSE_ERROR_HASH_ALGO, indent); return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); @@ -227,7 +228,7 @@ public class PgpSignEncryptOperation extends BaseOperation { if (algo == PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED) { // get most preferred // TODO: get from recipients - algo = PgpConstants.sPreferredSymmetricAlgorithms.getFirst(); + algo = PgpConstants.sPreferredSymmetricAlgorithms.get(0); } // has Integrity packet enabled! JcePGPDataEncryptorBuilder encryptorBuilder = diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java index 8b18d9353..11b596c24 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -205,7 +205,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi data.addOutputUris(mOutputUris); if (mUseCompression) { - data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.getFirst()); + data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0)); } else { data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 0f92bbb41..08ff5b962 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -198,7 +198,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv data.setCleartextSignature(true); if (mUseCompression) { - data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.getFirst()); + data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0)); } else { data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); } -- cgit v1.2.3 From 0bb3b9c6cc8ef12f0ef19238e0ba5fe0f3df2e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 5 Mar 2015 23:39:41 +0100 Subject: Format code of merged password strength widget --- .../PasswordStrengthBarView.java | 23 ++++---- .../PasswordStrengthView.java | 66 +++++++++++++--------- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java index c1db823b3..9e06c4cce 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java @@ -34,7 +34,6 @@ import android.util.AttributeSet; /** * Created by matt on 04/07/2014. * https://github.com/matt-allen/android-password-strength-indicator - * */ public class PasswordStrengthBarView extends PasswordStrengthView { @@ -65,12 +64,12 @@ public class PasswordStrengthBarView extends PasswordStrengthView { if (mShowGuides) { // TODO: Try and do this with a loop, for efficiency // Draw bottom guide border - float positionY = getHeight()-getPaddingBottom()-getPaddingTop(); - float notchHeight = (float)(positionY * 0.8); + float positionY = getHeight() - getPaddingBottom() - getPaddingTop(); + float notchHeight = (float) (positionY * 0.8); canvas.drawLine( getPaddingLeft(), positionY, - getWidth()-getPaddingRight(), + getWidth() - getPaddingRight(), positionY, mGuidePaint); // Show left-most notch @@ -83,33 +82,33 @@ public class PasswordStrengthBarView extends PasswordStrengthView { ); // Show middle-left notch canvas.drawLine( - (float)(mIndicatorWidth*0.25)+getPaddingLeft(), + (float) (mIndicatorWidth * 0.25) + getPaddingLeft(), positionY, - (float)(mIndicatorWidth*0.25)+getPaddingLeft(), + (float) (mIndicatorWidth * 0.25) + getPaddingLeft(), notchHeight, mGuidePaint ); // Show the middle notch canvas.drawLine( - (float)(mIndicatorWidth*0.5)+getPaddingLeft(), + (float) (mIndicatorWidth * 0.5) + getPaddingLeft(), positionY, - (float)(mIndicatorWidth*0.5)+getPaddingLeft(), + (float) (mIndicatorWidth * 0.5) + getPaddingLeft(), notchHeight, mGuidePaint ); // Show the middle-right notch canvas.drawLine( - (float)(mIndicatorWidth*0.75)+getPaddingLeft(), + (float) (mIndicatorWidth * 0.75) + getPaddingLeft(), positionY, - (float)(mIndicatorWidth*0.75)+getPaddingLeft(), + (float) (mIndicatorWidth * 0.75) + getPaddingLeft(), notchHeight, mGuidePaint ); // Show the right-most notch canvas.drawLine( - mIndicatorWidth+getPaddingLeft(), + mIndicatorWidth + getPaddingLeft(), positionY, - mIndicatorWidth+getPaddingLeft(), + mIndicatorWidth + getPaddingLeft(), notchHeight, mGuidePaint ); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java index 47e6d9527..d7270ff58 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java @@ -38,15 +38,15 @@ import org.sufficientlysecure.keychain.R; * 01/07/14 * http://www.mattallensoftware.co.uk * mattallen092@gmail.com - * - * https://github.com/matt-allen/android-password-strength-indicator - * + *

+ * https://github.com/matt-allen/android-password-strength-indicator + *

*

* This View is designed to indicate how secure a user-entered password is in a visual way to * relay to the user if they need to make it stronger. The strength of the password can be set * at creation (or after) which will decide whether their password is strong enough. *

- * + *

*

* The password strength is decided by an index of 20. The minimum score needed to pass is 10 * which means the String has met the conditions imposed by the strength test, but can be improved. @@ -113,7 +113,7 @@ public class PasswordStrengthView extends View { mColorWeak = style.getColor(R.styleable.PasswordStrengthView_color_weak, COLOR_WEAK); mColorStrong = style.getColor(R.styleable.PasswordStrengthView_color_strong, COLOR_STRONG); - } catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); } // Create and style the paint used for drawing the guide on the indicator @@ -128,6 +128,7 @@ public class PasswordStrengthView extends View { /** * This view can determine if the password entered by the user is acceptable for * use by your use case. This is based on the strength requirement you have set. + * * @return True if requirement has been met */ public boolean isStrengthRequirementMet() { @@ -137,10 +138,11 @@ public class PasswordStrengthView extends View { /** * Change the strength requirement of the password entered by the user. This will also * re-check the password already entered against these new requirements. + * * @param requiredStrength Use the public constants of this class to set */ public void setStrengthRequirement(int requiredStrength) { - if(requiredStrength >= 0 && requiredStrength <= 2){ + if (requiredStrength >= 0 && requiredStrength <= 2) { mStrengthRequirement = requiredStrength; if (mPassword != null && mPassword.length() > 0) { generatePasswordScore(); @@ -155,10 +157,11 @@ public class PasswordStrengthView extends View { /** * Update the password string to check strength of + * * @param passwordString String representation of user-input */ public void setPassword(String passwordString) { - if(passwordString != null && passwordString.length() > 0) { + if (passwordString != null && passwordString.length() > 0) { mPassword = passwordString; generatePasswordScore(); } else { @@ -173,13 +176,14 @@ public class PasswordStrengthView extends View { /** * Private convenience method for adding to the password score + * * @param score Amount to be added to current score */ protected void addToPasswordScore(int score) { int newScore = mCurrentScore + score; // Limit max score - if (newScore > 20){ + if (newScore > 20) { mCurrentScore = 20; } else { mCurrentScore = newScore; @@ -188,6 +192,7 @@ public class PasswordStrengthView extends View { /** * Call this to determine the current strength requirement set on the algorithm + * * @return Int representation of the current strength set for the indicator */ public int getStrengthRequirement() { @@ -203,23 +208,23 @@ public class PasswordStrengthView extends View { int upperCase = getUppercaseCount(mPassword); int nonAlpha = getNonAlphanumericCount(mPassword); int numbers = getNumberCount(mPassword); - switch (mStrengthRequirement){ + switch (mStrengthRequirement) { case STRENGTH_WEAK: - addToPasswordScore(mPassword.length()*2); - addToPasswordScore(upperCase*2); - addToPasswordScore(nonAlpha*2); - addToPasswordScore(numbers*2); + addToPasswordScore(mPassword.length() * 2); + addToPasswordScore(upperCase * 2); + addToPasswordScore(nonAlpha * 2); + addToPasswordScore(numbers * 2); break; case STRENGTH_MEDIUM: addToPasswordScore(mPassword.length()); addToPasswordScore(upperCase); - addToPasswordScore(nonAlpha*2); + addToPasswordScore(nonAlpha * 2); addToPasswordScore(numbers); break; case STRENGTH_STRONG: - addToPasswordScore(mPassword.length()/2); + addToPasswordScore(mPassword.length() / 2); // Cut the score in half to make this a very high requirement addToPasswordScore(upperCase); addToPasswordScore(nonAlpha); @@ -241,7 +246,8 @@ public class PasswordStrengthView extends View { * The standard parts of the onMeasure needed to create the password strength * indicator. Subclasses should call super.onMeasure, but also need to set * the minimum height and width in the constructor. - * @param widthMeasureSpec The measurement given by the system + * + * @param widthMeasureSpec The measurement given by the system * @param heightMeasureSpec The measurement given by the system */ @Override @@ -264,8 +270,7 @@ public class PasswordStrengthView extends View { int color = mColorFail; if (mCurrentScore >= 18) { color = mColorStrong; - } - else if (mCurrentScore >= 10) { + } else if (mCurrentScore >= 10) { color = mColorWeak; } mIndicatorPaint.setColor(color); @@ -273,14 +278,15 @@ public class PasswordStrengthView extends View { /** * Quick method to determine how many of the characters in a given string are upper case + * * @param stringToCheck The string to examine * @return Number of upper case characters */ protected int getUppercaseCount(String stringToCheck) { int score = 0; - int loops = stringToCheck.length()-1; - for (int i=0;i<=loops;i++){ - if(Character.isUpperCase(stringToCheck.charAt(i))) { + int loops = stringToCheck.length() - 1; + for (int i = 0; i <= loops; i++) { + if (Character.isUpperCase(stringToCheck.charAt(i))) { score++; } } @@ -290,15 +296,16 @@ public class PasswordStrengthView extends View { /** * A convenience method to determine how many characters in the given String aren't * letters or numbers. + * * @param stringToCheck * @return Number of characters that aren't numbers or letters */ protected int getNonAlphanumericCount(String stringToCheck) { int score = 0; - int loops = stringToCheck.length()-1; - for (int i=0;i<=loops;i++) { - if(!Character.isLetter(stringToCheck.charAt(i)) && - !Character.isDigit(stringToCheck.charAt(i))){ + int loops = stringToCheck.length() - 1; + for (int i = 0; i <= loops; i++) { + if (!Character.isLetter(stringToCheck.charAt(i)) && + !Character.isDigit(stringToCheck.charAt(i))) { score++; } } @@ -307,14 +314,15 @@ public class PasswordStrengthView extends View { /** * A convenience method for returning the count of numbers in a given String. + * * @param stringToCheck * @return The numbers of digits in the String */ protected int getNumberCount(String stringToCheck) { int score = 0; - int loops = stringToCheck.length()-1; - for (int i=0;i<=loops;i++) { - if(Character.isDigit(stringToCheck.charAt(i))) { + int loops = stringToCheck.length() - 1; + for (int i = 0; i <= loops; i++) { + if (Character.isDigit(stringToCheck.charAt(i))) { score++; } } @@ -326,6 +334,7 @@ public class PasswordStrengthView extends View { * On the line style, the guides will show underneath
* On the rounded style, the guides will be shown on the outer edges.
* The view will be redrawn after the method is called. + * * @param showGuides True if you want the guides to be shown */ public void setShowGuides(boolean showGuides) { @@ -342,6 +351,7 @@ public class PasswordStrengthView extends View { /** * Determine whether the view is showing the guides for the password score + * * @return True if the guides are being shown */ public boolean isShowingGuides() { -- cgit v1.2.3 From d83219f3a0915c30b297aeaadfb37f1ba966d5c1 Mon Sep 17 00:00:00 2001 From: chipset95 Date: Fri, 6 Mar 2015 11:13:56 +0530 Subject: Created EmailEditText, PasswordEditText and implemented wherever required --- .../keychain/ui/CreateKeyInputFragment.java | 56 ++------------- .../ui/dialog/AddUserIdDialogFragment.java | 36 +--------- .../ui/dialog/SetPassphraseDialogFragment.java | 10 ++- .../keychain/ui/widget/EmailEditText.java | 80 +++++++++++++++++++++ .../keychain/ui/widget/PasswordEditText.java | 84 ++++++++++++++++++++++ .../src/main/res/layout/add_user_id_dialog.xml | 3 +- .../main/res/layout/create_key_input_fragment.xml | 12 ++-- .../main/res/layout/passphrase_repeat_dialog.xml | 35 ++++++--- 8 files changed, 215 insertions(+), 101 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java index 115614808..b496d40fd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java @@ -20,9 +20,6 @@ package org.sufficientlysecure.keychain.ui; import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Patterns; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -33,19 +30,19 @@ import android.widget.EditText; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; +import org.sufficientlysecure.keychain.ui.widget.EmailEditText; +import org.sufficientlysecure.keychain.ui.widget.PasswordEditText; import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthView; import org.sufficientlysecure.keychain.util.ContactHelper; -import java.util.regex.Matcher; - public class CreateKeyInputFragment extends Fragment { CreateKeyActivity mCreateKeyActivity; PasswordStrengthView mPassphraseStrengthView; AutoCompleteTextView mNameEdit; - AutoCompleteTextView mEmailEdit; - EditText mPassphraseEdit; + EmailEditText mEmailEdit; + PasswordEditText mPassphraseEdit; EditText mPassphraseEditAgain; View mCreateButton; @@ -74,8 +71,8 @@ public class CreateKeyInputFragment extends Fragment { mPassphraseStrengthView = (PasswordStrengthView) view.findViewById(R.id .create_key_passphrase_strength); mNameEdit = (AutoCompleteTextView) view.findViewById(R.id.create_key_name); - mEmailEdit = (AutoCompleteTextView) view.findViewById(R.id.create_key_email); - mPassphraseEdit = (EditText) view.findViewById(R.id.create_key_passphrase); + mEmailEdit = (EmailEditText) view.findViewById(R.id.create_key_email); + mPassphraseEdit = (PasswordEditText) view.findViewById(R.id.create_key_passphrase); mPassphraseEditAgain = (EditText) view.findViewById(R.id.create_key_passphrase_again); mCreateButton = view.findViewById(R.id.create_key_button); @@ -99,33 +96,7 @@ public class CreateKeyInputFragment extends Fragment { ContactHelper.getPossibleUserEmails(getActivity()) ) ); - mEmailEdit.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { - } - @Override - public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { - } - - @Override - public void afterTextChanged(Editable editable) { - String email = editable.toString(); - if (email.length() > 0) { - Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); - if (emailMatcher.matches()) { - mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, - R.drawable.uid_mail_ok, 0); - } else { - mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, - R.drawable.uid_mail_bad, 0); - } - } else { - // remove drawable if email is empty - mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - } - } - }); mNameEdit.setThreshold(1); // Start working from first character mNameEdit.setAdapter( @@ -141,21 +112,8 @@ public class CreateKeyInputFragment extends Fragment { mPassphraseEdit.getPaddingTop(), (int) (56 * getResources().getDisplayMetrics().density), mPassphraseEdit.getPaddingBottom()); - mPassphraseEdit.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - @Override - public void afterTextChanged(Editable editable) { - String passphrase = editable.toString(); - mPassphraseStrengthView.setPassword(passphrase); - } - }); + mPassphraseEdit.setPasswordStrengthView(mPassphraseStrengthView); mCreateButton.setOnClickListener(new View.OnClickListener() { @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java index 094c4d8a9..ee4af8cbe 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java @@ -28,9 +28,6 @@ import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.support.v4.app.DialogFragment; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Patterns; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; @@ -46,11 +43,10 @@ import android.widget.TextView.OnEditorActionListener; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.ui.widget.EmailEditText; import org.sufficientlysecure.keychain.util.ContactHelper; import org.sufficientlysecure.keychain.util.Log; -import java.util.regex.Matcher; - public class AddUserIdDialogFragment extends DialogFragment implements OnEditorActionListener { private static final String ARG_MESSENGER = "messenger"; private static final String ARG_NAME = "name"; @@ -62,7 +58,7 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA private Messenger mMessenger; private AutoCompleteTextView mName; - private AutoCompleteTextView mEmail; + private EmailEditText mEmail; private EditText mComment; public static AddUserIdDialogFragment newInstance(Messenger messenger, String predefinedName) { @@ -99,38 +95,12 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA alert.setView(view); mName = (AutoCompleteTextView) view.findViewById(R.id.add_user_id_name); - mEmail = (AutoCompleteTextView) view.findViewById(R.id.add_user_id_address); + mEmail = (EmailEditText) view.findViewById(R.id.add_user_id_address); mComment = (EditText) view.findViewById(R.id.add_user_id_comment); mName.setText(predefinedName); - mEmail.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - @Override - public void afterTextChanged(Editable editable) { - String email = editable.toString(); - if (email.length() > 0) { - Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); - if (emailMatcher.matches()) { - mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, - R.drawable.uid_mail_ok, 0); - } else { - mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, - R.drawable.uid_mail_bad, 0); - } - } else { - // remove drawable if email is empty - mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - } - } - }); mEmail.setThreshold(1); // Start working from first character mEmail.setAdapter(autoCompleteEmailAdapter); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java index a3ffe250b..9e1f21f60 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java @@ -43,6 +43,8 @@ import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.widget.PasswordEditText; +import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthView; import org.sufficientlysecure.keychain.util.Log; public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener { @@ -55,9 +57,10 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi public static final String MESSAGE_NEW_PASSPHRASE = "new_passphrase"; private Messenger mMessenger; - private EditText mPassphraseEditText; + private PasswordEditText mPassphraseEditText; private EditText mPassphraseAgainEditText; private CheckBox mNoPassphraseCheckBox; + private PasswordStrengthView mPassphraseStrengthView; /** * Creates new instance of this dialog fragment @@ -97,9 +100,12 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi View view = inflater.inflate(R.layout.passphrase_repeat_dialog, null); alert.setView(view); - mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase); + mPassphraseEditText = (PasswordEditText) view.findViewById(R.id.passphrase_passphrase); mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again); mNoPassphraseCheckBox = (CheckBox) view.findViewById(R.id.passphrase_no_passphrase); + mPassphraseStrengthView = (PasswordStrengthView) view.findViewById(R.id.passphrase_repeat_passphrase_strength); + mPassphraseEditText.setPasswordStrengthView(mPassphraseStrengthView); + if (TextUtils.isEmpty(oldPassphrase)) { mNoPassphraseCheckBox.setChecked(true); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java new file mode 100644 index 000000000..22845fda0 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java @@ -0,0 +1,80 @@ +package org.sufficientlysecure.keychain.ui.widget; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.text.Editable; +import android.text.InputType; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.util.Patterns; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.util.ContactHelper; + +import java.util.regex.Matcher; + +public class EmailEditText extends AutoCompleteTextView { + EmailEditText emailEditText; + + public EmailEditText(Context context) { + super(context); + emailEditText = this; + this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); + this.addTextChangedListener(textWatcher); + } + + public EmailEditText(Context context, AttributeSet attrs) { + super(context, attrs); + emailEditText = this; + this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); + this.addTextChangedListener(textWatcher); + } + + public EmailEditText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + emailEditText = this; + this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); + this.addTextChangedListener(textWatcher); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public EmailEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + emailEditText = this; + this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); + this.addTextChangedListener(textWatcher); + } + + TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable editable) { + String email = editable.toString(); + if (email.length() > 0) { + Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); + if (emailMatcher.matches()) { + emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0, + R.drawable.uid_mail_ok, 0); + } else { + emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0, + R.drawable.uid_mail_bad, 0); + } + } else { + // remove drawable if email is empty + emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + } + }; +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java new file mode 100644 index 000000000..dea9e5163 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java @@ -0,0 +1,84 @@ +package org.sufficientlysecure.keychain.ui.widget; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.text.Editable; +import android.text.InputType; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.widget.EditText; + +import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthView; + +/** + * Developer: chipset + * Package : org.sufficientlysecure.keychain.layouts + * Project : open-keychain + * Date : 6/3/15 + */ +public class PasswordEditText extends EditText { + + PasswordEditText passwordEditText; + PasswordStrengthView passwordStrengthView; + + public PasswordEditText(Context context) { + super(context); + passwordEditText = this; + this.setInputType(InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_VARIATION_PASSWORD); + this.addTextChangedListener(textWatcher); + } + + public PasswordEditText(Context context, AttributeSet attrs) { + super(context, attrs); + passwordEditText = this; + this.setInputType(InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_VARIATION_PASSWORD); + this.addTextChangedListener(textWatcher); + } + + public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + passwordEditText = this; + this.setInputType(InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_VARIATION_PASSWORD); + this.addTextChangedListener(textWatcher); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + passwordEditText = this; + this.setInputType(InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_VARIATION_PASSWORD); + this.addTextChangedListener(textWatcher); + } + + + TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable editable) { + String passphrase = editable.toString(); + passwordStrengthView.setPassword(passphrase); + } + }; + +// public PasswordStrengthView getPasswordStrengthView() { +// return passwordStrengthView; +// } + + public void setPasswordStrengthView(PasswordStrengthView mPasswordStrengthView) { + this.passwordStrengthView = mPasswordStrengthView; + } +} diff --git a/OpenKeychain/src/main/res/layout/add_user_id_dialog.xml b/OpenKeychain/src/main/res/layout/add_user_id_dialog.xml index 79137bf51..c1b97b02c 100644 --- a/OpenKeychain/src/main/res/layout/add_user_id_dialog.xml +++ b/OpenKeychain/src/main/res/layout/add_user_id_dialog.xml @@ -8,13 +8,12 @@ android:paddingLeft="24dp" android:paddingRight="24dp"> - @@ -43,13 +43,12 @@ android:hint="@string/create_key_hint_full_name" android:ems="10" /> - @@ -65,15 +64,14 @@ android:layout_marginTop="8dp" android:layout_marginBottom="8dp"> - + android:layout_gravity="center_horizontal" /> + custom:color_strong="@color/android_green_light" /> diff --git a/OpenKeychain/src/main/res/layout/passphrase_repeat_dialog.xml b/OpenKeychain/src/main/res/layout/passphrase_repeat_dialog.xml index 09e37ee56..11355bbc0 100644 --- a/OpenKeychain/src/main/res/layout/passphrase_repeat_dialog.xml +++ b/OpenKeychain/src/main/res/layout/passphrase_repeat_dialog.xml @@ -1,5 +1,6 @@ - + android:layout_marginBottom="8dp"> + + + + + + Date: Fri, 6 Mar 2015 11:50:41 +0530 Subject: Asks Passphrase for key delete/export in ViewKeyActivity. --- .../keychain/ui/ViewKeyActivity.java | 112 ++++++++++++++------- 1 file changed, 74 insertions(+), 38 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 0be6c26f6..5a5e1ec36 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -90,6 +90,8 @@ public class ViewKeyActivity extends BaseActivity implements LoaderManager.LoaderCallbacks { static final int REQUEST_QR_FINGERPRINT = 1; + static final int REQUEST_DELETE= 2; + static final int REQUEST_EXPORT= 3; ExportHelper mExportHelper; ProviderHelper mProviderHelper; @@ -296,48 +298,63 @@ public class ViewKeyActivity extends BaseActivity implements @Override public boolean onOptionsItemSelected(MenuItem item) { - try { - switch (item.getItemId()) { - case android.R.id.home: { - Intent homeIntent = new Intent(this, MainActivity.class); - homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(homeIntent); - return true; - } - case R.id.menu_key_view_export_file: { - exportToFile(mDataUri, mExportHelper, mProviderHelper); - return true; - } - case R.id.menu_key_view_delete: { - deleteKey(mDataUri, mExportHelper); - return true; - } - case R.id.menu_key_view_advanced: { - Intent advancedIntent = new Intent(this, ViewKeyAdvActivity.class); - advancedIntent.setData(mDataUri); - startActivity(advancedIntent); - return true; - } - case R.id.menu_key_view_refresh: { - try { - updateFromKeyserver(mDataUri, mProviderHelper); - } catch (ProviderHelper.NotFoundException e) { - Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR); - } - return true; + switch (item.getItemId()) { + case android.R.id.home: { + Intent homeIntent = new Intent(this, MainActivity.class); + homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(homeIntent); + return true; + } + case R.id.menu_key_view_export_file: { + Intent mIntent = new Intent(this,PassphraseDialogActivity.class); + long keyId=0; + try { + keyId = new ProviderHelper(this) + .getCachedPublicKeyRing(mDataUri) + .extractOrGetMasterKeyId(); + } catch (PgpKeyNotFoundException e) { + e.printStackTrace(); } - case R.id.menu_key_view_edit: { - editKey(mDataUri); - return true; + mIntent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID,keyId); + startActivityForResult(mIntent,REQUEST_EXPORT); + return true; + } + case R.id.menu_key_view_delete: { + Intent mIntent = new Intent(this,PassphraseDialogActivity.class); + long keyId=0; + try { + keyId = new ProviderHelper(this) + .getCachedPublicKeyRing(mDataUri) + .extractOrGetMasterKeyId(); + } catch (PgpKeyNotFoundException e) { + e.printStackTrace(); } - case R.id.menu_key_view_certify_fingerprint: { - certifyFingeprint(mDataUri); - return true; + mIntent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID,keyId); + startActivityForResult(mIntent,REQUEST_DELETE); + return true; + } + case R.id.menu_key_view_advanced: { + Intent advancedIntent = new Intent(this, ViewKeyAdvActivity.class); + advancedIntent.setData(mDataUri); + startActivity(advancedIntent); + return true; + } + case R.id.menu_key_view_refresh: { + try { + updateFromKeyserver(mDataUri, mProviderHelper); + } catch (ProviderHelper.NotFoundException e) { + Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR); } + return true; + } + case R.id.menu_key_view_edit: { + editKey(mDataUri); + return true; + } + case R.id.menu_key_view_certify_fingerprint: { + certifyFingeprint(mDataUri); + return true; } - } catch (ProviderHelper.NotFoundException e) { - Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR); - Log.e(Constants.TAG, "Key not found", e); } return super.onOptionsItemSelected(item); } @@ -425,6 +442,12 @@ public class ViewKeyActivity extends BaseActivity implements startActivityForResult(intent, 0); } + @Override + protected void onSaveInstanceState(Bundle outState) { + //Note:-Done due to the same weird crashes as for commitAllowingStateLoss() + //super.onSaveInstanceState(outState); + } + private void showQrCodeDialog() { Intent qrCodeIntent = new Intent(this, QrCodeViewActivity.class); @@ -498,6 +521,19 @@ public class ViewKeyActivity extends BaseActivity implements return; } + if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK){ + deleteKey(mDataUri, mExportHelper); + } + if (requestCode == REQUEST_EXPORT && resultCode == Activity.RESULT_OK){ + try { + exportToFile(mDataUri, mExportHelper, mProviderHelper); + } catch (ProviderHelper.NotFoundException e) { + Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR); + Log.e(Constants.TAG, "Key not found", e); + } + } + + if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); result.createNotify(this).show(); -- cgit v1.2.3 From 7c2fefe2f7b9f6f7d770e37041336ae563518e93 Mon Sep 17 00:00:00 2001 From: chipset95 Date: Fri, 6 Mar 2015 14:47:11 +0530 Subject: Added GPLv3 License --- .../keychain/ui/widget/EmailEditText.java | 17 +++++++++++++++++ .../keychain/ui/widget/PasswordEditText.java | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java index 22845fda0..697f5a61e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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.ui.widget; import android.annotation.TargetApi; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java index dea9e5163..04c48922b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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.ui.widget; import android.annotation.TargetApi; -- cgit v1.2.3 From 30ca8637ff50a78a7f36b82d3deef577f2f1e792 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 8 Mar 2015 01:44:06 +0100 Subject: add support for certification of user attributes --- .../keychain/operations/CertifyOperation.java | 24 +++++--- .../operations/results/OperationResult.java | 4 +- .../keychain/pgp/CanonicalizedSecretKey.java | 72 ++++++++++++++++++++-- .../keychain/service/CertifyActionsParcel.java | 14 ++++- OpenKeychain/src/main/res/values/strings.xml | 7 ++- 5 files changed, 102 insertions(+), 19 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java index 025f45f7f..2e9551826 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java @@ -101,18 +101,26 @@ public class CertifyOperation extends BaseOperation { continue; } - if (action.mUserIds == null) { - log.add(LogType.MSG_CRT_CERTIFY_ALL, 2, - KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId)); - } else { - log.add(LogType.MSG_CRT_CERTIFY_SOME, 2, action.mUserIds.size(), + CanonicalizedPublicKeyRing publicRing = + mProviderHelper.getCanonicalizedPublicKeyRing(action.mMasterKeyId); + + UncachedKeyRing certifiedKey = null; + if (action.mUserIds != null) { + log.add(LogType.MSG_CRT_CERTIFY_UIDS, 2, action.mUserIds.size(), KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId)); + + certifiedKey = certificationKey.certifyUserIds( + publicRing, action.mUserIds, null, null); } - CanonicalizedPublicKeyRing publicRing = - mProviderHelper.getCanonicalizedPublicKeyRing(action.mMasterKeyId); + if (action.mUserAttributes != null) { + log.add(LogType.MSG_CRT_CERTIFY_UATS, 2, action.mUserAttributes.size(), + KeyFormattingUtils.convertKeyIdToHex(action.mMasterKeyId)); + + certifiedKey = certificationKey.certifyUserAttributes( + publicRing, action.mUserAttributes, null, null); + } - UncachedKeyRing certifiedKey = certificationKey.certifyUserIds(publicRing, action.mUserIds, null, null); if (certifiedKey == null) { certifyError += 1; log.add(LogType.MSG_CRT_WARN_CERT_FAILED, 3); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index a96cec8cf..068e314d5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -691,8 +691,8 @@ public abstract class OperationResult implements Parcelable { MSG_PSE_SYMMETRIC (LogLevel.INFO, R.string.msg_pse_symmetric), MSG_CRT_CERTIFYING (LogLevel.DEBUG, R.string.msg_crt_certifying), - MSG_CRT_CERTIFY_ALL (LogLevel.DEBUG, R.string.msg_crt_certify_all), - MSG_CRT_CERTIFY_SOME (LogLevel.DEBUG, R.plurals.msg_crt_certify_some), + MSG_CRT_CERTIFY_UIDS (LogLevel.DEBUG, R.plurals.msg_crt_certify_uids), + MSG_CRT_CERTIFY_UATS (LogLevel.DEBUG, R.plurals.msg_crt_certify_uats), MSG_CRT_ERROR_SELF (LogLevel.ERROR, R.string.msg_crt_error_self), MSG_CRT_ERROR_MASTER_NOT_FOUND (LogLevel.ERROR, R.string.msg_crt_error_master_not_found), MSG_CRT_ERROR_NOTHING (LogLevel.ERROR, R.string.msg_crt_error_nothing), 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 fe5db8c6d..c3fccc789 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java @@ -30,6 +30,7 @@ import org.spongycastle.openpgp.PGPSignature; import org.spongycastle.openpgp.PGPSignatureGenerator; import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator; import org.spongycastle.openpgp.PGPSignatureSubpacketVector; +import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector; import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.PGPContentSignerBuilder; @@ -268,7 +269,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { * Certify the given pubkeyid with the given masterkeyid. * * @param publicKeyRing Keyring to add certification to. - * @param userIds User IDs to certify, or all if null + * @param userIds User IDs to certify * @return A keyring with added certifications */ public UncachedKeyRing certifyUserIds(CanonicalizedPublicKeyRing publicKeyRing, List userIds, @@ -313,10 +314,8 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { PGPPublicKey publicKey = publicKeyRing.getPublicKey().getPublicKey(); // fetch public key ring, add the certification and return it - Iterable it = userIds != null ? userIds - : new IterableIterator(publicKey.getUserIDs()); try { - for (String userId : it) { + for (String userId : userIds) { PGPSignature sig = signatureGenerator.generateCertification(userId, publicKey); publicKey = PGPPublicKey.addCertification(publicKey, userId, sig); } @@ -330,6 +329,71 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey { return new UncachedKeyRing(ring); } + /** + * Certify the given user attributes with the given masterkeyid. + * + * @param publicKeyRing Keyring to add certification to. + * @param userAttributes User IDs to certify, or all if null + * @return A keyring with added certifications + */ + public UncachedKeyRing certifyUserAttributes(CanonicalizedPublicKeyRing publicKeyRing, + List userAttributes, byte[] nfcSignedHash, Date nfcCreationTimestamp) { + if (mPrivateKeyState == PRIVATE_KEY_STATE_LOCKED) { + throw new PrivateKeyNotUnlockedException(); + } + if (!isMasterKey()) { + throw new AssertionError("tried to certify with non-master key, this is a programming error!"); + } + if (publicKeyRing.getMasterKeyId() == getKeyId()) { + throw new AssertionError("key tried to self-certify, this is a programming error!"); + } + + // create a signatureGenerator from the supplied masterKeyId and passphrase + PGPSignatureGenerator signatureGenerator; + { + // TODO: SHA256 fixed? + PGPContentSignerBuilder contentSignerBuilder = getContentSignerBuilder(PGPUtil.SHA256, + nfcSignedHash, nfcCreationTimestamp); + + signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder); + try { + signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, mPrivateKey); + } catch (PGPException e) { + Log.e(Constants.TAG, "signing error", e); + return null; + } + } + + { // supply signatureGenerator with a SubpacketVector + PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); + if (nfcCreationTimestamp != null) { + spGen.setSignatureCreationTime(false, nfcCreationTimestamp); + Log.d(Constants.TAG, "For NFC: set sig creation time to " + nfcCreationTimestamp); + } + PGPSignatureSubpacketVector packetVector = spGen.generate(); + signatureGenerator.setHashedSubpackets(packetVector); + } + + // get the master subkey (which we certify for) + PGPPublicKey publicKey = publicKeyRing.getPublicKey().getPublicKey(); + + // fetch public key ring, add the certification and return it + try { + for (WrappedUserAttribute userAttribute : userAttributes) { + PGPUserAttributeSubpacketVector vector = userAttribute.getVector(); + PGPSignature sig = signatureGenerator.generateCertification(vector, publicKey); + publicKey = PGPPublicKey.addCertification(publicKey, vector, sig); + } + } catch (PGPException e) { + Log.e(Constants.TAG, "signing error", e); + return null; + } + + PGPPublicKeyRing ring = PGPPublicKeyRing.insertPublicKey(publicKeyRing.getRing(), publicKey); + + return new UncachedKeyRing(ring); + } + static class PrivateKeyNotUnlockedException extends RuntimeException { // this exception is a programming error which happens when an operation which requires // the private key is called without a previous call to unlock() diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java index f0dbf0820..f4b941109 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/CertifyActionsParcel.java @@ -24,6 +24,9 @@ import android.os.Parcelable; import java.io.Serializable; import java.util.ArrayList; +import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; + + /** * This class is a a transferable representation for a number of keyrings to * be certified. @@ -76,14 +79,19 @@ public class CertifyActionsParcel implements Parcelable { final public long mMasterKeyId; final public ArrayList mUserIds; + final public ArrayList mUserAttributes; - public CertifyAction(long masterKeyId) { - this(masterKeyId, null); + public CertifyAction(long masterKeyId, ArrayList userIds) { + mMasterKeyId = masterKeyId; + mUserIds = userIds; + mUserAttributes = null; } - public CertifyAction(long masterKeyId, ArrayList userIds) { + public CertifyAction(long masterKeyId, ArrayList userIds, + ArrayList attributes) { mMasterKeyId = masterKeyId; mUserIds = userIds; + mUserAttributes = attributes; } } diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index d9460882c..051383a36 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -1071,11 +1071,14 @@ "Preparing symmetric encryption" "Generating certifications" - "Certifying all user IDs for key %s" - + "Certifying one user ID for key %2$s" "Certifying %1$d user IDs for key %2$s" + + "Certifying one user attribute for key %2$s" + "Certifying %1$d user attributes for key %2$s" + "Cannot issue self-certificate like this!" "Master key not found!" "No keys certified!" -- cgit v1.2.3 From 4f11fb5a2f08ecf5fb81c86d590d04387cd1cd9a Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 8 Mar 2015 01:44:25 +0100 Subject: unit test certification of user attributes --- .../keychain/operations/CertifyOperationTest.java | 60 +++++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java index c05f4a029..0af87ada4 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java @@ -38,6 +38,7 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyOperation; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing.IteratorWithIOThrow; import org.sufficientlysecure.keychain.pgp.WrappedSignature; +import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.CertifyActionsParcel; @@ -54,14 +55,15 @@ import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.io.PrintStream; import java.security.Security; +import java.util.ArrayList; import java.util.Iterator; +import java.util.Random; + @RunWith(RobolectricTestRunner.class) @org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19 public class CertifyOperationTest { - static String mPassphrase = TestingUtils.genPassphrase(true); - static UncachedKeyRing mStaticRing1, mStaticRing2; static String mKeyPhrase1 = TestingUtils.genPassphrase(true); static String mKeyPhrase2 = TestingUtils.genPassphrase(true); @@ -74,6 +76,8 @@ public class CertifyOperationTest { oldShadowStream = ShadowLog.stream; // ShadowLog.stream = System.out; + Random random = new Random(); + PgpKeyOperation op = new PgpKeyOperation(null); { @@ -102,8 +106,14 @@ public class CertifyOperationTest { Algorithm.DSA, 1024, null, KeyFlags.SIGN_DATA, 0L)); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L)); + parcel.mAddUserIds.add("ditz"); - parcel.mNewUnlock = new ChangeUnlockParcel(null, "1234"); + byte[] uatdata = new byte[random.nextInt(150)+10]; + random.nextBytes(uatdata); + parcel.mAddUserAttribute.add( + WrappedUserAttribute.fromSubpacket(random.nextInt(100)+1, uatdata)); + + parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase2); PgpEditKeyResult result = op.createSecretKeyRing(parcel); Assert.assertTrue("initial test key creation must succeed", result.success()); @@ -140,7 +150,7 @@ public class CertifyOperationTest { } @Test - public void testCertify() throws Exception { + public void testCertifyId() throws Exception { CertifyOperation op = operationWithFakePassphraseCache( mStaticRing1.getMasterKeyId(), mStaticRing1.getMasterKeyId(), mKeyPhrase1); @@ -152,7 +162,8 @@ public class CertifyOperationTest { } CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId()); - actions.add(new CertifyAction(mStaticRing2.getMasterKeyId())); + actions.add(new CertifyAction(mStaticRing2.getMasterKeyId(), + mStaticRing2.getPublicKey().getUnorderedUserIds())); CertifyResult result = op.certify(actions, null); Assert.assertTrue("certification must succeed", result.success()); @@ -166,13 +177,43 @@ public class CertifyOperationTest { } + @Test + public void testCertifyAttribute() throws Exception { + CertifyOperation op = operationWithFakePassphraseCache( + mStaticRing1.getMasterKeyId(), mStaticRing1.getMasterKeyId(), mKeyPhrase1); + + { + CanonicalizedPublicKeyRing ring = new ProviderHelper(Robolectric.application) + .getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId()); + Assert.assertEquals("public key must not be marked verified prior to certification", + Certs.UNVERIFIED, ring.getVerified()); + } + + CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId()); + actions.add(new CertifyAction(mStaticRing2.getMasterKeyId(), null, + mStaticRing2.getPublicKey().getUnorderedUserAttributes())); + CertifyResult result = op.certify(actions, null); + + Assert.assertTrue("certification must succeed", result.success()); + + { + CanonicalizedPublicKeyRing ring = new ProviderHelper(Robolectric.application) + .getCanonicalizedPublicKeyRing(mStaticRing2.getMasterKeyId()); + Assert.assertEquals("new key must be verified now", + Certs.VERIFIED_SECRET, ring.getVerified()); + } + + } + + @Test public void testCertifySelf() throws Exception { CertifyOperation op = operationWithFakePassphraseCache( mStaticRing1.getMasterKeyId(), mStaticRing1.getMasterKeyId(), mKeyPhrase1); CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId()); - actions.add(new CertifyAction(mStaticRing1.getMasterKeyId())); + actions.add(new CertifyAction(mStaticRing1.getMasterKeyId(), + mStaticRing2.getPublicKey().getUnorderedUserIds())); CertifyResult result = op.certify(actions, null); @@ -188,7 +229,9 @@ public class CertifyOperationTest { { CertifyActionsParcel actions = new CertifyActionsParcel(mStaticRing1.getMasterKeyId()); - actions.add(new CertifyAction(1234L)); + ArrayList uids = new ArrayList(); + uids.add("nonexistent"); + actions.add(new CertifyAction(1234L, uids)); CertifyResult result = op.certify(actions, null); @@ -199,7 +242,8 @@ public class CertifyOperationTest { { CertifyActionsParcel actions = new CertifyActionsParcel(1234L); - actions.add(new CertifyAction(mStaticRing1.getMasterKeyId())); + actions.add(new CertifyAction(mStaticRing1.getMasterKeyId(), + mStaticRing2.getPublicKey().getUnorderedUserIds())); CertifyResult result = op.certify(actions, null); -- cgit v1.2.3