Merge branch 'master' into encrypted-export
This commit is contained in:
@@ -242,7 +242,7 @@ android {
|
|||||||
|
|
||||||
// apply plugin: 'spoon'
|
// apply plugin: 'spoon'
|
||||||
|
|
||||||
task jacocoTestReport(type:JacocoReport) {
|
task jacocoTestReport(type:JacocoReport, dependsOn: "testDebugUnitTest") {
|
||||||
group = "Reporting"
|
group = "Reporting"
|
||||||
description = "Generate Jacoco coverage reports"
|
description = "Generate Jacoco coverage reports"
|
||||||
|
|
||||||
@@ -252,7 +252,9 @@ task jacocoTestReport(type:JacocoReport) {
|
|||||||
'**/R$*.class',
|
'**/R$*.class',
|
||||||
'**/*$ViewInjector*.*',
|
'**/*$ViewInjector*.*',
|
||||||
'**/BuildConfig.*',
|
'**/BuildConfig.*',
|
||||||
'**/Manifest*.*']
|
'**/Manifest*.*',
|
||||||
|
'**/*Activity*.*',
|
||||||
|
'**/*Fragment*.*']
|
||||||
)
|
)
|
||||||
|
|
||||||
sourceDirectories = files("${buildDir.parent}/src/main/java")
|
sourceDirectories = files("${buildDir.parent}/src/main/java")
|
||||||
@@ -260,10 +262,7 @@ task jacocoTestReport(type:JacocoReport) {
|
|||||||
"${buildDir}/generated/source/buildConfig/debug",
|
"${buildDir}/generated/source/buildConfig/debug",
|
||||||
"${buildDir}/generated/source/r/debug"
|
"${buildDir}/generated/source/r/debug"
|
||||||
])
|
])
|
||||||
executionData = files([
|
executionData = fileTree(dir: "${buildDir}/jacoco", include: "**/*.exec")
|
||||||
"${buildDir}/jacoco/testDebug.exec",
|
|
||||||
"${buildDir}/outputs/code-coverage/connected/coverage.ec"
|
|
||||||
])
|
|
||||||
|
|
||||||
reports {
|
reports {
|
||||||
xml.enabled = true
|
xml.enabled = true
|
||||||
|
|||||||
@@ -151,7 +151,6 @@ public class KeybaseVerificationOperation extends BaseOperation<KeybaseVerificat
|
|||||||
PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(mContext, mProviderHelper, mProgressable);
|
PgpDecryptVerifyOperation op = new PgpDecryptVerifyOperation(mContext, mProviderHelper, mProgressable);
|
||||||
|
|
||||||
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(messageBytes)
|
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(messageBytes)
|
||||||
.setSignedLiteralData(true)
|
|
||||||
.setRequiredSignerFingerprint(requiredFingerprint);
|
.setRequiredSignerFingerprint(requiredFingerprint);
|
||||||
|
|
||||||
DecryptVerifyResult decryptVerifyResult = op.execute(input, new CryptoInputParcel());
|
DecryptVerifyResult decryptVerifyResult = op.execute(input, new CryptoInputParcel());
|
||||||
|
|||||||
@@ -514,7 +514,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_CR_ERROR_NO_USER_ID (LogLevel.ERROR, R.string.msg_cr_error_no_user_id),
|
MSG_CR_ERROR_NO_USER_ID (LogLevel.ERROR, R.string.msg_cr_error_no_user_id),
|
||||||
MSG_CR_ERROR_NO_CERTIFY (LogLevel.ERROR, R.string.msg_cr_error_no_certify),
|
MSG_CR_ERROR_NO_CERTIFY (LogLevel.ERROR, R.string.msg_cr_error_no_certify),
|
||||||
MSG_CR_ERROR_NULL_EXPIRY(LogLevel.ERROR, R.string.msg_cr_error_null_expiry),
|
MSG_CR_ERROR_NULL_EXPIRY(LogLevel.ERROR, R.string.msg_cr_error_null_expiry),
|
||||||
MSG_CR_ERROR_KEYSIZE_512 (LogLevel.ERROR, R.string.msg_cr_error_keysize_512),
|
MSG_CR_ERROR_KEYSIZE_2048(LogLevel.ERROR, R.string.msg_cr_error_keysize_2048),
|
||||||
MSG_CR_ERROR_NO_KEYSIZE (LogLevel.ERROR, R.string.msg_cr_error_no_keysize),
|
MSG_CR_ERROR_NO_KEYSIZE (LogLevel.ERROR, R.string.msg_cr_error_no_keysize),
|
||||||
MSG_CR_ERROR_NO_CURVE (LogLevel.ERROR, R.string.msg_cr_error_no_curve),
|
MSG_CR_ERROR_NO_CURVE (LogLevel.ERROR, R.string.msg_cr_error_no_curve),
|
||||||
MSG_CR_ERROR_UNKNOWN_ALGO (LogLevel.ERROR, R.string.msg_cr_error_unknown_algo),
|
MSG_CR_ERROR_UNKNOWN_ALGO (LogLevel.ERROR, R.string.msg_cr_error_unknown_algo),
|
||||||
@@ -661,6 +661,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_DC_ERROR_INPUT (LogLevel.ERROR, R.string.msg_dc_error_input),
|
MSG_DC_ERROR_INPUT (LogLevel.ERROR, R.string.msg_dc_error_input),
|
||||||
MSG_DC_ERROR_NO_DATA (LogLevel.ERROR, R.string.msg_dc_error_no_data),
|
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_NO_KEY (LogLevel.ERROR, R.string.msg_dc_error_no_key),
|
||||||
|
MSG_DC_ERROR_NO_SIGNATURE (LogLevel.ERROR, R.string.msg_dc_error_no_signature),
|
||||||
MSG_DC_ERROR_PGP_EXCEPTION (LogLevel.ERROR, R.string.msg_dc_error_pgp_exception),
|
MSG_DC_ERROR_PGP_EXCEPTION (LogLevel.ERROR, R.string.msg_dc_error_pgp_exception),
|
||||||
MSG_DC_INTEGRITY_CHECK_OK (LogLevel.INFO, R.string.msg_dc_integrity_check_ok),
|
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_META_ONLY (LogLevel.OK, R.string.msg_dc_ok_meta_only),
|
||||||
@@ -687,6 +688,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_VL_ERROR_MISSING_SIGLIST (LogLevel.ERROR, R.string.msg_vl_error_no_siglist),
|
MSG_VL_ERROR_MISSING_SIGLIST (LogLevel.ERROR, R.string.msg_vl_error_no_siglist),
|
||||||
MSG_VL_ERROR_MISSING_LITERAL (LogLevel.ERROR, R.string.msg_vl_error_missing_literal),
|
MSG_VL_ERROR_MISSING_LITERAL (LogLevel.ERROR, R.string.msg_vl_error_missing_literal),
|
||||||
MSG_VL_ERROR_MISSING_KEY (LogLevel.ERROR, R.string.msg_vl_error_wrong_key),
|
MSG_VL_ERROR_MISSING_KEY (LogLevel.ERROR, R.string.msg_vl_error_wrong_key),
|
||||||
|
MSG_VL_ERROR_NO_SIGNATURE (LogLevel.ERROR, R.string.msg_vl_error_no_signature),
|
||||||
MSG_VL_CLEAR_SIGNATURE_CHECK (LogLevel.DEBUG, R.string.msg_vl_clear_signature_check),
|
MSG_VL_CLEAR_SIGNATURE_CHECK (LogLevel.DEBUG, R.string.msg_vl_clear_signature_check),
|
||||||
MSG_VL_ERROR_INTEGRITY_CHECK (LogLevel.ERROR, R.string.msg_vl_error_integrity_check),
|
MSG_VL_ERROR_INTEGRITY_CHECK (LogLevel.ERROR, R.string.msg_vl_error_integrity_check),
|
||||||
MSG_VL_OK (LogLevel.OK, R.string.msg_vl_ok),
|
MSG_VL_OK (LogLevel.OK, R.string.msg_vl_ok),
|
||||||
@@ -703,7 +705,6 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
|
|
||||||
// pgpsignencrypt
|
// pgpsignencrypt
|
||||||
MSG_PSE_ASYMMETRIC (LogLevel.INFO, R.string.msg_pse_asymmetric),
|
MSG_PSE_ASYMMETRIC (LogLevel.INFO, R.string.msg_pse_asymmetric),
|
||||||
MSG_PSE_CLEARSIGN_ONLY (LogLevel.DEBUG, R.string.msg_pse_clearsign_only),
|
|
||||||
MSG_PSE_COMPRESSING (LogLevel.DEBUG, R.string.msg_pse_compressing),
|
MSG_PSE_COMPRESSING (LogLevel.DEBUG, R.string.msg_pse_compressing),
|
||||||
MSG_PSE_ENCRYPTING (LogLevel.DEBUG, R.string.msg_pse_encrypting),
|
MSG_PSE_ENCRYPTING (LogLevel.DEBUG, R.string.msg_pse_encrypting),
|
||||||
MSG_PSE_ERROR_BAD_PASSPHRASE (LogLevel.ERROR, R.string.msg_pse_error_bad_passphrase),
|
MSG_PSE_ERROR_BAD_PASSPHRASE (LogLevel.ERROR, R.string.msg_pse_error_bad_passphrase),
|
||||||
|
|||||||
@@ -154,8 +154,13 @@ public abstract class CanonicalizedKeyRing extends KeyRing {
|
|||||||
return getRing().getEncoded();
|
return getRing().getEncoded();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsSubkey(String expectedFingerprint) {
|
/// Returns true iff the keyring contains a primary key or mutually bound subkey with the expected fingerprint
|
||||||
|
public boolean containsBoundSubkey(String expectedFingerprint) {
|
||||||
for (CanonicalizedPublicKey key : publicKeyIterator()) {
|
for (CanonicalizedPublicKey key : publicKeyIterator()) {
|
||||||
|
boolean isMasterOrMutuallyBound = key.isMasterKey() || key.canSign();
|
||||||
|
if (!isMasterOrMutuallyBound) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (KeyFormattingUtils.convertFingerprintToHex(
|
if (KeyFormattingUtils.convertFingerprintToHex(
|
||||||
key.getFingerprint()).equalsIgnoreCase(expectedFingerprint)) {
|
key.getFingerprint()).equalsIgnoreCase(expectedFingerprint)) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -44,13 +44,17 @@ import java.util.Iterator;
|
|||||||
public class CanonicalizedPublicKey extends UncachedPublicKey {
|
public class CanonicalizedPublicKey extends UncachedPublicKey {
|
||||||
|
|
||||||
// this is the parent key ring
|
// this is the parent key ring
|
||||||
final KeyRing mRing;
|
final CanonicalizedKeyRing mRing;
|
||||||
|
|
||||||
CanonicalizedPublicKey(KeyRing ring, PGPPublicKey key) {
|
CanonicalizedPublicKey(CanonicalizedKeyRing ring, PGPPublicKey key) {
|
||||||
super(key);
|
super(key);
|
||||||
mRing = ring;
|
mRing = ring;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CanonicalizedKeyRing getKeyRing() {
|
||||||
|
return mRing;
|
||||||
|
}
|
||||||
|
|
||||||
public IterableIterator<String> getUserIds() {
|
public IterableIterator<String> getUserIds() {
|
||||||
return new IterableIterator<String>(mPublicKey.getUserIDs());
|
return new IterableIterator<String>(mPublicKey.getUserIDs());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,11 +91,12 @@ public class OpenPgpSignatureResultBuilder {
|
|||||||
return mInsecure;
|
return mInsecure;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initValid(CanonicalizedPublicKeyRing signingRing,
|
public void initValid(CanonicalizedPublicKey signingKey) {
|
||||||
CanonicalizedPublicKey signingKey) {
|
|
||||||
setSignatureAvailable(true);
|
setSignatureAvailable(true);
|
||||||
setKnownKey(true);
|
setKnownKey(true);
|
||||||
|
|
||||||
|
CanonicalizedKeyRing signingRing = signingKey.getKeyRing();
|
||||||
|
|
||||||
// from RING
|
// from RING
|
||||||
setKeyId(signingRing.getMasterKeyId());
|
setKeyId(signingRing.getMasterKeyId());
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -36,7 +36,6 @@ public class PgpDecryptVerifyInputParcel implements Parcelable {
|
|||||||
private boolean mDecryptMetadataOnly;
|
private boolean mDecryptMetadataOnly;
|
||||||
private byte[] mDetachedSignature;
|
private byte[] mDetachedSignature;
|
||||||
private String mRequiredSignerFingerprint;
|
private String mRequiredSignerFingerprint;
|
||||||
private boolean mSignedLiteralData;
|
|
||||||
|
|
||||||
public PgpDecryptVerifyInputParcel() {
|
public PgpDecryptVerifyInputParcel() {
|
||||||
}
|
}
|
||||||
@@ -61,7 +60,6 @@ public class PgpDecryptVerifyInputParcel implements Parcelable {
|
|||||||
mDecryptMetadataOnly = source.readInt() != 0;
|
mDecryptMetadataOnly = source.readInt() != 0;
|
||||||
mDetachedSignature = source.createByteArray();
|
mDetachedSignature = source.createByteArray();
|
||||||
mRequiredSignerFingerprint = source.readString();
|
mRequiredSignerFingerprint = source.readString();
|
||||||
mSignedLiteralData = source.readInt() != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -80,7 +78,6 @@ public class PgpDecryptVerifyInputParcel implements Parcelable {
|
|||||||
dest.writeInt(mDecryptMetadataOnly ? 1 : 0);
|
dest.writeInt(mDecryptMetadataOnly ? 1 : 0);
|
||||||
dest.writeByteArray(mDetachedSignature);
|
dest.writeByteArray(mDetachedSignature);
|
||||||
dest.writeString(mRequiredSignerFingerprint);
|
dest.writeString(mRequiredSignerFingerprint);
|
||||||
dest.writeInt(mSignedLiteralData ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] getInputBytes() {
|
byte[] getInputBytes() {
|
||||||
@@ -150,15 +147,6 @@ public class PgpDecryptVerifyInputParcel implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isSignedLiteralData() {
|
|
||||||
return mSignedLiteralData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PgpDecryptVerifyInputParcel setSignedLiteralData(boolean signedLiteralData) {
|
|
||||||
mSignedLiteralData = signedLiteralData;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Creator<PgpDecryptVerifyInputParcel> CREATOR = new Creator<PgpDecryptVerifyInputParcel>() {
|
public static final Creator<PgpDecryptVerifyInputParcel> CREATOR = new Creator<PgpDecryptVerifyInputParcel>() {
|
||||||
public PgpDecryptVerifyInputParcel createFromParcel(final Parcel source) {
|
public PgpDecryptVerifyInputParcel createFromParcel(final Parcel source) {
|
||||||
return new PgpDecryptVerifyInputParcel(source);
|
return new PgpDecryptVerifyInputParcel(source);
|
||||||
|
|||||||
@@ -18,13 +18,23 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
|
|
||||||
import org.openintents.openpgp.OpenPgpDecryptionResult;
|
import org.openintents.openpgp.OpenPgpDecryptionResult;
|
||||||
import org.openintents.openpgp.OpenPgpMetadata;
|
import org.openintents.openpgp.OpenPgpMetadata;
|
||||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
|
||||||
import org.spongycastle.bcpg.ArmoredInputStream;
|
import org.spongycastle.bcpg.ArmoredInputStream;
|
||||||
import org.spongycastle.openpgp.PGPCompressedData;
|
import org.spongycastle.openpgp.PGPCompressedData;
|
||||||
import org.spongycastle.openpgp.PGPDataValidationException;
|
import org.spongycastle.openpgp.PGPDataValidationException;
|
||||||
@@ -33,18 +43,14 @@ import org.spongycastle.openpgp.PGPEncryptedDataList;
|
|||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPKeyValidationException;
|
import org.spongycastle.openpgp.PGPKeyValidationException;
|
||||||
import org.spongycastle.openpgp.PGPLiteralData;
|
import org.spongycastle.openpgp.PGPLiteralData;
|
||||||
import org.spongycastle.openpgp.PGPOnePassSignature;
|
|
||||||
import org.spongycastle.openpgp.PGPOnePassSignatureList;
|
|
||||||
import org.spongycastle.openpgp.PGPPBEEncryptedData;
|
import org.spongycastle.openpgp.PGPPBEEncryptedData;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyEncryptedData;
|
import org.spongycastle.openpgp.PGPPublicKeyEncryptedData;
|
||||||
import org.spongycastle.openpgp.PGPSignature;
|
|
||||||
import org.spongycastle.openpgp.PGPSignatureList;
|
import org.spongycastle.openpgp.PGPSignatureList;
|
||||||
import org.spongycastle.openpgp.PGPUtil;
|
import org.spongycastle.openpgp.PGPUtil;
|
||||||
import org.spongycastle.openpgp.jcajce.JcaPGPObjectFactory;
|
import org.spongycastle.openpgp.jcajce.JcaPGPObjectFactory;
|
||||||
import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
|
import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
|
||||||
import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
|
import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.CachingDataDecryptorFactory;
|
import org.spongycastle.openpgp.operator.jcajce.CachingDataDecryptorFactory;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder;
|
||||||
import org.spongycastle.util.encoders.DecoderException;
|
import org.spongycastle.util.encoders.DecoderException;
|
||||||
@@ -68,17 +74,6 @@ import org.sufficientlysecure.keychain.util.Log;
|
|||||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.security.SignatureException;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInputParcel> {
|
public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInputParcel> {
|
||||||
|
|
||||||
public PgpDecryptVerifyOperation(Context context, ProviderHelper providerHelper, Progressable progressable) {
|
public PgpDecryptVerifyOperation(Context context, ProviderHelper providerHelper, Progressable progressable) {
|
||||||
@@ -153,9 +148,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
// it is ascii armored
|
// it is ascii armored
|
||||||
Log.d(Constants.TAG, "ASCII Armor Header Line: " + aIn.getArmorHeaderLine());
|
Log.d(Constants.TAG, "ASCII Armor Header Line: " + aIn.getArmorHeaderLine());
|
||||||
|
|
||||||
if (input.isSignedLiteralData()) {
|
if (aIn.isClearText()) {
|
||||||
return verifySignedLiteralData(input, aIn, outputStream, 0);
|
|
||||||
} else if (aIn.isClearText()) {
|
|
||||||
// a cleartext signature, verify it with the other method
|
// a cleartext signature, verify it with the other method
|
||||||
return verifyCleartextSignature(aIn, outputStream, 0);
|
return verifyCleartextSignature(aIn, outputStream, 0);
|
||||||
} else {
|
} else {
|
||||||
@@ -186,133 +179,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Verify signed plaintext data (PGP/INLINE). */
|
|
||||||
@NonNull
|
|
||||||
private DecryptVerifyResult verifySignedLiteralData(
|
|
||||||
PgpDecryptVerifyInputParcel input, InputStream in, OutputStream out, int indent)
|
|
||||||
throws IOException, PGPException {
|
|
||||||
OperationLog log = new OperationLog();
|
|
||||||
log.add(LogType.MSG_VL, indent);
|
|
||||||
|
|
||||||
// thinking that the proof-fetching operation is going to take most of the time
|
|
||||||
updateProgress(R.string.progress_reading_data, 75, 100);
|
|
||||||
|
|
||||||
JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);
|
|
||||||
Object o = pgpF.nextObject();
|
|
||||||
if (o instanceof PGPCompressedData) {
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_DECOMPRESS, indent + 1);
|
|
||||||
|
|
||||||
pgpF = new JcaPGPObjectFactory(((PGPCompressedData) o).getDataStream());
|
|
||||||
o = pgpF.nextObject();
|
|
||||||
updateProgress(R.string.progress_decompressing_data, 80, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
// all we want to see is a OnePassSignatureList followed by LiteralData
|
|
||||||
if (!(o instanceof PGPOnePassSignatureList)) {
|
|
||||||
log.add(LogType.MSG_VL_ERROR_MISSING_SIGLIST, indent);
|
|
||||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
|
||||||
}
|
|
||||||
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) o;
|
|
||||||
|
|
||||||
// go through all signatures (should be just one), make sure we have
|
|
||||||
// the key and it matches the one we’re looking for
|
|
||||||
CanonicalizedPublicKeyRing signingRing = null;
|
|
||||||
CanonicalizedPublicKey signingKey = null;
|
|
||||||
int signatureIndex = -1;
|
|
||||||
for (int i = 0; i < sigList.size(); ++i) {
|
|
||||||
try {
|
|
||||||
long sigKeyId = sigList.get(i).getKeyID();
|
|
||||||
signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
|
|
||||||
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
|
|
||||||
);
|
|
||||||
signingKey = signingRing.getPublicKey(sigKeyId);
|
|
||||||
signatureIndex = i;
|
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
|
||||||
Log.d(Constants.TAG, "key not found, trying next signature...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// there has to be a key, and it has to be the right one
|
|
||||||
if (signingKey == null) {
|
|
||||||
log.add(LogType.MSG_VL_ERROR_MISSING_KEY, indent);
|
|
||||||
Log.d(Constants.TAG, "Failed to find key in signed-literal message");
|
|
||||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
|
||||||
}
|
|
||||||
|
|
||||||
String fingerprint = KeyFormattingUtils.convertFingerprintToHex(signingRing.getFingerprint());
|
|
||||||
if (!(input.getRequiredSignerFingerprint().equals(fingerprint))) {
|
|
||||||
log.add(LogType.MSG_VL_ERROR_MISSING_KEY, indent);
|
|
||||||
Log.d(Constants.TAG, "Fingerprint mismatch; wanted " + input.getRequiredSignerFingerprint() +
|
|
||||||
" got " + fingerprint + "!");
|
|
||||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
|
||||||
|
|
||||||
PGPOnePassSignature signature = sigList.get(signatureIndex);
|
|
||||||
signatureResultBuilder.initValid(signingRing, signingKey);
|
|
||||||
|
|
||||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
|
||||||
new JcaPGPContentVerifierBuilderProvider()
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
|
||||||
signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
|
|
||||||
|
|
||||||
o = pgpF.nextObject();
|
|
||||||
|
|
||||||
if (!(o instanceof PGPLiteralData)) {
|
|
||||||
log.add(LogType.MSG_VL_ERROR_MISSING_LITERAL, indent);
|
|
||||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
|
||||||
}
|
|
||||||
|
|
||||||
PGPLiteralData literalData = (PGPLiteralData) o;
|
|
||||||
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_DATA, indent + 1);
|
|
||||||
updateProgress(R.string.progress_decrypting, 85, 100);
|
|
||||||
|
|
||||||
InputStream dataIn = literalData.getInputStream();
|
|
||||||
|
|
||||||
int length;
|
|
||||||
byte[] buffer = new byte[1 << 16];
|
|
||||||
while ((length = dataIn.read(buffer)) > 0) {
|
|
||||||
out.write(buffer, 0, length);
|
|
||||||
signature.update(buffer, 0, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProgress(R.string.progress_verifying_signature, 95, 100);
|
|
||||||
log.add(LogType.MSG_VL_CLEAR_SIGNATURE_CHECK, indent + 1);
|
|
||||||
|
|
||||||
PGPSignatureList signatureList = (PGPSignatureList) pgpF.nextObject();
|
|
||||||
PGPSignature messageSignature = signatureList.get(signatureIndex);
|
|
||||||
|
|
||||||
// Verify signature and check binding signatures
|
|
||||||
boolean validSignature = signature.verify(messageSignature);
|
|
||||||
if (validSignature) {
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
|
|
||||||
} else {
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
|
|
||||||
}
|
|
||||||
signatureResultBuilder.setValidSignature(validSignature);
|
|
||||||
|
|
||||||
OpenPgpSignatureResult signatureResult = signatureResultBuilder.build();
|
|
||||||
|
|
||||||
if (signatureResult.getResult() != OpenPgpSignatureResult.RESULT_VALID_CONFIRMED
|
|
||||||
&& signatureResult.getResult() != OpenPgpSignatureResult.RESULT_VALID_UNCONFIRMED) {
|
|
||||||
log.add(LogType.MSG_VL_ERROR_INTEGRITY_CHECK, indent);
|
|
||||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProgress(R.string.progress_done, 100, 100);
|
|
||||||
|
|
||||||
log.add(LogType.MSG_VL_OK, indent);
|
|
||||||
|
|
||||||
// Return a positive result, with metadata and verification info
|
|
||||||
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
|
||||||
result.setSignatureResult(signatureResult);
|
|
||||||
result.setDecryptionResult(
|
|
||||||
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class EncryptStreamResult {
|
private static class EncryptStreamResult {
|
||||||
|
|
||||||
// this is non-null iff an error occured, return directly
|
// this is non-null iff an error occured, return directly
|
||||||
@@ -368,7 +234,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
|
||||||
OpenPgpDecryptionResultBuilder decryptionResultBuilder = new OpenPgpDecryptionResultBuilder();
|
OpenPgpDecryptionResultBuilder decryptionResultBuilder = new OpenPgpDecryptionResultBuilder();
|
||||||
|
|
||||||
JcaPGPObjectFactory plainFact;
|
JcaPGPObjectFactory plainFact;
|
||||||
@@ -415,10 +280,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
|
|
||||||
log.add(LogType.MSG_DC_PREP_STREAMS, indent);
|
log.add(LogType.MSG_DC_PREP_STREAMS, indent);
|
||||||
|
|
||||||
int signatureIndex = -1;
|
|
||||||
CanonicalizedPublicKeyRing signingRing = null;
|
|
||||||
CanonicalizedPublicKey signingKey = null;
|
|
||||||
|
|
||||||
log.add(LogType.MSG_DC_CLEAR, indent);
|
log.add(LogType.MSG_DC_CLEAR, indent);
|
||||||
indent += 1;
|
indent += 1;
|
||||||
|
|
||||||
@@ -435,58 +296,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
plainFact = fact;
|
plainFact = fact;
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve leading signature data
|
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper);
|
||||||
PGPOnePassSignature signature = null;
|
if (signatureChecker.initializeOnePassSignature(dataChunk, log, indent +1)) {
|
||||||
if (dataChunk instanceof PGPOnePassSignatureList) {
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE, indent + 1);
|
|
||||||
currentProgress += 2;
|
|
||||||
updateProgress(R.string.progress_processing_signature, currentProgress, 100);
|
|
||||||
|
|
||||||
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk;
|
|
||||||
|
|
||||||
// NOTE: following code is similar to processSignature, but for PGPOnePassSignature
|
|
||||||
|
|
||||||
// go through all signatures
|
|
||||||
// and find out for which signature we have a key in our database
|
|
||||||
for (int i = 0; i < sigList.size(); ++i) {
|
|
||||||
try {
|
|
||||||
long sigKeyId = sigList.get(i).getKeyID();
|
|
||||||
signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
|
|
||||||
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
|
|
||||||
);
|
|
||||||
signingKey = signingRing.getPublicKey(sigKeyId);
|
|
||||||
signatureIndex = i;
|
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
|
||||||
Log.d(Constants.TAG, "key not found, trying next signature...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signingKey != null) {
|
|
||||||
// key found in our database!
|
|
||||||
signature = sigList.get(signatureIndex);
|
|
||||||
|
|
||||||
signatureResultBuilder.initValid(signingRing, signingKey);
|
|
||||||
|
|
||||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
|
||||||
new JcaPGPContentVerifierBuilderProvider()
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
|
||||||
signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
|
|
||||||
} else {
|
|
||||||
// no key in our database -> return "unknown pub key" status including the first key id
|
|
||||||
if (!sigList.isEmpty()) {
|
|
||||||
signatureResultBuilder.setSignatureAvailable(true);
|
|
||||||
signatureResultBuilder.setKnownKey(false);
|
|
||||||
signatureResultBuilder.setKeyId(sigList.get(0).getKeyID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for insecure signing key
|
|
||||||
// TODO: checks on signingRing ?
|
|
||||||
if (signingKey != null && ! PgpSecurityConstants.isSecureKey(signingKey)) {
|
|
||||||
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
|
|
||||||
signatureResultBuilder.setInsecure(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
dataChunk = plainFact.nextObject();
|
dataChunk = plainFact.nextObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,16 +378,8 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int endProgress;
|
|
||||||
if (signature != null) {
|
|
||||||
endProgress = 90;
|
|
||||||
} else if (esResult != null && esResult.encryptedData.isIntegrityProtected()) {
|
|
||||||
endProgress = 95;
|
|
||||||
} else {
|
|
||||||
endProgress = 100;
|
|
||||||
}
|
|
||||||
ProgressScaler progressScaler =
|
ProgressScaler progressScaler =
|
||||||
new ProgressScaler(mProgressable, currentProgress, endProgress, 100);
|
new ProgressScaler(mProgressable, currentProgress, 95, 100);
|
||||||
|
|
||||||
InputStream dataIn = literalData.getInputStream();
|
InputStream dataIn = literalData.getInputStream();
|
||||||
|
|
||||||
@@ -592,9 +395,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update signature buffer if signature is also present
|
// update signature buffer if signature is also present
|
||||||
if (signature != null) {
|
signatureChecker.updateSignatureData(buffer, 0, length);
|
||||||
signature.update(buffer, 0, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// note down first couple of bytes for "magic bytes" file type detection
|
// note down first couple of bytes for "magic bytes" file type detection
|
||||||
if (alreadyWritten == 0) {
|
if (alreadyWritten == 0) {
|
||||||
@@ -602,7 +403,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
}
|
}
|
||||||
|
|
||||||
alreadyWritten += length;
|
alreadyWritten += length;
|
||||||
|
// noinspection ConstantConditions, TODO progress
|
||||||
if (wholeSize > 0) {
|
if (wholeSize > 0) {
|
||||||
long progress = 100 * alreadyWritten / wholeSize;
|
long progress = 100 * alreadyWritten / wholeSize;
|
||||||
// stop at 100% for wrong file sizes...
|
// stop at 100% for wrong file sizes...
|
||||||
@@ -611,7 +412,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
}
|
}
|
||||||
progressScaler.setProgress((int) progress, 100);
|
progressScaler.setProgress((int) progress, 100);
|
||||||
}
|
}
|
||||||
// TODO: slow annealing to fake a progress?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// special treatment to detect pgp mime types
|
// special treatment to detect pgp mime types
|
||||||
@@ -628,28 +428,15 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
metadata = new OpenPgpMetadata(
|
metadata = new OpenPgpMetadata(
|
||||||
originalFilename, mimeType, literalData.getModificationTime().getTime(), alreadyWritten, charset);
|
originalFilename, mimeType, literalData.getModificationTime().getTime(), alreadyWritten, charset);
|
||||||
|
|
||||||
if (signature != null) {
|
if (signatureChecker.isInitialized()) {
|
||||||
updateProgress(R.string.progress_verifying_signature, 90, 100);
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
|
|
||||||
|
|
||||||
PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
|
Object o = plainFact.nextObject();
|
||||||
PGPSignature messageSignature = signatureList.get(signatureIndex);
|
boolean signatureCheckOk = signatureChecker.verifySignatureOnePass(o, log, indent + 1);
|
||||||
|
|
||||||
// Verify signature
|
if (!signatureCheckOk) {
|
||||||
boolean validSignature = signature.verify(messageSignature);
|
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
||||||
if (validSignature) {
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
|
|
||||||
} else {
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for insecure hash algorithms
|
|
||||||
if (!PgpSecurityConstants.isSecureHashAlgorithm(signature.getHashAlgorithm())) {
|
|
||||||
log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
|
|
||||||
signatureResultBuilder.setInsecure(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
signatureResultBuilder.setValidSignature(validSignature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
indent -= 1;
|
indent -= 1;
|
||||||
@@ -664,7 +451,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
log.add(LogType.MSG_DC_ERROR_INTEGRITY_CHECK, indent);
|
log.add(LogType.MSG_DC_ERROR_INTEGRITY_CHECK, indent);
|
||||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
||||||
}
|
}
|
||||||
} else if (signature == null) {
|
} else if ( ! signatureChecker.isInitialized() ) {
|
||||||
// If no signature is present, we *require* an MDC!
|
// If no signature is present, we *require* an MDC!
|
||||||
// Handle missing integrity protection like failed integrity protection!
|
// Handle missing integrity protection like failed integrity protection!
|
||||||
// The MDC packet can be stripped by an attacker!
|
// The MDC packet can be stripped by an attacker!
|
||||||
@@ -681,7 +468,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||||
|
|
||||||
result.setCachedCryptoInputParcel(cryptoInput);
|
result.setCachedCryptoInputParcel(cryptoInput);
|
||||||
result.setSignatureResult(signatureResultBuilder.build());
|
result.setSignatureResult(signatureChecker.getSignatureResult());
|
||||||
result.setDecryptionResult(decryptionResultBuilder.build());
|
result.setDecryptionResult(decryptionResultBuilder.build());
|
||||||
result.setDecryptionMetadata(metadata);
|
result.setDecryptionMetadata(metadata);
|
||||||
|
|
||||||
@@ -692,13 +479,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
private EncryptStreamResult handleEncryptedPacket(PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput,
|
private EncryptStreamResult handleEncryptedPacket(PgpDecryptVerifyInputParcel input, CryptoInputParcel cryptoInput,
|
||||||
PGPEncryptedDataList enc, OperationLog log, int indent, int currentProgress) throws PGPException {
|
PGPEncryptedDataList enc, OperationLog log, int indent, int currentProgress) throws PGPException {
|
||||||
|
|
||||||
// TODO is this necessary?
|
|
||||||
/*
|
|
||||||
else if (obj instanceof PGPEncryptedDataList) {
|
|
||||||
enc = (PGPEncryptedDataList) pgpF.nextObject();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
EncryptStreamResult result = new EncryptStreamResult();
|
EncryptStreamResult result = new EncryptStreamResult();
|
||||||
|
|
||||||
boolean asymmetricPacketFound = false;
|
boolean asymmetricPacketFound = false;
|
||||||
@@ -739,11 +519,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1);
|
log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (secretKeyRing == null) {
|
|
||||||
// continue with the next packet in the while loop
|
|
||||||
log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allow only specific keys for decryption?
|
// allow only specific keys for decryption?
|
||||||
if (input.getAllowedKeyIds() != null) {
|
if (input.getAllowedKeyIds() != null) {
|
||||||
@@ -763,11 +538,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
|
|
||||||
// get subkey which has been used for this encryption packet
|
// get subkey which has been used for this encryption packet
|
||||||
secretEncryptionKey = secretKeyRing.getSecretKey(subKeyId);
|
secretEncryptionKey = secretKeyRing.getSecretKey(subKeyId);
|
||||||
if (secretEncryptionKey == null) {
|
|
||||||
// should actually never happen, so no need to be more specific.
|
|
||||||
log.add(LogType.MSG_DC_ASKIP_NO_KEY, indent + 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* secret key exists in database and is allowed! */
|
/* secret key exists in database and is allowed! */
|
||||||
asymmetricPacketFound = true;
|
asymmetricPacketFound = true;
|
||||||
@@ -969,30 +739,31 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
|
|
||||||
OperationLog log = new OperationLog();
|
OperationLog log = new OperationLog();
|
||||||
|
|
||||||
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
byte[] clearText;
|
||||||
|
{ // read cleartext
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
updateProgress(R.string.progress_reading_data, 0, 100);
|
||||||
|
|
||||||
updateProgress(R.string.progress_reading_data, 0, 100);
|
ByteArrayOutputStream lineOut = new ByteArrayOutputStream();
|
||||||
|
int lookAhead = readInputLine(lineOut, aIn);
|
||||||
|
byte[] lineSep = getLineSeparator();
|
||||||
|
|
||||||
ByteArrayOutputStream lineOut = new ByteArrayOutputStream();
|
byte[] line = lineOut.toByteArray();
|
||||||
int lookAhead = readInputLine(lineOut, aIn);
|
|
||||||
byte[] lineSep = getLineSeparator();
|
|
||||||
|
|
||||||
byte[] line = lineOut.toByteArray();
|
|
||||||
out.write(line, 0, getLengthWithoutSeparator(line));
|
|
||||||
out.write(lineSep);
|
|
||||||
|
|
||||||
while (lookAhead != -1 && aIn.isClearText()) {
|
|
||||||
lookAhead = readInputLine(lineOut, lookAhead, aIn);
|
|
||||||
line = lineOut.toByteArray();
|
|
||||||
out.write(line, 0, getLengthWithoutSeparator(line));
|
out.write(line, 0, getLengthWithoutSeparator(line));
|
||||||
out.write(lineSep);
|
out.write(lineSep);
|
||||||
|
|
||||||
|
while (lookAhead != -1 && aIn.isClearText()) {
|
||||||
|
lookAhead = readInputLine(lineOut, lookAhead, aIn);
|
||||||
|
line = lineOut.toByteArray();
|
||||||
|
out.write(line, 0, getLengthWithoutSeparator(line));
|
||||||
|
out.write(lineSep);
|
||||||
|
}
|
||||||
|
|
||||||
|
out.close();
|
||||||
|
clearText = out.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
out.close();
|
|
||||||
|
|
||||||
byte[] clearText = out.toByteArray();
|
|
||||||
if (outputStream != null) {
|
if (outputStream != null) {
|
||||||
outputStream.write(clearText);
|
outputStream.write(clearText);
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
@@ -1001,51 +772,20 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
updateProgress(R.string.progress_processing_signature, 60, 100);
|
updateProgress(R.string.progress_processing_signature, 60, 100);
|
||||||
JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(aIn);
|
JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(aIn);
|
||||||
|
|
||||||
PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject();
|
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper);
|
||||||
if (sigList == null) {
|
|
||||||
|
Object o = pgpFact.nextObject();
|
||||||
|
if (!signatureChecker.initializeSignature(o, log, indent+1)) {
|
||||||
log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0);
|
log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0);
|
||||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPSignature signature = processPGPSignatureList(sigList, signatureResultBuilder, log, indent);
|
if (signatureChecker.isInitialized()) {
|
||||||
|
|
||||||
if (signature != null) {
|
|
||||||
try {
|
try {
|
||||||
updateProgress(R.string.progress_verifying_signature, 90, 100);
|
updateProgress(R.string.progress_verifying_signature, 90, 100);
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
|
|
||||||
|
|
||||||
InputStream sigIn = new BufferedInputStream(new ByteArrayInputStream(clearText));
|
signatureChecker.updateSignatureWithCleartext(clearText);
|
||||||
|
signatureChecker.verifySignature(log, indent);
|
||||||
lookAhead = readInputLine(lineOut, sigIn);
|
|
||||||
|
|
||||||
processLine(signature, lineOut.toByteArray());
|
|
||||||
|
|
||||||
if (lookAhead != -1) {
|
|
||||||
do {
|
|
||||||
lookAhead = readInputLine(lineOut, lookAhead, sigIn);
|
|
||||||
|
|
||||||
signature.update((byte) '\r');
|
|
||||||
signature.update((byte) '\n');
|
|
||||||
|
|
||||||
processLine(signature, lineOut.toByteArray());
|
|
||||||
} while (lookAhead != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify signature and check binding signatures
|
|
||||||
boolean validSignature = signature.verify();
|
|
||||||
if (validSignature) {
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
|
|
||||||
} else {
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for insecure hash algorithms
|
|
||||||
if (!PgpSecurityConstants.isSecureHashAlgorithm(signature.getHashAlgorithm())) {
|
|
||||||
log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
|
|
||||||
signatureResultBuilder.setInsecure(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
signatureResultBuilder.setValidSignature(validSignature);
|
|
||||||
|
|
||||||
} catch (SignatureException e) {
|
} catch (SignatureException e) {
|
||||||
Log.d(Constants.TAG, "SignatureException", e);
|
Log.d(Constants.TAG, "SignatureException", e);
|
||||||
@@ -1064,7 +804,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
clearText.length);
|
clearText.length);
|
||||||
|
|
||||||
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||||
result.setSignatureResult(signatureResultBuilder.build());
|
result.setSignatureResult(signatureChecker.getSignatureResult());
|
||||||
result.setDecryptionResult(
|
result.setDecryptionResult(
|
||||||
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
|
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
|
||||||
result.setDecryptionMetadata(metadata);
|
result.setDecryptionMetadata(metadata);
|
||||||
@@ -1078,30 +818,28 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
|
|
||||||
OperationLog log = new OperationLog();
|
OperationLog log = new OperationLog();
|
||||||
|
|
||||||
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
|
||||||
|
|
||||||
updateProgress(R.string.progress_processing_signature, 0, 100);
|
updateProgress(R.string.progress_processing_signature, 0, 100);
|
||||||
InputStream detachedSigIn = new ByteArrayInputStream(input.getDetachedSignature());
|
InputStream detachedSigIn = new ByteArrayInputStream(input.getDetachedSignature());
|
||||||
detachedSigIn = PGPUtil.getDecoderStream(detachedSigIn);
|
detachedSigIn = PGPUtil.getDecoderStream(detachedSigIn);
|
||||||
|
|
||||||
JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(detachedSigIn);
|
JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(detachedSigIn);
|
||||||
|
|
||||||
PGPSignatureList sigList;
|
|
||||||
Object o = pgpFact.nextObject();
|
Object o = pgpFact.nextObject();
|
||||||
if (o instanceof PGPCompressedData) {
|
if (o instanceof PGPCompressedData) {
|
||||||
PGPCompressedData c1 = (PGPCompressedData) o;
|
PGPCompressedData c1 = (PGPCompressedData) o;
|
||||||
pgpFact = new JcaPGPObjectFactory(c1.getDataStream());
|
pgpFact = new JcaPGPObjectFactory(c1.getDataStream());
|
||||||
sigList = (PGPSignatureList) pgpFact.nextObject();
|
o = pgpFact.nextObject();
|
||||||
} else if (o instanceof PGPSignatureList) {
|
}
|
||||||
sigList = (PGPSignatureList) o;
|
|
||||||
} else {
|
PgpSignatureChecker signatureChecker = new PgpSignatureChecker(mProviderHelper);
|
||||||
|
|
||||||
|
if ( ! signatureChecker.initializeSignature(o, log, indent+1)) {
|
||||||
log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0);
|
log.add(LogType.MSG_DC_ERROR_INVALID_DATA, 0);
|
||||||
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
return new DecryptVerifyResult(DecryptVerifyResult.RESULT_ERROR, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
PGPSignature signature = processPGPSignatureList(sigList, signatureResultBuilder, log, indent);
|
if (signatureChecker.isInitialized()) {
|
||||||
|
|
||||||
if (signature != null) {
|
|
||||||
updateProgress(R.string.progress_reading_data, 60, 100);
|
updateProgress(R.string.progress_reading_data, 60, 100);
|
||||||
|
|
||||||
ProgressScaler progressScaler = new ProgressScaler(mProgressable, 60, 90, 100);
|
ProgressScaler progressScaler = new ProgressScaler(mProgressable, 60, 90, 100);
|
||||||
@@ -1116,7 +854,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update signature buffer if signature is also present
|
// update signature buffer if signature is also present
|
||||||
signature.update(buffer, 0, length);
|
signatureChecker.updateSignatureData(buffer, 0, length);
|
||||||
|
|
||||||
alreadyWritten += length;
|
alreadyWritten += length;
|
||||||
if (wholeSize > 0) {
|
if (wholeSize > 0) {
|
||||||
@@ -1127,105 +865,28 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
}
|
}
|
||||||
progressScaler.setProgress((int) progress, 100);
|
progressScaler.setProgress((int) progress, 100);
|
||||||
}
|
}
|
||||||
// TODO: slow annealing to fake a progress?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProgress(R.string.progress_verifying_signature, 90, 100);
|
updateProgress(R.string.progress_verifying_signature, 90, 100);
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
|
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
|
||||||
|
|
||||||
// Verify signature and check binding signatures
|
signatureChecker.verifySignature(log, indent);
|
||||||
boolean validSignature = signature.verify();
|
|
||||||
if (validSignature) {
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
|
|
||||||
} else {
|
|
||||||
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for insecure hash algorithms
|
|
||||||
if (!PgpSecurityConstants.isSecureHashAlgorithm(signature.getHashAlgorithm())) {
|
|
||||||
log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
|
|
||||||
signatureResultBuilder.setInsecure(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
signatureResultBuilder.setValidSignature(validSignature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProgress(R.string.progress_done, 100, 100);
|
updateProgress(R.string.progress_done, 100, 100);
|
||||||
|
|
||||||
log.add(LogType.MSG_DC_OK, indent);
|
log.add(LogType.MSG_DC_OK, indent);
|
||||||
|
|
||||||
|
// TODO return metadata object?
|
||||||
|
|
||||||
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||||
result.setSignatureResult(signatureResultBuilder.build());
|
result.setSignatureResult(signatureChecker.getSignatureResult());
|
||||||
result.setDecryptionResult(
|
result.setDecryptionResult(
|
||||||
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
|
new OpenPgpDecryptionResult(OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PGPSignature processPGPSignatureList(
|
|
||||||
PGPSignatureList sigList, OpenPgpSignatureResultBuilder signatureResultBuilder,
|
|
||||||
OperationLog log, int indent)
|
|
||||||
throws PGPException {
|
|
||||||
CanonicalizedPublicKeyRing signingRing = null;
|
|
||||||
CanonicalizedPublicKey signingKey = null;
|
|
||||||
int signatureIndex = -1;
|
|
||||||
|
|
||||||
// go through all signatures
|
|
||||||
// and find out for which signature we have a key in our database
|
|
||||||
for (int i = 0; i < sigList.size(); ++i) {
|
|
||||||
try {
|
|
||||||
long sigKeyId = sigList.get(i).getKeyID();
|
|
||||||
signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
|
|
||||||
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
|
|
||||||
);
|
|
||||||
signingKey = signingRing.getPublicKey(sigKeyId);
|
|
||||||
signatureIndex = i;
|
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
|
||||||
Log.d(Constants.TAG, "key not found, trying next signature...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PGPSignature signature = null;
|
|
||||||
|
|
||||||
if (signingKey != null) {
|
|
||||||
// key found in our database!
|
|
||||||
signature = sigList.get(signatureIndex);
|
|
||||||
|
|
||||||
signatureResultBuilder.initValid(signingRing, signingKey);
|
|
||||||
|
|
||||||
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
|
||||||
new JcaPGPContentVerifierBuilderProvider()
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
|
||||||
signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
|
|
||||||
} else {
|
|
||||||
// no key in our database -> return "unknown pub key" status including the first key id
|
|
||||||
if (!sigList.isEmpty()) {
|
|
||||||
signatureResultBuilder.setSignatureAvailable(true);
|
|
||||||
signatureResultBuilder.setKnownKey(false);
|
|
||||||
signatureResultBuilder.setKeyId(sigList.get(0).getKeyID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for insecure signing key
|
|
||||||
// TODO: checks on signingRing ?
|
|
||||||
if (signingKey != null && ! PgpSecurityConstants.isSecureKey(signingKey)) {
|
|
||||||
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
|
|
||||||
signatureResultBuilder.setInsecure(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mostly taken from ClearSignedFileProcessor in Bouncy Castle
|
|
||||||
*/
|
|
||||||
private static void processLine(PGPSignature sig, byte[] line)
|
|
||||||
throws SignatureException {
|
|
||||||
int length = getLengthWithoutWhiteSpace(line);
|
|
||||||
if (length > 0) {
|
|
||||||
sig.update(line, 0, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int readInputLine(ByteArrayOutputStream bOut, InputStream fIn)
|
private static int readInputLine(ByteArrayOutputStream bOut, InputStream fIn)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
bOut.reset();
|
bOut.reset();
|
||||||
@@ -1291,20 +952,6 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
|||||||
return b == '\r' || b == '\n';
|
return b == '\r' || b == '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getLengthWithoutWhiteSpace(byte[] line) {
|
|
||||||
int end = line.length - 1;
|
|
||||||
|
|
||||||
while (end >= 0 && isWhiteSpace(line[end])) {
|
|
||||||
end--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return end + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isWhiteSpace(byte b) {
|
|
||||||
return b == '\r' || b == '\n' || b == '\t' || b == ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] getLineSeparator() {
|
private static byte[] getLineSeparator() {
|
||||||
String nl = System.getProperty("line.separator");
|
String nl = System.getProperty("line.separator");
|
||||||
return nl.getBytes();
|
return nl.getBytes();
|
||||||
|
|||||||
@@ -171,8 +171,8 @@ public class PgpKeyOperation {
|
|||||||
log.add(LogType.MSG_CR_ERROR_NO_KEYSIZE, indent);
|
log.add(LogType.MSG_CR_ERROR_NO_KEYSIZE, indent);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (add.mKeySize < 512) {
|
if (add.mKeySize < 2048) {
|
||||||
log.add(LogType.MSG_CR_ERROR_KEYSIZE_512, indent);
|
log.add(LogType.MSG_CR_ERROR_KEYSIZE_2048, indent);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -492,9 +492,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
|||||||
|
|
||||||
literalGen.close();
|
literalGen.close();
|
||||||
} else {
|
} else {
|
||||||
pOut = null;
|
throw new AssertionError("cannot clearsign in non-ascii armored text, this is a bug!");
|
||||||
// TODO: Is this log right?
|
|
||||||
log.add(LogType.MSG_PSE_CLEARSIGN_ONLY, indent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableSignature) {
|
if (enableSignature) {
|
||||||
|
|||||||
@@ -0,0 +1,344 @@
|
|||||||
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
|
||||||
|
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||||
|
import org.spongycastle.openpgp.PGPException;
|
||||||
|
import org.spongycastle.openpgp.PGPOnePassSignature;
|
||||||
|
import org.spongycastle.openpgp.PGPOnePassSignatureList;
|
||||||
|
import org.spongycastle.openpgp.PGPSignature;
|
||||||
|
import org.spongycastle.openpgp.PGPSignatureList;
|
||||||
|
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
|
||||||
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
|
|
||||||
|
/** This class is used to track the state of a single signature verification.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class PgpSignatureChecker {
|
||||||
|
|
||||||
|
OpenPgpSignatureResultBuilder signatureResultBuilder = new OpenPgpSignatureResultBuilder();
|
||||||
|
|
||||||
|
private CanonicalizedPublicKey signingKey;
|
||||||
|
|
||||||
|
private int signatureIndex;
|
||||||
|
PGPOnePassSignature onePassSignature;
|
||||||
|
PGPSignature signature;
|
||||||
|
|
||||||
|
ProviderHelper mProviderHelper;
|
||||||
|
|
||||||
|
PgpSignatureChecker(ProviderHelper providerHelper) {
|
||||||
|
mProviderHelper = providerHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean initializeSignature(Object dataChunk, OperationLog log, int indent) throws PGPException {
|
||||||
|
|
||||||
|
if (!(dataChunk instanceof PGPSignatureList)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PGPSignatureList sigList = (PGPSignatureList) dataChunk;
|
||||||
|
findAvailableSignature(sigList);
|
||||||
|
|
||||||
|
if (signingKey != null) {
|
||||||
|
|
||||||
|
// key found in our database!
|
||||||
|
signatureResultBuilder.initValid(signingKey);
|
||||||
|
|
||||||
|
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
||||||
|
new JcaPGPContentVerifierBuilderProvider()
|
||||||
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
|
signature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
|
||||||
|
checkKeySecurity(log, indent);
|
||||||
|
|
||||||
|
|
||||||
|
} else if (!sigList.isEmpty()) {
|
||||||
|
|
||||||
|
signatureResultBuilder.setSignatureAvailable(true);
|
||||||
|
signatureResultBuilder.setKnownKey(false);
|
||||||
|
signatureResultBuilder.setKeyId(sigList.get(0).getKeyID());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean initializeOnePassSignature(Object dataChunk, OperationLog log, int indent) throws PGPException {
|
||||||
|
|
||||||
|
if (!(dataChunk instanceof PGPOnePassSignatureList)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.add(LogType.MSG_DC_CLEAR_SIGNATURE, indent + 1);
|
||||||
|
|
||||||
|
PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk;
|
||||||
|
findAvailableSignature(sigList);
|
||||||
|
|
||||||
|
if (signingKey != null) {
|
||||||
|
|
||||||
|
// key found in our database!
|
||||||
|
signatureResultBuilder.initValid(signingKey);
|
||||||
|
|
||||||
|
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider =
|
||||||
|
new JcaPGPContentVerifierBuilderProvider()
|
||||||
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||||
|
onePassSignature.init(contentVerifierBuilderProvider, signingKey.getPublicKey());
|
||||||
|
|
||||||
|
checkKeySecurity(log, indent);
|
||||||
|
|
||||||
|
} else if (!sigList.isEmpty()) {
|
||||||
|
|
||||||
|
signatureResultBuilder.setSignatureAvailable(true);
|
||||||
|
signatureResultBuilder.setKnownKey(false);
|
||||||
|
signatureResultBuilder.setKeyId(sigList.get(0).getKeyID());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkKeySecurity(OperationLog log, int indent) {
|
||||||
|
// TODO: checks on signingRing ?
|
||||||
|
if (!PgpSecurityConstants.isSecureKey(signingKey)) {
|
||||||
|
log.add(LogType.MSG_DC_INSECURE_KEY, indent + 1);
|
||||||
|
signatureResultBuilder.setInsecure(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInitialized() {
|
||||||
|
return signingKey != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findAvailableSignature(PGPOnePassSignatureList sigList) {
|
||||||
|
// go through all signatures (should be just one), make sure we have
|
||||||
|
// the key and it matches the one we’re looking for
|
||||||
|
for (int i = 0; i < sigList.size(); ++i) {
|
||||||
|
try {
|
||||||
|
long sigKeyId = sigList.get(i).getKeyID();
|
||||||
|
CanonicalizedPublicKeyRing signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
|
||||||
|
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
|
||||||
|
);
|
||||||
|
CanonicalizedPublicKey keyCandidate = signingRing.getPublicKey(sigKeyId);
|
||||||
|
if ( ! signingKey.canSign()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
signatureIndex = i;
|
||||||
|
signingKey = keyCandidate;
|
||||||
|
onePassSignature = sigList.get(i);
|
||||||
|
return;
|
||||||
|
} catch (ProviderHelper.NotFoundException e) {
|
||||||
|
Log.d(Constants.TAG, "key not found, trying next signature...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void findAvailableSignature(PGPSignatureList sigList) {
|
||||||
|
// go through all signatures (should be just one), make sure we have
|
||||||
|
// the key and it matches the one we’re looking for
|
||||||
|
for (int i = 0; i < sigList.size(); ++i) {
|
||||||
|
try {
|
||||||
|
long sigKeyId = sigList.get(i).getKeyID();
|
||||||
|
CanonicalizedPublicKeyRing signingRing = mProviderHelper.getCanonicalizedPublicKeyRing(
|
||||||
|
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(sigKeyId)
|
||||||
|
);
|
||||||
|
CanonicalizedPublicKey keyCandidate = signingRing.getPublicKey(sigKeyId);
|
||||||
|
if ( ! signingKey.canSign()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
signatureIndex = i;
|
||||||
|
signingKey = keyCandidate;
|
||||||
|
signature = sigList.get(i);
|
||||||
|
return;
|
||||||
|
} catch (ProviderHelper.NotFoundException e) {
|
||||||
|
Log.d(Constants.TAG, "key not found, trying next signature...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateSignatureWithCleartext(byte[] clearText) throws IOException, SignatureException {
|
||||||
|
|
||||||
|
InputStream sigIn = new BufferedInputStream(new ByteArrayInputStream(clearText));
|
||||||
|
|
||||||
|
ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
int lookAhead = readInputLine(outputBuffer, sigIn);
|
||||||
|
|
||||||
|
processLine(signature, outputBuffer.toByteArray());
|
||||||
|
|
||||||
|
while (lookAhead != -1) {
|
||||||
|
lookAhead = readInputLine(outputBuffer, lookAhead, sigIn);
|
||||||
|
|
||||||
|
signature.update((byte) '\r');
|
||||||
|
signature.update((byte) '\n');
|
||||||
|
|
||||||
|
processLine(signature, outputBuffer.toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateSignatureData(byte[] buf, int off, int len) {
|
||||||
|
if (signature != null) {
|
||||||
|
signature.update(buf, off, len);
|
||||||
|
} else if (onePassSignature != null) {
|
||||||
|
onePassSignature.update(buf, off, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void verifySignature(OperationLog log, int indent) throws PGPException {
|
||||||
|
|
||||||
|
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent);
|
||||||
|
|
||||||
|
// Verify signature
|
||||||
|
boolean validSignature = signature.verify();
|
||||||
|
if (validSignature) {
|
||||||
|
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
|
||||||
|
} else {
|
||||||
|
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for insecure hash algorithms
|
||||||
|
if (!PgpSecurityConstants.isSecureHashAlgorithm(signature.getHashAlgorithm())) {
|
||||||
|
log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
|
||||||
|
signatureResultBuilder.setInsecure(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
signatureResultBuilder.setValidSignature(validSignature);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean verifySignatureOnePass(Object o, OperationLog log, int indent) throws PGPException {
|
||||||
|
|
||||||
|
if (!(o instanceof PGPSignatureList)) {
|
||||||
|
log.add(LogType.MSG_DC_ERROR_NO_SIGNATURE, indent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PGPSignatureList signatureList = (PGPSignatureList) o;
|
||||||
|
if (signatureList.size() <= signatureIndex) {
|
||||||
|
log.add(LogType.MSG_DC_ERROR_NO_SIGNATURE, indent);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PGPOnePassSignature and PGPSignature packets are "bracketed",
|
||||||
|
// so we need to take the last-minus-index'th element here
|
||||||
|
PGPSignature messageSignature = signatureList.get(signatureList.size() - 1 - signatureIndex);
|
||||||
|
|
||||||
|
// Verify signature
|
||||||
|
boolean validSignature = onePassSignature.verify(messageSignature);
|
||||||
|
if (validSignature) {
|
||||||
|
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_OK, indent + 1);
|
||||||
|
} else {
|
||||||
|
log.add(LogType.MSG_DC_CLEAR_SIGNATURE_BAD, indent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for insecure hash algorithms
|
||||||
|
if (!PgpSecurityConstants.isSecureHashAlgorithm(onePassSignature.getHashAlgorithm())) {
|
||||||
|
log.add(LogType.MSG_DC_INSECURE_HASH_ALGO, indent + 1);
|
||||||
|
signatureResultBuilder.setInsecure(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
signatureResultBuilder.setValidSignature(validSignature);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getSigningFingerprint() {
|
||||||
|
return signingKey.getFingerprint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OpenPgpSignatureResult getSignatureResult() {
|
||||||
|
return signatureResultBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mostly taken from ClearSignedFileProcessor in Bouncy Castle
|
||||||
|
*/
|
||||||
|
|
||||||
|
private static void processLine(PGPSignature sig, byte[] line)
|
||||||
|
throws SignatureException {
|
||||||
|
int length = getLengthWithoutWhiteSpace(line);
|
||||||
|
if (length > 0) {
|
||||||
|
sig.update(line, 0, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readInputLine(ByteArrayOutputStream bOut, InputStream fIn)
|
||||||
|
throws IOException {
|
||||||
|
bOut.reset();
|
||||||
|
|
||||||
|
int lookAhead = -1;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
while ((ch = fIn.read()) >= 0) {
|
||||||
|
bOut.write(ch);
|
||||||
|
if (ch == '\r' || ch == '\n') {
|
||||||
|
lookAhead = readPastEOL(bOut, ch, fIn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lookAhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readInputLine(ByteArrayOutputStream bOut, int lookAhead, InputStream fIn)
|
||||||
|
throws IOException {
|
||||||
|
bOut.reset();
|
||||||
|
|
||||||
|
int ch = lookAhead;
|
||||||
|
|
||||||
|
do {
|
||||||
|
bOut.write(ch);
|
||||||
|
if (ch == '\r' || ch == '\n') {
|
||||||
|
lookAhead = readPastEOL(bOut, ch, fIn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ((ch = fIn.read()) >= 0);
|
||||||
|
|
||||||
|
if (ch < 0) {
|
||||||
|
lookAhead = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lookAhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readPastEOL(ByteArrayOutputStream bOut, int lastCh, InputStream fIn)
|
||||||
|
throws IOException {
|
||||||
|
int lookAhead = fIn.read();
|
||||||
|
|
||||||
|
if (lastCh == '\r' && lookAhead == '\n') {
|
||||||
|
bOut.write(lookAhead);
|
||||||
|
lookAhead = fIn.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
return lookAhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getLengthWithoutWhiteSpace(byte[] line) {
|
||||||
|
int end = line.length - 1;
|
||||||
|
|
||||||
|
while (end >= 0 && isWhiteSpace(line[end])) {
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return end + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isWhiteSpace(byte b) {
|
||||||
|
return b == '\r' || b == '\n' || b == '\t' || b == ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -83,6 +83,8 @@ public class UncachedKeyRing {
|
|||||||
final PGPKeyRing mRing;
|
final PGPKeyRing mRing;
|
||||||
final boolean mIsSecret;
|
final boolean mIsSecret;
|
||||||
|
|
||||||
|
private static final int CANONICALIZE_MAX_USER_IDS = 100;
|
||||||
|
|
||||||
UncachedKeyRing(PGPKeyRing ring) {
|
UncachedKeyRing(PGPKeyRing ring) {
|
||||||
mRing = ring;
|
mRing = ring;
|
||||||
mIsSecret = ring instanceof PGPSecretKeyRing;
|
mIsSecret = ring instanceof PGPSecretKeyRing;
|
||||||
@@ -460,7 +462,7 @@ public class UncachedKeyRing {
|
|||||||
// strip out the first found user id with this name
|
// strip out the first found user id with this name
|
||||||
modified = PGPPublicKey.removeCertification(modified, rawUserId);
|
modified = PGPPublicKey.removeCertification(modified, rawUserId);
|
||||||
}
|
}
|
||||||
if (processedUserIds.size() > 100) {
|
if (processedUserIds.size() > CANONICALIZE_MAX_USER_IDS) {
|
||||||
log.add(LogType.MSG_KC_UID_TOO_MANY, indent, userId);
|
log.add(LogType.MSG_KC_UID_TOO_MANY, indent, userId);
|
||||||
// strip out the user id
|
// strip out the user id
|
||||||
modified = PGPPublicKey.removeCertification(modified, rawUserId);
|
modified = PGPPublicKey.removeCertification(modified, rawUserId);
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
|||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeys;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.UpdatedKeys;
|
||||||
import org.sufficientlysecure.keychain.remote.AccountSettings;
|
import org.sufficientlysecure.keychain.remote.AccountSettings;
|
||||||
import org.sufficientlysecure.keychain.remote.AppSettings;
|
import org.sufficientlysecure.keychain.remote.AppSettings;
|
||||||
@@ -968,7 +967,7 @@ public class ProviderHelper {
|
|||||||
|
|
||||||
// If we have an expected fingerprint, make sure it matches
|
// If we have an expected fingerprint, make sure it matches
|
||||||
if (expectedFingerprint != null) {
|
if (expectedFingerprint != null) {
|
||||||
if (!canPublicRing.containsSubkey(expectedFingerprint)) {
|
if (!canPublicRing.containsBoundSubkey(expectedFingerprint)) {
|
||||||
log(LogType.MSG_IP_FINGERPRINT_ERROR);
|
log(LogType.MSG_IP_FINGERPRINT_ERROR);
|
||||||
return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null);
|
return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog, null);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class CreateYubiKeyImportFragment
|
|||||||
extends QueueingCryptoOperationFragment<ImportKeyringParcel, ImportKeyResult>
|
extends QueueingCryptoOperationFragment<ImportKeyringParcel, ImportKeyResult>
|
||||||
implements NfcListenerFragment {
|
implements NfcListenerFragment {
|
||||||
|
|
||||||
private static final String ARG_FINGERPRINT = "fingerprint";
|
private static final String ARG_FINGERPRINTS = "fingerprint";
|
||||||
public static final String ARG_AID = "aid";
|
public static final String ARG_AID = "aid";
|
||||||
public static final String ARG_USER_ID = "user_ids";
|
public static final String ARG_USER_ID = "user_ids";
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ public class CreateYubiKeyImportFragment
|
|||||||
CreateYubiKeyImportFragment frag = new CreateYubiKeyImportFragment();
|
CreateYubiKeyImportFragment frag = new CreateYubiKeyImportFragment();
|
||||||
|
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putByteArray(ARG_FINGERPRINT, scannedFingerprints);
|
args.putByteArray(ARG_FINGERPRINTS, scannedFingerprints);
|
||||||
args.putByteArray(ARG_AID, nfcAid);
|
args.putByteArray(ARG_AID, nfcAid);
|
||||||
args.putString(ARG_USER_ID, userId);
|
args.putString(ARG_USER_ID, userId);
|
||||||
frag.setArguments(args);
|
frag.setArguments(args);
|
||||||
@@ -86,7 +86,7 @@ public class CreateYubiKeyImportFragment
|
|||||||
|
|
||||||
Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
|
Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
|
||||||
|
|
||||||
mNfcFingerprints = args.getByteArray(ARG_FINGERPRINT);
|
mNfcFingerprints = args.getByteArray(ARG_FINGERPRINTS);
|
||||||
mNfcAid = args.getByteArray(ARG_AID);
|
mNfcAid = args.getByteArray(ARG_AID);
|
||||||
mNfcUserId = args.getString(ARG_USER_ID);
|
mNfcUserId = args.getString(ARG_USER_ID);
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ public class CreateYubiKeyImportFragment
|
|||||||
public void onSaveInstanceState(Bundle args) {
|
public void onSaveInstanceState(Bundle args) {
|
||||||
super.onSaveInstanceState(args);
|
super.onSaveInstanceState(args);
|
||||||
|
|
||||||
args.putByteArray(ARG_FINGERPRINT, mNfcFingerprints);
|
args.putByteArray(ARG_FINGERPRINTS, mNfcFingerprints);
|
||||||
args.putByteArray(ARG_AID, mNfcAid);
|
args.putByteArray(ARG_AID, mNfcAid);
|
||||||
args.putString(ARG_USER_ID, mNfcUserId);
|
args.putString(ARG_USER_ID, mNfcUserId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import org.sufficientlysecure.keychain.R;
|
|||||||
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
|
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||||
import org.sufficientlysecure.keychain.util.ShareHelper;
|
|
||||||
|
|
||||||
public class DisplayTextFragment extends DecryptFragment {
|
public class DisplayTextFragment extends DecryptFragment {
|
||||||
|
|
||||||
@@ -60,22 +59,6 @@ public class DisplayTextFragment extends DecryptFragment {
|
|||||||
return frag;
|
return frag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create Intent Chooser but exclude decrypt activites
|
|
||||||
*/
|
|
||||||
private Intent sendWithChooserExcludingDecrypt(String text) {
|
|
||||||
Intent prototype = createSendIntent(text);
|
|
||||||
String title = getString(R.string.title_share_message);
|
|
||||||
|
|
||||||
// we don't want to decrypt the decrypted, no inception ;)
|
|
||||||
String[] blacklist = new String[]{
|
|
||||||
Constants.PACKAGE_NAME + ".ui.DecryptActivity",
|
|
||||||
"org.thialfihar.android.apg.ui.DecryptActivity"
|
|
||||||
};
|
|
||||||
|
|
||||||
return new ShareHelper(getActivity()).createChooserExcluding(prototype, title, blacklist);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Intent createSendIntent(String text) {
|
private Intent createSendIntent(String text) {
|
||||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||||
sendIntent.putExtra(Intent.EXTRA_TEXT, text);
|
sendIntent.putExtra(Intent.EXTRA_TEXT, text);
|
||||||
@@ -146,7 +129,8 @@ public class DisplayTextFragment extends DecryptFragment {
|
|||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.decrypt_share: {
|
case R.id.decrypt_share: {
|
||||||
startActivity(sendWithChooserExcludingDecrypt(mText.getText().toString()));
|
startActivity(Intent.createChooser(createSendIntent(mText.getText().toString()),
|
||||||
|
getString(R.string.title_share_message)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R.id.decrypt_copy: {
|
case R.id.decrypt_copy: {
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ import org.sufficientlysecure.keychain.util.FileHelper;
|
|||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
import org.sufficientlysecure.keychain.util.ShareHelper;
|
|
||||||
|
|
||||||
public class EncryptFilesFragment
|
public class EncryptFilesFragment
|
||||||
extends CachingCryptoOperationFragment<SignEncryptParcel, SignEncryptResult> {
|
extends CachingCryptoOperationFragment<SignEncryptParcel, SignEncryptResult> {
|
||||||
@@ -406,7 +405,7 @@ public class EncryptFilesFragment
|
|||||||
public void onDeleted() {
|
public void onDeleted() {
|
||||||
if (mAfterEncryptAction == AfterEncryptAction.SHARE) {
|
if (mAfterEncryptAction == AfterEncryptAction.SHARE) {
|
||||||
// Share encrypted message/file
|
// Share encrypted message/file
|
||||||
startActivity(sendWithChooserExcludingEncrypt());
|
startActivity(Intent.createChooser(createSendIntent(), getString(R.string.title_share_file)));
|
||||||
} else {
|
} else {
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
if (activity == null) {
|
if (activity == null) {
|
||||||
@@ -426,7 +425,7 @@ public class EncryptFilesFragment
|
|||||||
|
|
||||||
case SHARE:
|
case SHARE:
|
||||||
// Share encrypted message/file
|
// Share encrypted message/file
|
||||||
startActivity(sendWithChooserExcludingEncrypt());
|
startActivity(Intent.createChooser(createSendIntent(), getString(R.string.title_share_file)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COPY:
|
case COPY:
|
||||||
@@ -622,22 +621,6 @@ public class EncryptFilesFragment
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create Intent Chooser but exclude OK's EncryptActivity.
|
|
||||||
*/
|
|
||||||
private Intent sendWithChooserExcludingEncrypt() {
|
|
||||||
Intent prototype = createSendIntent();
|
|
||||||
String title = getString(R.string.title_share_file);
|
|
||||||
|
|
||||||
// we don't want to encrypt the encrypted, no inception ;)
|
|
||||||
String[] blacklist = new String[]{
|
|
||||||
Constants.PACKAGE_NAME + ".ui.EncryptFilesActivity",
|
|
||||||
"org.thialfihar.android.apg.ui.EncryptActivity"
|
|
||||||
};
|
|
||||||
|
|
||||||
return new ShareHelper(getActivity()).createChooserExcluding(prototype, title, blacklist);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Intent createSendIntent() {
|
private Intent createSendIntent() {
|
||||||
Intent sendIntent;
|
Intent sendIntent;
|
||||||
// file
|
// file
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener;
|
|||||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
import org.sufficientlysecure.keychain.util.ShareHelper;
|
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -289,22 +288,6 @@ public class EncryptTextFragment
|
|||||||
result.createNotify(activity).show();
|
result.createNotify(activity).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create Intent Chooser but exclude OK's EncryptActivity.
|
|
||||||
*/
|
|
||||||
private Intent sendWithChooserExcludingEncrypt(byte[] resultBytes) {
|
|
||||||
Intent prototype = createSendIntent(resultBytes);
|
|
||||||
String title = getString(R.string.title_share_message);
|
|
||||||
|
|
||||||
// we don't want to encrypt the encrypted, no inception ;)
|
|
||||||
String[] blacklist = new String[]{
|
|
||||||
Constants.PACKAGE_NAME + ".ui.EncryptTextActivity",
|
|
||||||
"org.thialfihar.android.apg.ui.EncryptActivity"
|
|
||||||
};
|
|
||||||
|
|
||||||
return new ShareHelper(getActivity()).createChooserExcluding(prototype, title, blacklist);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Intent createSendIntent(byte[] resultBytes) {
|
private Intent createSendIntent(byte[] resultBytes) {
|
||||||
Intent sendIntent;
|
Intent sendIntent;
|
||||||
sendIntent = new Intent(Intent.ACTION_SEND);
|
sendIntent = new Intent(Intent.ACTION_SEND);
|
||||||
@@ -343,7 +326,8 @@ public class EncryptTextFragment
|
|||||||
|
|
||||||
if (mShareAfterEncrypt) {
|
if (mShareAfterEncrypt) {
|
||||||
// Share encrypted message/file
|
// Share encrypted message/file
|
||||||
startActivity(sendWithChooserExcludingEncrypt(result.getResultBytes()));
|
startActivity(Intent.createChooser(createSendIntent(result.getResultBytes()),
|
||||||
|
getString(R.string.title_share_message)));
|
||||||
} else {
|
} else {
|
||||||
// Copy to clipboard
|
// Copy to clipboard
|
||||||
copyToClipboard(result);
|
copyToClipboard(result);
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEnt
|
|||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogLevel;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogLevel;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.SubLogEntryParcel;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.SubLogEntryParcel;
|
||||||
import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
|
import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
|
||||||
|
import org.sufficientlysecure.keychain.ui.dialog.ShareLogDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||||
@@ -149,11 +150,9 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
|
||||||
intent.putExtra(Intent.EXTRA_STREAM, mLogTempFile);
|
ShareLogDialogFragment shareLogDialog = ShareLogDialogFragment.newInstance(mLogTempFile);
|
||||||
intent.setType("text/plain");
|
shareLogDialog.show(getActivity().getSupportFragmentManager(), "shareLogDialog");
|
||||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
||||||
startActivity(intent);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -348,30 +348,30 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <h3>RSA</h3>
|
* <h3>RSA</h3>
|
||||||
* <p>for RSA algorithm, key length must be greater than 1024 (according to
|
* <p>for RSA algorithm, key length must be greater than 2048. Possibility to generate keys bigger
|
||||||
* <a href="https://github.com/open-keychain/open-keychain/issues/102">#102</a>). Possibility to generate keys bigger
|
|
||||||
* than 8192 bits is currently disabled, because it's almost impossible to generate them on a mobile device (check
|
* than 8192 bits is currently disabled, because it's almost impossible to generate them on a mobile device (check
|
||||||
* <a href="http://www.javamex.com/tutorials/cryptography/rsa_key_length.shtml">RSA key length plot</a> and
|
* <a href="http://www.javamex.com/tutorials/cryptography/rsa_key_length.shtml">RSA key length plot</a> and
|
||||||
* <a href="http://www.keylength.com/">Cryptographic Key Length Recommendation</a>). Also, key length must be a
|
* <a href="http://www.keylength.com/">Cryptographic Key Length Recommendation</a>). Also, key length must be a
|
||||||
* multiplicity of 8.</p>
|
* multiplicity of 8.</p>
|
||||||
* <h3>ElGamal</h3>
|
* <h3>ElGamal</h3>
|
||||||
* <p>For ElGamal algorithm, supported key lengths are 1536, 2048, 3072, 4096 or 8192 bits.</p>
|
* <p>For ElGamal algorithm, supported key lengths are 2048, 3072, 4096 or 8192 bits.</p>
|
||||||
* <h3>DSA</h3>
|
* <h3>DSA</h3>
|
||||||
* <p>For DSA algorithm key length must be between 512 and 1024. Also, it must me dividable by 64.</p>
|
* <p>For DSA algorithm key length must be between 2048 and 3072. Also, it must me dividable by 64.</p>
|
||||||
*
|
*
|
||||||
* @return correct key length, according to SpongyCastle specification. Returns <code>-1</code>, if key length is
|
* @return correct key length, according to SpongyCastle specification. Returns <code>-1</code>, if key length is
|
||||||
* inappropriate.
|
* inappropriate.
|
||||||
*/
|
*/
|
||||||
private int getProperKeyLength(Algorithm algorithm, int currentKeyLength) {
|
private int getProperKeyLength(Algorithm algorithm, int currentKeyLength) {
|
||||||
final int[] elGamalSupportedLengths = {1536, 2048, 3072, 4096, 8192};
|
final int[] elGamalSupportedLengths = {2048, 3072, 4096, 8192};
|
||||||
int properKeyLength = -1;
|
int properKeyLength = -1;
|
||||||
switch (algorithm) {
|
switch (algorithm) {
|
||||||
case RSA:
|
case RSA: {
|
||||||
if (currentKeyLength > 1024 && currentKeyLength <= 16384) {
|
if (currentKeyLength >= 2048 && currentKeyLength <= 16384) {
|
||||||
properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8);
|
properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ELGAMAL:
|
}
|
||||||
|
case ELGAMAL: {
|
||||||
int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length];
|
int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length];
|
||||||
for (int i = 0; i < elGamalSupportedLengths.length; i++) {
|
for (int i = 0; i < elGamalSupportedLengths.length; i++) {
|
||||||
elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength);
|
elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength);
|
||||||
@@ -386,11 +386,14 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
properKeyLength = elGamalSupportedLengths[minimalIndex];
|
properKeyLength = elGamalSupportedLengths[minimalIndex];
|
||||||
break;
|
break;
|
||||||
case DSA:
|
}
|
||||||
if (currentKeyLength >= 512 && currentKeyLength <= 1024) {
|
case DSA: {
|
||||||
|
// Bouncy Castle supports 4096 maximum
|
||||||
|
if (currentKeyLength >= 2048 && currentKeyLength <= 4096) {
|
||||||
properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64);
|
properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return properKeyLength;
|
return properKeyLength;
|
||||||
}
|
}
|
||||||
@@ -424,7 +427,7 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
|||||||
final ArrayAdapter<CharSequence> keySizeAdapter = (ArrayAdapter<CharSequence>) mKeySizeSpinner.getAdapter();
|
final ArrayAdapter<CharSequence> keySizeAdapter = (ArrayAdapter<CharSequence>) mKeySizeSpinner.getAdapter();
|
||||||
keySizeAdapter.clear();
|
keySizeAdapter.clear();
|
||||||
switch (algorithm) {
|
switch (algorithm) {
|
||||||
case RSA:
|
case RSA: {
|
||||||
replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values);
|
replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values);
|
||||||
mKeySizeSpinner.setSelection(1);
|
mKeySizeSpinner.setSelection(1);
|
||||||
mKeySizeRow.setVisibility(View.VISIBLE);
|
mKeySizeRow.setVisibility(View.VISIBLE);
|
||||||
@@ -450,7 +453,8 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
mFlagAuthenticate.setChecked(false);
|
mFlagAuthenticate.setChecked(false);
|
||||||
break;
|
break;
|
||||||
case ELGAMAL:
|
}
|
||||||
|
case ELGAMAL: {
|
||||||
replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values);
|
replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values);
|
||||||
mKeySizeSpinner.setSelection(3);
|
mKeySizeSpinner.setSelection(3);
|
||||||
mKeySizeRow.setVisibility(View.VISIBLE);
|
mKeySizeRow.setVisibility(View.VISIBLE);
|
||||||
@@ -466,7 +470,8 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
|||||||
mFlagAuthenticate.setChecked(false);
|
mFlagAuthenticate.setChecked(false);
|
||||||
mFlagAuthenticate.setEnabled(false);
|
mFlagAuthenticate.setEnabled(false);
|
||||||
break;
|
break;
|
||||||
case DSA:
|
}
|
||||||
|
case DSA: {
|
||||||
replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values);
|
replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values);
|
||||||
mKeySizeSpinner.setSelection(2);
|
mKeySizeSpinner.setSelection(2);
|
||||||
mKeySizeRow.setVisibility(View.VISIBLE);
|
mKeySizeRow.setVisibility(View.VISIBLE);
|
||||||
@@ -482,7 +487,8 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
|||||||
mFlagAuthenticate.setChecked(false);
|
mFlagAuthenticate.setChecked(false);
|
||||||
mFlagAuthenticate.setEnabled(false);
|
mFlagAuthenticate.setEnabled(false);
|
||||||
break;
|
break;
|
||||||
case ECDSA:
|
}
|
||||||
|
case ECDSA: {
|
||||||
mKeySizeRow.setVisibility(View.GONE);
|
mKeySizeRow.setVisibility(View.GONE);
|
||||||
mCurveRow.setVisibility(View.VISIBLE);
|
mCurveRow.setVisibility(View.VISIBLE);
|
||||||
mCustomKeyInfoTextView.setText("");
|
mCustomKeyInfoTextView.setText("");
|
||||||
@@ -496,7 +502,8 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
|||||||
mFlagAuthenticate.setEnabled(true);
|
mFlagAuthenticate.setEnabled(true);
|
||||||
mFlagAuthenticate.setChecked(false);
|
mFlagAuthenticate.setChecked(false);
|
||||||
break;
|
break;
|
||||||
case ECDH:
|
}
|
||||||
|
case ECDH: {
|
||||||
mKeySizeRow.setVisibility(View.GONE);
|
mKeySizeRow.setVisibility(View.GONE);
|
||||||
mCurveRow.setVisibility(View.VISIBLE);
|
mCurveRow.setVisibility(View.VISIBLE);
|
||||||
mCustomKeyInfoTextView.setText("");
|
mCustomKeyInfoTextView.setText("");
|
||||||
@@ -510,6 +517,7 @@ public class AddSubkeyDialogFragment extends DialogFragment {
|
|||||||
mFlagAuthenticate.setChecked(false);
|
mFlagAuthenticate.setChecked(false);
|
||||||
mFlagAuthenticate.setEnabled(false);
|
mFlagAuthenticate.setEnabled(false);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
keySizeAdapter.notifyDataSetChanged();
|
keySizeAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.sufficientlysecure.keychain.ui.dialog;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.view.ContextThemeWrapper;
|
||||||
|
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
|
||||||
|
|
||||||
|
public class ShareLogDialogFragment extends DialogFragment {
|
||||||
|
private static final String ARG_STREAM = "stream";
|
||||||
|
|
||||||
|
public static ShareLogDialogFragment newInstance(Uri stream) {
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putParcelable(ARG_STREAM, stream);
|
||||||
|
|
||||||
|
ShareLogDialogFragment fragment = new ShareLogDialogFragment();
|
||||||
|
fragment.setArguments(args);
|
||||||
|
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
final Uri stream = getArguments().getParcelable(ARG_STREAM);
|
||||||
|
|
||||||
|
ContextThemeWrapper theme = ThemeChanger.getDialogThemeWrapper(getActivity());
|
||||||
|
|
||||||
|
CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(theme);
|
||||||
|
builder.setTitle(R.string.share_log_dialog_title)
|
||||||
|
.setMessage(R.string.share_log_dialog_message)
|
||||||
|
.setNegativeButton(R.string.share_log_dialog_cancel_button,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setPositiveButton(R.string.share_log_dialog_share_button,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dismiss();
|
||||||
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
|
intent.putExtra(Intent.EXTRA_STREAM, stream);
|
||||||
|
intent.setType("text/plain");
|
||||||
|
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.sufficientlysecure.keychain.util;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.LabeledIntent;
|
|
||||||
import android.content.pm.ResolveInfo;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ShareHelper {
|
|
||||||
Context mContext;
|
|
||||||
|
|
||||||
public ShareHelper(Context context) {
|
|
||||||
mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create Intent Chooser but exclude specific activites, e.g., EncryptActivity to prevent encrypting again
|
|
||||||
* <p/>
|
|
||||||
* Put together from some stackoverflow posts...
|
|
||||||
*/
|
|
||||||
public Intent createChooserExcluding(Intent prototype, String title, String[] activityBlacklist) {
|
|
||||||
// Produced an empty list on Huawei U8860 with Android Version 4.0.3
|
|
||||||
// TODO: test on 4.1, 4.2, 4.3, only tested on 4.4
|
|
||||||
// Disabled on 5.0 because using EXTRA_INITIAL_INTENTS prevents the usage based sorting
|
|
||||||
// introduced in 5.0: https://medium.com/@xXxXxXxXxXam/how-lollipops-share-menu-is-organized-d204888f606d
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
return Intent.createChooser(prototype, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<LabeledIntent> targetedShareIntents = new ArrayList<>();
|
|
||||||
|
|
||||||
List<ResolveInfo> resInfoList = mContext.getPackageManager().queryIntentActivities(prototype, 0);
|
|
||||||
List<ResolveInfo> resInfoListFiltered = new ArrayList<>();
|
|
||||||
if (!resInfoList.isEmpty()) {
|
|
||||||
for (ResolveInfo resolveInfo : resInfoList) {
|
|
||||||
// do not add blacklisted ones
|
|
||||||
if (resolveInfo.activityInfo == null || Arrays.asList(activityBlacklist).contains(resolveInfo.activityInfo.name))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
resInfoListFiltered.add(resolveInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!resInfoListFiltered.isEmpty()) {
|
|
||||||
// sorting for nice readability
|
|
||||||
Collections.sort(resInfoListFiltered, new Comparator<ResolveInfo>() {
|
|
||||||
@Override
|
|
||||||
public int compare(ResolveInfo first, ResolveInfo second) {
|
|
||||||
String firstName = first.loadLabel(mContext.getPackageManager()).toString();
|
|
||||||
String secondName = second.loadLabel(mContext.getPackageManager()).toString();
|
|
||||||
return firstName.compareToIgnoreCase(secondName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// create the custom intent list
|
|
||||||
for (ResolveInfo resolveInfo : resInfoListFiltered) {
|
|
||||||
Intent targetedShareIntent = (Intent) prototype.clone();
|
|
||||||
targetedShareIntent.setPackage(resolveInfo.activityInfo.packageName);
|
|
||||||
targetedShareIntent.setClassName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
|
|
||||||
|
|
||||||
LabeledIntent lIntent = new LabeledIntent(targetedShareIntent,
|
|
||||||
resolveInfo.activityInfo.packageName,
|
|
||||||
resolveInfo.loadLabel(mContext.getPackageManager()),
|
|
||||||
resolveInfo.activityInfo.icon);
|
|
||||||
targetedShareIntents.add(lIntent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create chooser with only one Intent in it
|
|
||||||
Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), title);
|
|
||||||
// append all other Intents
|
|
||||||
// TODO this line looks wrong?!
|
|
||||||
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
|
|
||||||
return chooserIntent;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallback to Android's default chooser
|
|
||||||
return Intent.createChooser(prototype, title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -62,6 +62,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:text="@string/btn_back"
|
android:text="@string/btn_back"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
@@ -79,6 +80,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:text="@string/btn_next"
|
android:text="@string/btn_next"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
|
|||||||
@@ -155,6 +155,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:text="@string/btn_back"
|
android:text="@string/btn_back"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
@@ -172,6 +173,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:text="@string/btn_create_key"
|
android:text="@string/btn_create_key"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:text="@string/btn_back"
|
android:text="@string/btn_back"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:text="@string/btn_next"
|
android:text="@string/btn_next"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/btn_back"
|
android:text="@string/btn_back"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
@@ -91,6 +92,7 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/btn_next"
|
android:text="@string/btn_next"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/first_time_import_key"
|
android:text="@string/first_time_import_key"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
@@ -91,6 +92,7 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/btn_do_not_save"
|
android:text="@string/btn_do_not_save"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:text="@string/btn_back"
|
android:text="@string/btn_back"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
@@ -52,8 +53,7 @@
|
|||||||
android:drawablePadding="8dp"
|
android:drawablePadding="8dp"
|
||||||
android:gravity="left|center_vertical"
|
android:gravity="left|center_vertical"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
style="?android:attr/borderlessButtonStyle"
|
style="?android:attr/borderlessButtonStyle" />
|
||||||
android:layout_gravity="center_vertical" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/create_key_next_button"
|
android:id="@+id/create_key_next_button"
|
||||||
@@ -63,6 +63,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:text="@string/first_time_blank_yubikey_yes"
|
android:text="@string/first_time_blank_yubikey_yes"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
@@ -70,7 +71,6 @@
|
|||||||
android:drawablePadding="8dp"
|
android:drawablePadding="8dp"
|
||||||
android:gravity="center_vertical|right"
|
android:gravity="center_vertical|right"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
style="?android:attr/borderlessButtonStyle"
|
style="?android:attr/borderlessButtonStyle" />
|
||||||
android:layout_gravity="center_vertical" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|||||||
@@ -94,6 +94,7 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/btn_back"
|
android:text="@string/btn_back"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
@@ -111,6 +112,7 @@
|
|||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="@string/btn_import"
|
android:text="@string/btn_import"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
|
|||||||
@@ -80,6 +80,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:text="@string/btn_back"
|
android:text="@string/btn_back"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
@@ -97,6 +98,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:text="@string/btn_next"
|
android:text="@string/btn_next"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
|
android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="8dp"
|
||||||
@@ -96,6 +97,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="8dp"
|
||||||
android:drawableRight="@drawable/ic_chevron_right_grey_24dp"
|
android:drawableRight="@drawable/ic_chevron_right_grey_24dp"
|
||||||
|
|||||||
@@ -56,27 +56,11 @@
|
|||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
|
android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
|
||||||
android:drawablePadding="8dp"
|
android:drawablePadding="8dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:gravity="left|center_vertical"
|
android:gravity="left|center_vertical"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
style="?android:attr/borderlessButtonStyle" />
|
style="?android:attr/borderlessButtonStyle" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/create_key_next_button"
|
|
||||||
android:paddingLeft="16dp"
|
|
||||||
android:paddingRight="16dp"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/btn_next"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
|
||||||
android:drawableRight="@drawable/yubi_icon_24dp"
|
|
||||||
android:drawablePadding="16dp"
|
|
||||||
android:gravity="right|center_vertical"
|
|
||||||
android:clickable="false"
|
|
||||||
style="?android:attr/borderlessButtonStyle" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|||||||
@@ -922,7 +922,7 @@
|
|||||||
<string name="msg_cr_error_no_user_id">Schlüsselbünde müssen mindestens eine User-ID enthalten!</string>
|
<string name="msg_cr_error_no_user_id">Schlüsselbünde müssen mindestens eine User-ID enthalten!</string>
|
||||||
<string name="msg_cr_error_no_certify">Hauptschlüssel benötigt das Attribut beglaubigen!</string>
|
<string name="msg_cr_error_no_certify">Hauptschlüssel benötigt das Attribut beglaubigen!</string>
|
||||||
<string name="msg_cr_error_null_expiry">Ablaufdatum kann bei Schlüsselerstellung nicht \'gleiche wie vorher\' sein. Dies ist ein Programmierfehler, bitte reiche einen Fehlerbericht ein!</string>
|
<string name="msg_cr_error_null_expiry">Ablaufdatum kann bei Schlüsselerstellung nicht \'gleiche wie vorher\' sein. Dies ist ein Programmierfehler, bitte reiche einen Fehlerbericht ein!</string>
|
||||||
<string name="msg_cr_error_keysize_512">Schlüssellänge muss größer/gleich 512 sein!</string>
|
<string name="msg_cr_error_keysize_2048">Schlüssellänge muss größer/gleich 512 sein!</string>
|
||||||
<string name="msg_cr_error_no_curve">Keine Schlüssellänge spezifiziert! Dies ist ein Progammierfehler, bitte reiche einen Fehlerbericht ein!</string>
|
<string name="msg_cr_error_no_curve">Keine Schlüssellänge spezifiziert! Dies ist ein Progammierfehler, bitte reiche einen Fehlerbericht ein!</string>
|
||||||
<string name="msg_cr_error_no_keysize">Keine Elliptische Kurve spezifiziert! Dies ist ein Progammierfehler, bitte reiche einen Fehlerbericht ein!</string>
|
<string name="msg_cr_error_no_keysize">Keine Elliptische Kurve spezifiziert! Dies ist ein Progammierfehler, bitte reiche einen Fehlerbericht ein!</string>
|
||||||
<string name="msg_cr_error_internal_pgp">Interner OpenPGP Fehler!</string>
|
<string name="msg_cr_error_internal_pgp">Interner OpenPGP Fehler!</string>
|
||||||
|
|||||||
@@ -921,7 +921,7 @@
|
|||||||
<string name="msg_cr_error_no_user_id">¡Los juegos de claves tienen que crearse con al menos una identificación de usuario!</string>
|
<string name="msg_cr_error_no_user_id">¡Los juegos de claves tienen que crearse con al menos una identificación de usuario!</string>
|
||||||
<string name="msg_cr_error_no_certify">¡La clave maestra debe tener el indicador de certificado!</string>
|
<string name="msg_cr_error_no_certify">¡La clave maestra debe tener el indicador de certificado!</string>
|
||||||
<string name="msg_cr_error_null_expiry">El periodo hasta la expiración no puede ser \'el mismo que antes\' al crear clave. Esto es un error de programación, ¡por favor consigne un informe de error!</string>
|
<string name="msg_cr_error_null_expiry">El periodo hasta la expiración no puede ser \'el mismo que antes\' al crear clave. Esto es un error de programación, ¡por favor consigne un informe de error!</string>
|
||||||
<string name="msg_cr_error_keysize_512">¡El tamaño de la clave debe ser mayor o igual de 512!</string>
|
<string name="msg_cr_error_keysize_2048">¡El tamaño de la clave debe ser mayor o igual de 512!</string>
|
||||||
<string name="msg_cr_error_no_curve">¡No se especificó tamaño de clave! ¡Esto es un error de programación, por favor consigne un informe de fallo!</string>
|
<string name="msg_cr_error_no_curve">¡No se especificó tamaño de clave! ¡Esto es un error de programación, por favor consigne un informe de fallo!</string>
|
||||||
<string name="msg_cr_error_no_keysize">¡No se especificó curva elíptica! ¡Esto es un error de programación, por favor consigne un informe de fallo!</string>
|
<string name="msg_cr_error_no_keysize">¡No se especificó curva elíptica! ¡Esto es un error de programación, por favor consigne un informe de fallo!</string>
|
||||||
<string name="msg_cr_error_internal_pgp">¡Error OpenPGP interno!</string>
|
<string name="msg_cr_error_internal_pgp">¡Error OpenPGP interno!</string>
|
||||||
|
|||||||
@@ -850,7 +850,7 @@
|
|||||||
<string name="msg_cr_error_no_user_id">Giltza-uztaiak gutxienez erabiltzaile ID batekin sortu behar dira!</string>
|
<string name="msg_cr_error_no_user_id">Giltza-uztaiak gutxienez erabiltzaile ID batekin sortu behar dira!</string>
|
||||||
<string name="msg_cr_error_no_certify">Maisu giltzak egiaztagiri ikurra izan behar du!</string>
|
<string name="msg_cr_error_no_certify">Maisu giltzak egiaztagiri ikurra izan behar du!</string>
|
||||||
<string name="msg_cr_error_null_expiry">Epemuga ezin daiteke giltza sortzea baino \'lehenago\' izan. Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
|
<string name="msg_cr_error_null_expiry">Epemuga ezin daiteke giltza sortzea baino \'lehenago\' izan. Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
|
||||||
<string name="msg_cr_error_keysize_512">Giltza neurria 512 edo handiagoa izan behar da!</string>
|
<string name="msg_cr_error_keysize_2048">Giltza neurria 512 edo handiagoa izan behar da!</string>
|
||||||
<string name="msg_cr_error_no_curve">Ez da giltzaren neurria adierazi! Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
|
<string name="msg_cr_error_no_curve">Ez da giltzaren neurria adierazi! Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
|
||||||
<string name="msg_cr_error_internal_pgp">Barneko OpenPGP akatsa!</string>
|
<string name="msg_cr_error_internal_pgp">Barneko OpenPGP akatsa!</string>
|
||||||
<string name="msg_cr_error_unknown_algo">Algoritmo ezezaguna hautatu da! Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
|
<string name="msg_cr_error_unknown_algo">Algoritmo ezezaguna hautatu da! Hau programazio akats bat da, mesedez agiritu akats jakinarazpen bat!</string>
|
||||||
|
|||||||
@@ -921,7 +921,7 @@
|
|||||||
<string name="msg_cr_error_no_user_id">Les trousseaux doivent être créés avec au moins un ID utilisateur !</string>
|
<string name="msg_cr_error_no_user_id">Les trousseaux doivent être créés avec au moins un ID utilisateur !</string>
|
||||||
<string name="msg_cr_error_no_certify">La clef maîtresse doit avoir le drapeau « certifié » !</string>
|
<string name="msg_cr_error_no_certify">La clef maîtresse doit avoir le drapeau « certifié » !</string>
|
||||||
<string name="msg_cr_error_null_expiry">L\'expiration ne peut pas être « pareille qu\'avant » à la création de la clef. C\'est une erreur du programme, veuillez remplir un rapport de bogue !</string>
|
<string name="msg_cr_error_null_expiry">L\'expiration ne peut pas être « pareille qu\'avant » à la création de la clef. C\'est une erreur du programme, veuillez remplir un rapport de bogue !</string>
|
||||||
<string name="msg_cr_error_keysize_512">La taille de la clef doit être supérieure ou égale à 512 !</string>
|
<string name="msg_cr_error_keysize_2048">La taille de la clef doit être supérieure ou égale à 512 !</string>
|
||||||
<string name="msg_cr_error_no_curve">Aucune taille de clef n\'a été spécifiée ! C\'est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
|
<string name="msg_cr_error_no_curve">Aucune taille de clef n\'a été spécifiée ! C\'est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
|
||||||
<string name="msg_cr_error_no_keysize">Aucune courbe elliptique n\'a été spécifiée ! C\'est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
|
<string name="msg_cr_error_no_keysize">Aucune courbe elliptique n\'a été spécifiée ! C\'est une erreur de programmation, veuillez remplir un rapport de bogue !</string>
|
||||||
<string name="msg_cr_error_internal_pgp">Erreur interne OpenPGP !</string>
|
<string name="msg_cr_error_internal_pgp">Erreur interne OpenPGP !</string>
|
||||||
|
|||||||
@@ -658,7 +658,7 @@ Permetti accesso?\n\nATTENZIONE: Se non sai perche\' questo schermata e\' appars
|
|||||||
<string name="msg_cr_error_no_master">Nessuna opzione della chiave principale specificata!</string>
|
<string name="msg_cr_error_no_master">Nessuna opzione della chiave principale specificata!</string>
|
||||||
<string name="msg_cr_error_no_certify">La chiave principale deve avere la caratteristica di certificazione!</string>
|
<string name="msg_cr_error_no_certify">La chiave principale deve avere la caratteristica di certificazione!</string>
|
||||||
<string name="msg_cr_error_null_expiry">La data di scadenza non può essere \'come prima\' sulla creazione di chiavi. Questo è un errore di programmazione, si prega di inviare una segnalazione di bug!</string>
|
<string name="msg_cr_error_null_expiry">La data di scadenza non può essere \'come prima\' sulla creazione di chiavi. Questo è un errore di programmazione, si prega di inviare una segnalazione di bug!</string>
|
||||||
<string name="msg_cr_error_keysize_512">La grandezza della chiave deve essere di 512bit o maggiore</string>
|
<string name="msg_cr_error_keysize_2048">La grandezza della chiave deve essere di 512bit o maggiore</string>
|
||||||
<string name="msg_cr_error_no_keysize">Nessuna curva ellittica specificata! Questo è un errore di programmazione, per favore invia una segnalazione!</string>
|
<string name="msg_cr_error_no_keysize">Nessuna curva ellittica specificata! Questo è un errore di programmazione, per favore invia una segnalazione!</string>
|
||||||
<!--modifySecretKeyRing-->
|
<!--modifySecretKeyRing-->
|
||||||
<string name="msg_mr">Modifica del portachiavi %s</string>
|
<string name="msg_mr">Modifica del portachiavi %s</string>
|
||||||
|
|||||||
@@ -898,7 +898,7 @@
|
|||||||
<string name="msg_cr_error_no_user_id">鍵輪は最低でも1つのユーザIDの生成が必要です!</string>
|
<string name="msg_cr_error_no_user_id">鍵輪は最低でも1つのユーザIDの生成が必要です!</string>
|
||||||
<string name="msg_cr_error_no_certify">主鍵は検証フラグが必須です!</string>
|
<string name="msg_cr_error_no_certify">主鍵は検証フラグが必須です!</string>
|
||||||
<string name="msg_cr_error_null_expiry">鍵の生成時に期限を\'過去\'とすることはできません。これはプログラムエラーで、バグレポートでファイルを送ってください!</string>
|
<string name="msg_cr_error_null_expiry">鍵の生成時に期限を\'過去\'とすることはできません。これはプログラムエラーで、バグレポートでファイルを送ってください!</string>
|
||||||
<string name="msg_cr_error_keysize_512">鍵サイズは512かそれ以上が必須です!</string>
|
<string name="msg_cr_error_keysize_2048">鍵サイズは512かそれ以上が必須です!</string>
|
||||||
<string name="msg_cr_error_no_curve">鍵サイズが不明です! これはプログラムエラーで、バグレポートでファイルの提出をお願いします!</string>
|
<string name="msg_cr_error_no_curve">鍵サイズが不明です! これはプログラムエラーで、バグレポートでファイルの提出をお願いします!</string>
|
||||||
<string name="msg_cr_error_no_keysize">楕円暗号が不明です! これはプログラムエラーで、バグレポートでファイルの提出をお願いします!</string>
|
<string name="msg_cr_error_no_keysize">楕円暗号が不明です! これはプログラムエラーで、バグレポートでファイルの提出をお願いします!</string>
|
||||||
<string name="msg_cr_error_internal_pgp">PGP内部エラー!</string>
|
<string name="msg_cr_error_internal_pgp">PGP内部エラー!</string>
|
||||||
|
|||||||
@@ -877,7 +877,7 @@
|
|||||||
<string name="msg_cr_error_no_user_id">Sleutelbossen moeten met minstens een gebruikers-ID aangemaakt worden!</string>
|
<string name="msg_cr_error_no_user_id">Sleutelbossen moeten met minstens een gebruikers-ID aangemaakt worden!</string>
|
||||||
<string name="msg_cr_error_no_certify">Hoofdsleutel moet certificeer-vlag hebben!</string>
|
<string name="msg_cr_error_no_certify">Hoofdsleutel moet certificeer-vlag hebben!</string>
|
||||||
<string name="msg_cr_error_null_expiry">Verloopdatum kan niet hetzelfde als voordien zijn bij aanmaken van een sleutel. Dit is een bug, gelieve een verslag in te dienen!</string>
|
<string name="msg_cr_error_null_expiry">Verloopdatum kan niet hetzelfde als voordien zijn bij aanmaken van een sleutel. Dit is een bug, gelieve een verslag in te dienen!</string>
|
||||||
<string name="msg_cr_error_keysize_512">Sleutelgrootte moet groter dan of gelijk zijn aan 512!</string>
|
<string name="msg_cr_error_keysize_2048">Sleutelgrootte moet groter dan of gelijk zijn aan 512!</string>
|
||||||
<string name="msg_cr_error_no_curve">Geen sleutelgrootte opgegeven! Dit is een bug, gelieve een verslag in te dienen!</string>
|
<string name="msg_cr_error_no_curve">Geen sleutelgrootte opgegeven! Dit is een bug, gelieve een verslag in te dienen!</string>
|
||||||
<string name="msg_cr_error_no_keysize">Geen elliptische curve opgegeven! Dit is een bug, gelieve een verslag in te dienen!</string>
|
<string name="msg_cr_error_no_keysize">Geen elliptische curve opgegeven! Dit is een bug, gelieve een verslag in te dienen!</string>
|
||||||
<string name="msg_cr_error_internal_pgp">Interne OpenPGP-fout!</string>
|
<string name="msg_cr_error_internal_pgp">Interne OpenPGP-fout!</string>
|
||||||
|
|||||||
@@ -768,7 +768,7 @@
|
|||||||
<string name="msg_cr_error_no_user_id">Связки должны создаваться с хотя бы одним ID пользователя!</string>
|
<string name="msg_cr_error_no_user_id">Связки должны создаваться с хотя бы одним ID пользователя!</string>
|
||||||
<string name="msg_cr_error_no_certify">Основной ключ должен иметь флаг сертификата!</string>
|
<string name="msg_cr_error_no_certify">Основной ключ должен иметь флаг сертификата!</string>
|
||||||
<string name="msg_cr_error_null_expiry">Срок годности не может быть \'такой же как раньше\' при создании ключа. Это программная ошибка, пожалуйста, сообщите об этом!</string>
|
<string name="msg_cr_error_null_expiry">Срок годности не может быть \'такой же как раньше\' при создании ключа. Это программная ошибка, пожалуйста, сообщите об этом!</string>
|
||||||
<string name="msg_cr_error_keysize_512">Размер ключа должен быть больше или равен 512!</string>
|
<string name="msg_cr_error_keysize_2048">Размер ключа должен быть больше или равен 512!</string>
|
||||||
<string name="msg_cr_error_no_curve">Не задан размер ключа! Это программная ошибка, пожалуйста, сообщите об этом!</string>
|
<string name="msg_cr_error_no_curve">Не задан размер ключа! Это программная ошибка, пожалуйста, сообщите об этом!</string>
|
||||||
<string name="msg_cr_error_no_keysize">Не задана эллиптическая кривая! Это программная ошибка, пожалуйста, сообщите об этом!</string>
|
<string name="msg_cr_error_no_keysize">Не задана эллиптическая кривая! Это программная ошибка, пожалуйста, сообщите об этом!</string>
|
||||||
<string name="msg_cr_error_internal_pgp">Внутренняя ошибка OpenPGP!</string>
|
<string name="msg_cr_error_internal_pgp">Внутренняя ошибка OpenPGP!</string>
|
||||||
|
|||||||
@@ -944,7 +944,7 @@
|
|||||||
<string name="msg_cr_error_no_user_id">Привесци морају садржати бар један кориснички ИД!</string>
|
<string name="msg_cr_error_no_user_id">Привесци морају садржати бар један кориснички ИД!</string>
|
||||||
<string name="msg_cr_error_no_certify">Главни кључ мора имати заставицу овере!</string>
|
<string name="msg_cr_error_no_certify">Главни кључ мора имати заставицу овере!</string>
|
||||||
<string name="msg_cr_error_null_expiry">Датум истицања не може бити „исти као пре“ на стварању кључа. Ово је грешка у програмирању, поднесите извештај о грешци!</string>
|
<string name="msg_cr_error_null_expiry">Датум истицања не може бити „исти као пре“ на стварању кључа. Ово је грешка у програмирању, поднесите извештај о грешци!</string>
|
||||||
<string name="msg_cr_error_keysize_512">Величина кључа мора бити већа или једнака 512!</string>
|
<string name="msg_cr_error_keysize_2048">Величина кључа мора бити већа или једнака 512!</string>
|
||||||
<string name="msg_cr_error_no_curve">Није наведена величина кључа! Ово је грешка у програмирању, поднесите извештај о грешци!</string>
|
<string name="msg_cr_error_no_curve">Није наведена величина кључа! Ово је грешка у програмирању, поднесите извештај о грешци!</string>
|
||||||
<string name="msg_cr_error_no_keysize">Није наведена елиптичка крива! Ово је грешка у програмирању, поднесите извештај о грешци!</string>
|
<string name="msg_cr_error_no_keysize">Није наведена елиптичка крива! Ово је грешка у програмирању, поднесите извештај о грешци!</string>
|
||||||
<string name="msg_cr_error_internal_pgp">Унутрашња ОпенПГП грешка!</string>
|
<string name="msg_cr_error_internal_pgp">Унутрашња ОпенПГП грешка!</string>
|
||||||
|
|||||||
@@ -727,7 +727,7 @@
|
|||||||
<string name="msg_cr">Genererar ny huvudnyckel</string>
|
<string name="msg_cr">Genererar ny huvudnyckel</string>
|
||||||
<string name="msg_cr_error_no_user_id">Nyckelringar måste skapas med minst ett användar-ID!</string>
|
<string name="msg_cr_error_no_user_id">Nyckelringar måste skapas med minst ett användar-ID!</string>
|
||||||
<string name="msg_cr_error_no_certify">Huvudnyckel måste ha en certifieringsflagga!</string>
|
<string name="msg_cr_error_no_certify">Huvudnyckel måste ha en certifieringsflagga!</string>
|
||||||
<string name="msg_cr_error_keysize_512">Nyckelstorlek måste vara större eller lika med 512!</string>
|
<string name="msg_cr_error_keysize_2048">Nyckelstorlek måste vara större eller lika med 512!</string>
|
||||||
<string name="msg_cr_error_internal_pgp">Internt OpenPGP-fel!</string>
|
<string name="msg_cr_error_internal_pgp">Internt OpenPGP-fel!</string>
|
||||||
<string name="msg_cr_error_unknown_algo">Okänd algoritm vald. Detta är ett programmeringsfel, skicka en buggrapport!</string>
|
<string name="msg_cr_error_unknown_algo">Okänd algoritm vald. Detta är ett programmeringsfel, skicka en buggrapport!</string>
|
||||||
<string name="msg_cr_error_flags_dsa">Dåliga nyckelflaggor valda, DSA kan inte användas för kryptering!</string>
|
<string name="msg_cr_error_flags_dsa">Dåliga nyckelflaggor valda, DSA kan inte användas för kryptering!</string>
|
||||||
|
|||||||
@@ -454,7 +454,7 @@
|
|||||||
<string name="msg_cr">Генерується новий основний ключ</string>
|
<string name="msg_cr">Генерується новий основний ключ</string>
|
||||||
<string name="msg_cr_error_no_master">Не вказано параметрів основного ключа!</string>
|
<string name="msg_cr_error_no_master">Не вказано параметрів основного ключа!</string>
|
||||||
<string name="msg_cr_error_no_certify">Основний ключ повинен мати прапорець certify!</string>
|
<string name="msg_cr_error_no_certify">Основний ключ повинен мати прапорець certify!</string>
|
||||||
<string name="msg_cr_error_keysize_512">Розмір ключа має бути більшим або рівним 512!</string>
|
<string name="msg_cr_error_keysize_2048">Розмір ключа має бути більшим або рівним 512!</string>
|
||||||
<!--modifySecretKeyRing-->
|
<!--modifySecretKeyRing-->
|
||||||
<string name="msg_mr">Змінюється в\'язка %s</string>
|
<string name="msg_mr">Змінюється в\'язка %s</string>
|
||||||
<string name="msg_mf_error_encode">Виняток шифрування!</string>
|
<string name="msg_mf_error_encode">Виняток шифрування!</string>
|
||||||
|
|||||||
@@ -48,17 +48,15 @@
|
|||||||
<item>@string/key_size_custom</item>
|
<item>@string/key_size_custom</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="elgamal_key_size_spinner_values" translatable="false">
|
<string-array name="elgamal_key_size_spinner_values" translatable="false">
|
||||||
<item>@string/key_size_1536</item>
|
|
||||||
<item>@string/key_size_2048</item>
|
<item>@string/key_size_2048</item>
|
||||||
<item>@string/key_size_3072</item>
|
<item>@string/key_size_3072</item>
|
||||||
<item>@string/key_size_4096</item>
|
<item>@string/key_size_4096</item>
|
||||||
<item>@string/key_size_8192</item>
|
<item>@string/key_size_8192</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="dsa_key_size_spinner_values" translatable="false">
|
<string-array name="dsa_key_size_spinner_values" translatable="false">
|
||||||
<item>@string/key_size_512</item>
|
<item>@string/key_size_2048</item>
|
||||||
<item>@string/key_size_768</item>
|
<item>@string/key_size_3072</item>
|
||||||
<item>@string/key_size_1024</item>
|
<item>@string/key_size_4096</item>
|
||||||
<item>@string/key_size_custom</item>
|
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="theme_entries" translatable="false">
|
<string-array name="theme_entries" translatable="false">
|
||||||
|
|||||||
@@ -437,7 +437,6 @@
|
|||||||
<string name="progress_decrypting">"decrypting data…"</string>
|
<string name="progress_decrypting">"decrypting data…"</string>
|
||||||
<string name="progress_preparing_signature">"preparing signature…"</string>
|
<string name="progress_preparing_signature">"preparing signature…"</string>
|
||||||
<string name="progress_generating_signature">"generating signature…"</string>
|
<string name="progress_generating_signature">"generating signature…"</string>
|
||||||
<string name="progress_processing_signature">"processing signature…"</string>
|
|
||||||
<string name="progress_verifying_signature">"verifying signature…"</string>
|
<string name="progress_verifying_signature">"verifying signature…"</string>
|
||||||
<string name="progress_signing">"signing…"</string>
|
<string name="progress_signing">"signing…"</string>
|
||||||
<string name="progress_certifying">"certifying…"</string>
|
<string name="progress_certifying">"certifying…"</string>
|
||||||
@@ -459,10 +458,6 @@
|
|||||||
<string name="hint_cloud_search_hint">"Search via Name, Email…"</string>
|
<string name="hint_cloud_search_hint">"Search via Name, Email…"</string>
|
||||||
|
|
||||||
<!-- key bit length selections -->
|
<!-- key bit length selections -->
|
||||||
<string name="key_size_512">"512"</string>
|
|
||||||
<string name="key_size_768">"768"</string>
|
|
||||||
<string name="key_size_1024">"1024"</string>
|
|
||||||
<string name="key_size_1536">"1536"</string>
|
|
||||||
<string name="key_size_2048">"2048"</string>
|
<string name="key_size_2048">"2048"</string>
|
||||||
<string name="key_size_3072">"3072"</string>
|
<string name="key_size_3072">"3072"</string>
|
||||||
<string name="key_size_4096">"4096"</string>
|
<string name="key_size_4096">"4096"</string>
|
||||||
@@ -1030,7 +1025,7 @@
|
|||||||
<string name="msg_cr_error_no_user_id">"Keyrings must be created with at least one user ID!"</string>
|
<string name="msg_cr_error_no_user_id">"Keyrings must be created with at least one user ID!"</string>
|
||||||
<string name="msg_cr_error_no_certify">"Master key must have certify flag!"</string>
|
<string name="msg_cr_error_no_certify">"Master key must have certify flag!"</string>
|
||||||
<string name="msg_cr_error_null_expiry">"Expiry time cannot be 'same as before' on key creation. This is a programming error, please file a bug report!"</string>
|
<string name="msg_cr_error_null_expiry">"Expiry time cannot be 'same as before' on key creation. This is a programming error, please file a bug report!"</string>
|
||||||
<string name="msg_cr_error_keysize_512">"Key size must be greater or equal 512!"</string>
|
<string name="msg_cr_error_keysize_2048">"Key size must be greater or equal 2048!"</string>
|
||||||
<string name="msg_cr_error_no_curve">"No key size specified! This is a programming error, please file a bug report!"</string>
|
<string name="msg_cr_error_no_curve">"No key size specified! This is a programming error, please file a bug report!"</string>
|
||||||
<string name="msg_cr_error_no_keysize">"No elliptic curve specified! This is a programming error, please file a bug report!"</string>
|
<string name="msg_cr_error_no_keysize">"No elliptic curve specified! This is a programming error, please file a bug report!"</string>
|
||||||
<string name="msg_cr_error_internal_pgp">"Internal OpenPGP error!"</string>
|
<string name="msg_cr_error_internal_pgp">"Internal OpenPGP error!"</string>
|
||||||
@@ -1179,6 +1174,7 @@
|
|||||||
<string name="msg_dc_error_input">"Error opening input data stream!"</string>
|
<string name="msg_dc_error_input">"Error opening input data stream!"</string>
|
||||||
<string name="msg_dc_error_no_data">"No encrypted data found in stream!"</string>
|
<string name="msg_dc_error_no_data">"No encrypted data found in stream!"</string>
|
||||||
<string name="msg_dc_error_no_key">"No encrypted data with known secret key found in stream!"</string>
|
<string name="msg_dc_error_no_key">"No encrypted data with known secret key found in stream!"</string>
|
||||||
|
<string name="msg_dc_error_no_signature">"Missing signature data!"</string>
|
||||||
<string name="msg_dc_error_pgp_exception">"Encountered OpenPGP Exception during operation!"</string>
|
<string name="msg_dc_error_pgp_exception">"Encountered OpenPGP Exception during operation!"</string>
|
||||||
<string name="msg_dc_integrity_check_ok">"Integrity check OK!"</string>
|
<string name="msg_dc_integrity_check_ok">"Integrity check OK!"</string>
|
||||||
<string name="msg_dc_ok_meta_only">"Only metadata was requested, skipping decryption"</string>
|
<string name="msg_dc_ok_meta_only">"Only metadata was requested, skipping decryption"</string>
|
||||||
@@ -1202,8 +1198,9 @@
|
|||||||
|
|
||||||
<!-- Messages for VerifySignedLiteralData operation -->
|
<!-- Messages for VerifySignedLiteralData operation -->
|
||||||
<string name="msg_vl">"Starting signature check"</string>
|
<string name="msg_vl">"Starting signature check"</string>
|
||||||
<string name="msg_vl_error_no_siglist">"No signature list in signed literal data"</string>
|
<string name="msg_vl_error_no_siglist">"No signature list in signed literal data!"</string>
|
||||||
<string name="msg_vl_error_wrong_key">"Message not signed with right key"</string>
|
<string name="msg_vl_error_wrong_key">"Message not signed with expected key!"</string>
|
||||||
|
<string name="msg_vl_error_no_signature">"Missing signature data!"</string>
|
||||||
<string name="msg_vl_error_missing_literal">"No payload in signed literal data"</string>
|
<string name="msg_vl_error_missing_literal">"No payload in signed literal data"</string>
|
||||||
<string name="msg_vl_clear_meta_file">"Filename: %s"</string>
|
<string name="msg_vl_clear_meta_file">"Filename: %s"</string>
|
||||||
<string name="msg_vl_clear_meta_mime">"MIME type: %s"</string>
|
<string name="msg_vl_clear_meta_mime">"MIME type: %s"</string>
|
||||||
@@ -1225,7 +1222,6 @@
|
|||||||
|
|
||||||
<!-- Messages for PgpSignEncrypt operation -->
|
<!-- Messages for PgpSignEncrypt operation -->
|
||||||
<string name="msg_pse_asymmetric">"Preparing public keys for encryption"</string>
|
<string name="msg_pse_asymmetric">"Preparing public keys for encryption"</string>
|
||||||
<string name="msg_pse_clearsign_only">"Signing of cleartext input not supported!"</string>
|
|
||||||
<string name="msg_pse_compressing">"Preparing compression"</string>
|
<string name="msg_pse_compressing">"Preparing compression"</string>
|
||||||
<string name="msg_pse_encrypting">"Encrypting data"</string>
|
<string name="msg_pse_encrypting">"Encrypting data"</string>
|
||||||
<string name="msg_pse_error_bad_passphrase">"Bad password!"</string>
|
<string name="msg_pse_error_bad_passphrase">"Bad password!"</string>
|
||||||
@@ -1660,4 +1656,9 @@
|
|||||||
<string name="snack_backup_saved_dir">"Saved to OpenKeychain directory"</string>
|
<string name="snack_backup_saved_dir">"Saved to OpenKeychain directory"</string>
|
||||||
<string name="btn_backup_back">Go back to check</string>
|
<string name="btn_backup_back">Go back to check</string>
|
||||||
|
|
||||||
|
<string name="share_log_dialog_title">"Share log?"</string>
|
||||||
|
<string name="share_log_dialog_message">"While logs can be super helpful for developers to find bugs in OpenKeychain, they can contain potential sensitive information such as data about the updated keys. Please make sure you are okay with sharing this information."</string>
|
||||||
|
<string name="share_log_dialog_share_button">"Share"</string>
|
||||||
|
<string name="share_log_dialog_cancel_button">"Cancel"</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -78,11 +78,11 @@ public class CertifyOperationTest {
|
|||||||
{
|
{
|
||||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
Algorithm.RSA, 2048, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.DSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
|
Algorithm.DSA, 2048, null, KeyFlags.SIGN_DATA, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
Algorithm.ELGAMAL, 2048, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
||||||
parcel.mAddUserIds.add("derp");
|
parcel.mAddUserIds.add("derp");
|
||||||
parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);
|
parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);
|
||||||
|
|
||||||
@@ -96,11 +96,11 @@ public class CertifyOperationTest {
|
|||||||
{
|
{
|
||||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
Algorithm.RSA, 2048, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.DSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
|
Algorithm.DSA, 2048, null, KeyFlags.SIGN_DATA, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
Algorithm.ELGAMAL, 2048, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
||||||
|
|
||||||
parcel.mAddUserIds.add("ditz");
|
parcel.mAddUserIds.add("ditz");
|
||||||
byte[] uatdata = new byte[random.nextInt(150)+10];
|
byte[] uatdata = new byte[random.nextInt(150)+10];
|
||||||
|
|||||||
@@ -100,11 +100,11 @@ public class ExportTest {
|
|||||||
{
|
{
|
||||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
Algorithm.RSA, 2048, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.DSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
|
Algorithm.DSA, 2048, null, KeyFlags.SIGN_DATA, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
Algorithm.ELGAMAL, 2048, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
||||||
parcel.mAddUserIds.add("snips");
|
parcel.mAddUserIds.add("snips");
|
||||||
parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);
|
parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);
|
||||||
|
|
||||||
@@ -118,11 +118,11 @@ public class ExportTest {
|
|||||||
{
|
{
|
||||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
Algorithm.RSA, 2048, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.DSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
|
Algorithm.DSA, 2048, null, KeyFlags.SIGN_DATA, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
Algorithm.ELGAMAL, 2048, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
||||||
parcel.mAddUserIds.add("snails");
|
parcel.mAddUserIds.add("snails");
|
||||||
parcel.mNewUnlock = new ChangeUnlockParcel(null, new Passphrase("1234"));
|
parcel.mNewUnlock = new ChangeUnlockParcel(null, new Passphrase("1234"));
|
||||||
|
|
||||||
|
|||||||
@@ -74,11 +74,11 @@ public class PromoteKeyOperationTest {
|
|||||||
{
|
{
|
||||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
Algorithm.RSA, 2048, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.DSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
|
Algorithm.DSA, 2048, null, KeyFlags.SIGN_DATA, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
Algorithm.ELGAMAL, 2048, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
||||||
parcel.mAddUserIds.add("derp");
|
parcel.mAddUserIds.add("derp");
|
||||||
parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);
|
parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhrase1);
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import java.util.Date;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.util.StringUtils;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
@@ -77,7 +78,7 @@ public class PgpEncryptDecryptTest {
|
|||||||
static UncachedKeyRing mStaticRing1, mStaticRing2, mStaticRingInsecure;
|
static UncachedKeyRing mStaticRing1, mStaticRing2, mStaticRingInsecure;
|
||||||
static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true);
|
static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true);
|
||||||
static Passphrase mKeyPhrase2 = TestingUtils.genPassphrase(true);
|
static Passphrase mKeyPhrase2 = TestingUtils.genPassphrase(true);
|
||||||
static Passphrase mKeyPhraseInsecure = TestingUtils.genPassphrase(true);
|
// static Passphrase mKeyPhraseInsecure = TestingUtils.genPassphrase(true);
|
||||||
|
|
||||||
static PrintStream oldShadowStream;
|
static PrintStream oldShadowStream;
|
||||||
|
|
||||||
@@ -127,24 +128,24 @@ public class PgpEncryptDecryptTest {
|
|||||||
mStaticRing2 = result.getRing();
|
mStaticRing2 = result.getRing();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// {
|
||||||
// insecure (1024 bit) RSA key
|
// // insecure (1024 bit) RSA key
|
||||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
// SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
// parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
// Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
// parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
|
// Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
// parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
// Algorithm.RSA, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
||||||
parcel.mAddUserIds.add("eve");
|
// parcel.mAddUserIds.add("eve");
|
||||||
parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhraseInsecure);
|
// parcel.mNewUnlock = new ChangeUnlockParcel(mKeyPhraseInsecure);
|
||||||
|
//
|
||||||
PgpEditKeyResult result = op.createSecretKeyRing(parcel);
|
// PgpEditKeyResult result = op.createSecretKeyRing(parcel);
|
||||||
Assert.assertTrue("initial test key creation must succeed", result.success());
|
// Assert.assertTrue("initial test key creation must succeed", result.success());
|
||||||
Assert.assertNotNull("initial test key creation must succeed", result.getRing());
|
// Assert.assertNotNull("initial test key creation must succeed", result.getRing());
|
||||||
|
//
|
||||||
mStaticRingInsecure = result.getRing();
|
// mStaticRingInsecure = result.getRing();
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +288,7 @@ public class PgpEncryptDecryptTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAsymmetricSign() {
|
public void testAsymmetricSignLiteral() {
|
||||||
|
|
||||||
String plaintext = "dies ist ein plaintext ☭" + TestingUtils.genPassphrase(true);
|
String plaintext = "dies ist ein plaintext ☭" + TestingUtils.genPassphrase(true);
|
||||||
byte[] ciphertext;
|
byte[] ciphertext;
|
||||||
@@ -340,6 +341,121 @@ public class PgpEncryptDecryptTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAsymmetricSignCleartext() {
|
||||||
|
|
||||||
|
String plaintext = "dies ist ein\r\nplaintext\n ☭" + TestingUtils.genPassphrase(true);
|
||||||
|
byte[] ciphertext;
|
||||||
|
|
||||||
|
{ // encrypt data with key
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(plaintext.getBytes());
|
||||||
|
|
||||||
|
PgpSignEncryptOperation op = new PgpSignEncryptOperation(RuntimeEnvironment.application,
|
||||||
|
new ProviderHelper(RuntimeEnvironment.application), null);
|
||||||
|
|
||||||
|
InputData data = new InputData(in, in.available());
|
||||||
|
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
|
||||||
|
|
||||||
|
// only sign, as cleartext
|
||||||
|
input.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId());
|
||||||
|
input.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1));
|
||||||
|
input.setCleartextSignature(true);
|
||||||
|
input.setEnableAsciiArmorOutput(true);
|
||||||
|
input.setDetachedSignature(false);
|
||||||
|
|
||||||
|
PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out);
|
||||||
|
Assert.assertTrue("signing must succeed", result.success());
|
||||||
|
|
||||||
|
ciphertext = out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.assertTrue("clearsigned text must contain plaintext (ignoring newlines)",
|
||||||
|
new String(ciphertext).replace("\r\n", "").contains(plaintext.replace("\r", "").replace("\n", "")));
|
||||||
|
|
||||||
|
{ // verification should succeed
|
||||||
|
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(ciphertext);
|
||||||
|
InputData data = new InputData(in, in.available());
|
||||||
|
|
||||||
|
PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(null, null, null);
|
||||||
|
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
|
||||||
|
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
|
||||||
|
|
||||||
|
Assert.assertTrue("verification must succeed", result.success());
|
||||||
|
|
||||||
|
Assert.assertTrue("verification text should equal plaintext (ignoring newlines)",
|
||||||
|
new String(out.toByteArray()).replace(StringUtils.LINE_SEP, "")
|
||||||
|
.equals(plaintext.replace("\r", "").replace("\n", "")));
|
||||||
|
Assert.assertEquals("decryptionResult should be RESULT_NOT_ENCRYPTED",
|
||||||
|
OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED, result.getDecryptionResult().getResult());
|
||||||
|
Assert.assertEquals("signatureResult should be RESULT_VALID_CONFIRMED",
|
||||||
|
OpenPgpSignatureResult.RESULT_VALID_CONFIRMED, result.getSignatureResult().getResult());
|
||||||
|
|
||||||
|
OpenPgpMetadata metadata = result.getDecryptionMetadata();
|
||||||
|
Assert.assertEquals("filesize must be correct",
|
||||||
|
out.toByteArray().length, metadata.getOriginalSize());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAsymmetricSignDetached() {
|
||||||
|
|
||||||
|
String plaintext = "dies ist ein plaintext ☭" + TestingUtils.genPassphrase(true);
|
||||||
|
byte[] detachedSignature;
|
||||||
|
|
||||||
|
{ // encrypt data with key
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(plaintext.getBytes());
|
||||||
|
|
||||||
|
PgpSignEncryptOperation op = new PgpSignEncryptOperation(RuntimeEnvironment.application,
|
||||||
|
new ProviderHelper(RuntimeEnvironment.application), null);
|
||||||
|
|
||||||
|
InputData data = new InputData(in, in.available());
|
||||||
|
PgpSignEncryptInputParcel input = new PgpSignEncryptInputParcel();
|
||||||
|
|
||||||
|
// only sign, as cleartext
|
||||||
|
input.setSignatureMasterKeyId(mStaticRing1.getMasterKeyId());
|
||||||
|
input.setSignatureSubKeyId(KeyringTestingHelper.getSubkeyId(mStaticRing1, 1));
|
||||||
|
input.setDetachedSignature(true);
|
||||||
|
|
||||||
|
PgpSignEncryptResult result = op.execute(input, new CryptoInputParcel(mKeyPhrase1), data, out);
|
||||||
|
Assert.assertTrue("signing must succeed", result.success());
|
||||||
|
|
||||||
|
detachedSignature = result.getDetachedSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // verification should succeed
|
||||||
|
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(plaintext.getBytes());
|
||||||
|
InputData data = new InputData(in, in.available());
|
||||||
|
|
||||||
|
PgpDecryptVerifyOperation op = operationWithFakePassphraseCache(null, null, null);
|
||||||
|
PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel();
|
||||||
|
input.setDetachedSignature(detachedSignature);
|
||||||
|
DecryptVerifyResult result = op.execute(input, new CryptoInputParcel(), data, out);
|
||||||
|
|
||||||
|
Assert.assertTrue("verification must succeed", result.success());
|
||||||
|
Assert.assertArrayEquals("verification text should equal plaintext (save for a newline)",
|
||||||
|
plaintext.getBytes(), out.toByteArray());
|
||||||
|
Assert.assertEquals("decryptionResult should be RESULT_NOT_ENCRYPTED",
|
||||||
|
OpenPgpDecryptionResult.RESULT_NOT_ENCRYPTED, result.getDecryptionResult().getResult());
|
||||||
|
Assert.assertEquals("signatureResult should be RESULT_VALID_CONFIRMED",
|
||||||
|
OpenPgpSignatureResult.RESULT_VALID_CONFIRMED, result.getSignatureResult().getResult());
|
||||||
|
|
||||||
|
// TODO should detached verify return any metadata?
|
||||||
|
// OpenPgpMetadata metadata = result.getDecryptionMetadata();
|
||||||
|
// Assert.assertEquals("filesize must be correct",
|
||||||
|
// out.toByteArray().length, metadata.getOriginalSize());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAsymmetricEncryptDecrypt() {
|
public void testAsymmetricEncryptDecrypt() {
|
||||||
|
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ public class PgpKeyOperationTest {
|
|||||||
UncachedKeyRing ring;
|
UncachedKeyRing ring;
|
||||||
PgpKeyOperation op;
|
PgpKeyOperation op;
|
||||||
SaveKeyringParcel parcel;
|
SaveKeyringParcel parcel;
|
||||||
ArrayList<RawPacket> onlyA = new ArrayList<RawPacket>();
|
ArrayList<RawPacket> onlyA = new ArrayList<>();
|
||||||
ArrayList<RawPacket> onlyB = new ArrayList<RawPacket>();
|
ArrayList<RawPacket> onlyB = new ArrayList<>();
|
||||||
|
|
||||||
static CryptoInputParcel cryptoInput;
|
static CryptoInputParcel cryptoInput;
|
||||||
|
|
||||||
@@ -94,11 +94,11 @@ public class PgpKeyOperationTest {
|
|||||||
|
|
||||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.DSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
Algorithm.DSA, 3072, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 2048, null, KeyFlags.SIGN_DATA, 0L));
|
Algorithm.RSA, 2048, null, KeyFlags.SIGN_DATA, 0L));
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
Algorithm.RSA, 3072, null, KeyFlags.ENCRYPT_COMMS, 0L));
|
||||||
|
|
||||||
parcel.mAddUserIds.add("twi");
|
parcel.mAddUserIds.add("twi");
|
||||||
parcel.mAddUserIds.add("pink");
|
parcel.mAddUserIds.add("pink");
|
||||||
@@ -153,13 +153,13 @@ public class PgpKeyOperationTest {
|
|||||||
parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
|
parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
|
||||||
|
|
||||||
assertFailure("creating ring with < 512 bytes keysize should fail", parcel,
|
assertFailure("creating ring with < 512 bytes keysize should fail", parcel,
|
||||||
LogType.MSG_CR_ERROR_KEYSIZE_512);
|
LogType.MSG_CR_ERROR_KEYSIZE_2048);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
parcel.reset();
|
parcel.reset();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.ELGAMAL, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
Algorithm.ELGAMAL, 2048, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||||
parcel.mAddUserIds.add("shy");
|
parcel.mAddUserIds.add("shy");
|
||||||
parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
|
parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ public class PgpKeyOperationTest {
|
|||||||
{
|
{
|
||||||
parcel.reset();
|
parcel.reset();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, null));
|
Algorithm.RSA, 2048, null, KeyFlags.CERTIFY_OTHER, null));
|
||||||
parcel.mAddUserIds.add("lotus");
|
parcel.mAddUserIds.add("lotus");
|
||||||
parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
|
parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ public class PgpKeyOperationTest {
|
|||||||
{
|
{
|
||||||
parcel.reset();
|
parcel.reset();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
|
Algorithm.RSA, 2048, null, KeyFlags.SIGN_DATA, 0L));
|
||||||
parcel.mAddUserIds.add("shy");
|
parcel.mAddUserIds.add("shy");
|
||||||
parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
|
parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ public class PgpKeyOperationTest {
|
|||||||
{
|
{
|
||||||
parcel.reset();
|
parcel.reset();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
Algorithm.RSA, 2048, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||||
parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
|
parcel.mNewUnlock = new ChangeUnlockParcel(passphrase);
|
||||||
|
|
||||||
assertFailure("creating ring without user ids should fail", parcel,
|
assertFailure("creating ring without user ids should fail", parcel,
|
||||||
@@ -216,7 +216,7 @@ public class PgpKeyOperationTest {
|
|||||||
public void testMasterFlags() throws Exception {
|
public void testMasterFlags() throws Exception {
|
||||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA, 0L));
|
Algorithm.RSA, 4096, null, KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA, 0L));
|
||||||
parcel.mAddUserIds.add("luna");
|
parcel.mAddUserIds.add("luna");
|
||||||
ring = assertCreateSuccess("creating ring with master key flags must succeed", parcel);
|
ring = assertCreateSuccess("creating ring with master key flags must succeed", parcel);
|
||||||
|
|
||||||
@@ -256,8 +256,8 @@ public class PgpKeyOperationTest {
|
|||||||
List<UncachedPublicKey> subkeys = KeyringTestingHelper.itToList(ring.getPublicKeys());
|
List<UncachedPublicKey> subkeys = KeyringTestingHelper.itToList(ring.getPublicKeys());
|
||||||
Assert.assertEquals("number of subkeys must be three", 3, subkeys.size());
|
Assert.assertEquals("number of subkeys must be three", 3, subkeys.size());
|
||||||
|
|
||||||
Assert.assertTrue("key ring should have been created in the last 120 seconds",
|
Assert.assertTrue("key ring should have been created in the last 360 seconds",
|
||||||
ring.getPublicKey().getCreationTime().after(new Date(new Date().getTime()-1000*120)));
|
ring.getPublicKey().getCreationTime().after(new Date(new Date().getTime()-1000*360)));
|
||||||
|
|
||||||
Assert.assertNull("key ring should not expire",
|
Assert.assertNull("key ring should not expire",
|
||||||
ring.getPublicKey().getUnsafeExpiryTimeForTesting());
|
ring.getPublicKey().getUnsafeExpiryTimeForTesting());
|
||||||
@@ -347,7 +347,7 @@ public class PgpKeyOperationTest {
|
|||||||
|
|
||||||
long expiry = new Date().getTime() / 1000 + 159;
|
long expiry = new Date().getTime() / 1000 + 159;
|
||||||
int flags = KeyFlags.SIGN_DATA;
|
int flags = KeyFlags.SIGN_DATA;
|
||||||
int bits = 1024 + new Random().nextInt(8);
|
int bits = 2048 + new Random().nextInt(8);
|
||||||
parcel.mAddSubKeys.add(new SubkeyAdd(Algorithm.RSA, bits, null, flags, expiry));
|
parcel.mAddSubKeys.add(new SubkeyAdd(Algorithm.RSA, bits, null, flags, expiry));
|
||||||
|
|
||||||
UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB);
|
UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB);
|
||||||
@@ -391,14 +391,14 @@ public class PgpKeyOperationTest {
|
|||||||
parcel.mAddSubKeys.add(new SubkeyAdd(
|
parcel.mAddSubKeys.add(new SubkeyAdd(
|
||||||
Algorithm.RSA, new Random().nextInt(512), null, KeyFlags.SIGN_DATA, 0L));
|
Algorithm.RSA, new Random().nextInt(512), null, KeyFlags.SIGN_DATA, 0L));
|
||||||
assertModifyFailure("creating a subkey with keysize < 512 should fail", ring, parcel,
|
assertModifyFailure("creating a subkey with keysize < 512 should fail", ring, parcel,
|
||||||
LogType.MSG_CR_ERROR_KEYSIZE_512);
|
LogType.MSG_CR_ERROR_KEYSIZE_2048);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
parcel.reset();
|
parcel.reset();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, null));
|
Algorithm.RSA, 2048, null, KeyFlags.SIGN_DATA, null));
|
||||||
|
|
||||||
assertModifyFailure("creating master key with null expiry should fail", ring, parcel,
|
assertModifyFailure("creating master key with null expiry should fail", ring, parcel,
|
||||||
LogType.MSG_MF_ERROR_NULL_EXPIRY);
|
LogType.MSG_MF_ERROR_NULL_EXPIRY);
|
||||||
@@ -406,7 +406,7 @@ public class PgpKeyOperationTest {
|
|||||||
|
|
||||||
{ // a past expiry should fail
|
{ // a past expiry should fail
|
||||||
parcel.reset();
|
parcel.reset();
|
||||||
parcel.mAddSubKeys.add(new SubkeyAdd(Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA,
|
parcel.mAddSubKeys.add(new SubkeyAdd(Algorithm.RSA, 2048, null, KeyFlags.SIGN_DATA,
|
||||||
new Date().getTime()/1000-10));
|
new Date().getTime()/1000-10));
|
||||||
assertModifyFailure("creating subkey with past expiry date should fail", ring, parcel,
|
assertModifyFailure("creating subkey with past expiry date should fail", ring, parcel,
|
||||||
LogType.MSG_MF_ERROR_PAST_EXPIRY);
|
LogType.MSG_MF_ERROR_PAST_EXPIRY);
|
||||||
@@ -837,7 +837,7 @@ public class PgpKeyOperationTest {
|
|||||||
|
|
||||||
UncachedKeyRing modified;
|
UncachedKeyRing modified;
|
||||||
|
|
||||||
{ // keytocard should fail with BAD_NFC_SIZE when presented with the RSA-1024 key
|
{ // keytocard should fail with BAD_NFC_SIZE when presented with the RSA-3072 key
|
||||||
long keyId = KeyringTestingHelper.getSubkeyId(ring, 2);
|
long keyId = KeyringTestingHelper.getSubkeyId(ring, 2);
|
||||||
parcel.reset();
|
parcel.reset();
|
||||||
parcel.mChangeSubKeys.add(new SubkeyChange(keyId, false, true));
|
parcel.mChangeSubKeys.add(new SubkeyChange(keyId, false, true));
|
||||||
@@ -846,7 +846,7 @@ public class PgpKeyOperationTest {
|
|||||||
parcel, cryptoInput, LogType.MSG_MF_ERROR_BAD_NFC_SIZE);
|
parcel, cryptoInput, LogType.MSG_MF_ERROR_BAD_NFC_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // keytocard should fail with BAD_NFC_ALGO when presented with the DSA-1024 key
|
{ // keytocard should fail with BAD_NFC_ALGO when presented with the DSA-3072 key
|
||||||
long keyId = KeyringTestingHelper.getSubkeyId(ring, 0);
|
long keyId = KeyringTestingHelper.getSubkeyId(ring, 0);
|
||||||
parcel.reset();
|
parcel.reset();
|
||||||
parcel.mChangeSubKeys.add(new SubkeyChange(keyId, false, true));
|
parcel.mChangeSubKeys.add(new SubkeyChange(keyId, false, true));
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ public class UncachedKeyringCanonicalizeTest {
|
|||||||
static UncachedKeyRing staticRing;
|
static UncachedKeyRing staticRing;
|
||||||
static int totalPackets;
|
static int totalPackets;
|
||||||
UncachedKeyRing ring;
|
UncachedKeyRing ring;
|
||||||
ArrayList<RawPacket> onlyA = new ArrayList<RawPacket>();
|
ArrayList<RawPacket> onlyA = new ArrayList<>();
|
||||||
ArrayList<RawPacket> onlyB = new ArrayList<RawPacket>();
|
ArrayList<RawPacket> onlyB = new ArrayList<>();
|
||||||
OperationResult.OperationLog log = new OperationResult.OperationLog();
|
OperationResult.OperationLog log = new OperationResult.OperationLog();
|
||||||
PGPSignatureSubpacketGenerator subHashedPacketsGen;
|
PGPSignatureSubpacketGenerator subHashedPacketsGen;
|
||||||
PGPSecretKey secretKey;
|
PGPSecretKey secretKey;
|
||||||
@@ -358,7 +358,7 @@ public class UncachedKeyringCanonicalizeTest {
|
|||||||
|
|
||||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L));
|
Algorithm.RSA, 2048, null, KeyFlags.CERTIFY_OTHER, 0L));
|
||||||
parcel.mAddUserIds.add("trix");
|
parcel.mAddUserIds.add("trix");
|
||||||
PgpKeyOperation op = new PgpKeyOperation(null);
|
PgpKeyOperation op = new PgpKeyOperation(null);
|
||||||
|
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ public class UncachedKeyringMergeTest {
|
|||||||
|
|
||||||
static UncachedKeyRing staticRingA, staticRingB;
|
static UncachedKeyRing staticRingA, staticRingB;
|
||||||
UncachedKeyRing ringA, ringB;
|
UncachedKeyRing ringA, ringB;
|
||||||
ArrayList<RawPacket> onlyA = new ArrayList<RawPacket>();
|
ArrayList<RawPacket> onlyA = new ArrayList<>();
|
||||||
ArrayList<RawPacket> onlyB = new ArrayList<RawPacket>();
|
ArrayList<RawPacket> onlyB = new ArrayList<>();
|
||||||
OperationResult.OperationLog log = new OperationResult.OperationLog();
|
OperationResult.OperationLog log = new OperationResult.OperationLog();
|
||||||
PgpKeyOperation op;
|
PgpKeyOperation op;
|
||||||
SaveKeyringParcel parcel;
|
SaveKeyringParcel parcel;
|
||||||
@@ -234,7 +234,7 @@ public class UncachedKeyringMergeTest {
|
|||||||
|
|
||||||
parcel.reset();
|
parcel.reset();
|
||||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||||
Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
|
Algorithm.RSA, 2048, null, KeyFlags.SIGN_DATA, 0L));
|
||||||
modifiedA = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Date(), new Passphrase()), parcel).getRing();
|
modifiedA = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Date(), new Passphrase()), parcel).getRing();
|
||||||
modifiedB = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Date(), new Passphrase()), parcel).getRing();
|
modifiedB = op.modifySecretKeyRing(secretRing, new CryptoInputParcel(new Date(), new Passphrase()), parcel).getRing();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user