diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java index ee312aedf..262c83404 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java @@ -36,11 +36,11 @@ import org.spongycastle.bcpg.UserIDPacket; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.jce.provider.BouncyCastleProvider; import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyChange; import org.sufficientlysecure.keychain.support.KeyringBuilder; @@ -78,11 +78,11 @@ public class PgpKeyOperationTest { SaveKeyringParcel parcel = new SaveKeyringParcel(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.CERTIFY_OTHER, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.DSA, 1024, KeyFlags.SIGN_DATA, 0L)); + Algorithm.DSA, 1024, null, KeyFlags.SIGN_DATA, 0L)); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT, 1024, KeyFlags.ENCRYPT_COMMS, 0L)); + Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L)); parcel.mAddUserIds.add("twi"); parcel.mAddUserIds.add("pink"); @@ -120,7 +120,7 @@ public class PgpKeyOperationTest { { parcel.reset(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, new Random().nextInt(256)+255, KeyFlags.CERTIFY_OTHER, 0L)); + Algorithm.RSA, new Random().nextInt(256)+255, null, KeyFlags.CERTIFY_OTHER, 0L)); parcel.mAddUserIds.add("shy"); parcel.mNewPassphrase = passphrase; @@ -131,18 +131,18 @@ public class PgpKeyOperationTest { { parcel.reset(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT, 1024, KeyFlags.CERTIFY_OTHER, 0L)); + Algorithm.ELGAMAL, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); parcel.mAddUserIds.add("shy"); parcel.mNewPassphrase = passphrase; assertFailure("creating ring with ElGamal master key should fail", parcel, - LogType.MSG_CR_ERROR_MASTER_ELGAMAL); + LogType.MSG_CR_ERROR_FLAGS_ELGAMAL); } { parcel.reset(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.CERTIFY_OTHER, null)); + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, null)); parcel.mAddUserIds.add("lotus"); parcel.mNewPassphrase = passphrase; @@ -153,18 +153,7 @@ public class PgpKeyOperationTest { { parcel.reset(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - 12345, 1024, KeyFlags.CERTIFY_OTHER, 0L)); - parcel.mAddUserIds.add("shy"); - parcel.mNewPassphrase = passphrase; - - assertFailure("creating ring with bad algorithm choice should fail", parcel, - LogType.MSG_CR_ERROR_UNKNOWN_ALGO); - } - - { - parcel.reset(); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.SIGN_DATA, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L)); parcel.mAddUserIds.add("shy"); parcel.mNewPassphrase = passphrase; @@ -175,7 +164,7 @@ public class PgpKeyOperationTest { { parcel.reset(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.CERTIFY_OTHER, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); parcel.mNewPassphrase = passphrase; assertFailure("creating ring without user ids should fail", parcel, @@ -199,7 +188,7 @@ public class PgpKeyOperationTest { public void testMasterFlags() throws Exception { SaveKeyringParcel parcel = new SaveKeyringParcel(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA, 0L)); parcel.mAddUserIds.add("luna"); ring = assertCreateSuccess("creating ring with master key flags must succeed", parcel); @@ -313,7 +302,7 @@ public class PgpKeyOperationTest { long expiry = new Date().getTime() / 1000 + 159; int flags = KeyFlags.SIGN_DATA; int bits = 1024 + new Random().nextInt(8); - parcel.mAddSubKeys.add(new SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, bits, flags, expiry)); + parcel.mAddSubKeys.add(new SubkeyAdd(Algorithm.RSA, bits, null, flags, expiry)); UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB); @@ -349,12 +338,12 @@ public class PgpKeyOperationTest { Assert.assertEquals("added key must have expected flags", flags, newKey.getKeyUsage()); Assert.assertEquals("added key must have expected bitsize", - bits, newKey.getBitStrength()); + bits, (int) newKey.getBitStrength()); { // bad keysize should fail parcel.reset(); parcel.mAddSubKeys.add(new SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, new Random().nextInt(512), 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, LogType.MSG_CR_ERROR_KEYSIZE_512); @@ -363,7 +352,7 @@ public class PgpKeyOperationTest { { parcel.reset(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.SIGN_DATA, null)); + Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, null)); assertModifyFailure("creating master key with null expiry should fail", ring, parcel, LogType.MSG_MF_ERROR_NULL_EXPIRY); @@ -371,7 +360,7 @@ public class PgpKeyOperationTest { { // a past expiry should fail parcel.reset(); - parcel.mAddSubKeys.add(new SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.SIGN_DATA, + parcel.mAddSubKeys.add(new SubkeyAdd(Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, new Date().getTime()/1000-10)); assertModifyFailure("creating subkey with past expiry date should fail", ring, parcel, LogType.MSG_MF_ERROR_PAST_EXPIRY); diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java index 670022a10..5792e8326 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java @@ -49,6 +49,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.support.KeyringTestingHelper; import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket; @@ -85,11 +86,11 @@ public class UncachedKeyringCanonicalizeTest { SaveKeyringParcel parcel = new SaveKeyringParcel(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.CERTIFY_OTHER, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.SIGN_DATA, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L)); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.ENCRYPT_COMMS, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L)); parcel.mAddUserIds.add("twi"); parcel.mAddUserIds.add("pink"); @@ -298,7 +299,7 @@ public class UncachedKeyringCanonicalizeTest { SaveKeyringParcel parcel = new SaveKeyringParcel(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.CERTIFY_OTHER, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); parcel.mAddUserIds.add("trix"); PgpKeyOperation op = new PgpKeyOperation(null); diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java index a04fe1f11..64152a040 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java @@ -33,6 +33,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.support.KeyringTestingHelper; import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -85,9 +86,9 @@ public class UncachedKeyringMergeTest { { SaveKeyringParcel parcel = new SaveKeyringParcel(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.CERTIFY_OTHER, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.SIGN_DATA, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L)); parcel.mAddUserIds.add("twi"); parcel.mAddUserIds.add("pink"); @@ -104,7 +105,7 @@ public class UncachedKeyringMergeTest { { SaveKeyringParcel parcel = new SaveKeyringParcel(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.CERTIFY_OTHER, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); parcel.mAddUserIds.add("shy"); // passphrase is tested in PgpKeyOperationTest, just use empty here @@ -210,7 +211,7 @@ public class UncachedKeyringMergeTest { parcel.reset(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.SIGN_DATA, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L)); modifiedA = op.modifySecretKeyRing(secretRing, parcel, "").getRing(); modifiedB = op.modifySecretKeyRing(secretRing, parcel, "").getRing(); diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java index 8aac5d430..636dae90c 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java @@ -31,6 +31,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket; import java.io.ByteArrayInputStream; @@ -55,11 +56,11 @@ public class UncachedKeyringTest { SaveKeyringParcel parcel = new SaveKeyringParcel(); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.CERTIFY_OTHER, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.CERTIFY_OTHER, 0L)); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.SIGN_DATA, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L)); parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( - PublicKeyAlgorithmTags.RSA_GENERAL, 1024, KeyFlags.ENCRYPT_COMMS, 0L)); + Algorithm.RSA, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L)); parcel.mAddUserIds.add("twi"); parcel.mAddUserIds.add("pink"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java index 69ac2551f..e30401180 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/HkpKeyserver.java @@ -283,7 +283,7 @@ public class HkpKeyserver extends Keyserver { entry.setBitStrength(Integer.parseInt(matcher.group(3))); final int algorithmId = Integer.decode(matcher.group(2)); - entry.setAlgorithm(PgpKeyHelper.getAlgorithmInfo(algorithmId)); + entry.setAlgorithm(PgpKeyHelper.getAlgorithmInfo(algorithmId, null, null)); // group 1 contains the full fingerprint (v4) or the long key id if available // see http://bit.ly/1d4bxbk and http://bit.ly/1gD1wwr diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java index 30e93f957..da70f1505 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java @@ -39,7 +39,8 @@ public class ImportKeysListEntry implements Serializable, Parcelable { private boolean mExpired; private Date mDate; // TODO: not displayed private String mFingerprintHex; - private int mBitStrength; + private Integer mBitStrength; + private String mCurveOid; private String mAlgorithm; private boolean mSecretKey; private String mPrimaryUserId; @@ -162,10 +163,14 @@ public class ImportKeysListEntry implements Serializable, Parcelable { this.mFingerprintHex = fingerprintHex; } - public int getBitStrength() { + public Integer getBitStrength() { return mBitStrength; } + public String getCurveOid() { + return mCurveOid; + } + public void setBitStrength(int bitStrength) { this.mBitStrength = bitStrength; } @@ -258,13 +263,15 @@ public class ImportKeysListEntry implements Serializable, Parcelable { mPrimaryUserId = mUserIds.get(0); } - this.mKeyId = key.getKeyId(); - this.mKeyIdHex = PgpKeyHelper.convertKeyIdToHex(mKeyId); + mKeyId = key.getKeyId(); + mKeyIdHex = PgpKeyHelper.convertKeyIdToHex(mKeyId); - this.mRevoked = key.isRevoked(); - this.mFingerprintHex = PgpKeyHelper.convertFingerprintToHex(key.getFingerprint()); - this.mBitStrength = key.getBitStrength(); + mRevoked = key.isRevoked(); + mFingerprintHex = PgpKeyHelper.convertFingerprintToHex(key.getFingerprint()); + mBitStrength = key.getBitStrength(); + mCurveOid = key.getCurveOid(); final int algorithm = key.getAlgorithm(); - this.mAlgorithm = PgpKeyHelper.getAlgorithmInfo(context, algorithm); + mAlgorithm = PgpKeyHelper.getAlgorithmInfo(context, algorithm, mBitStrength, mCurveOid); } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java index 0ca6f07fd..cbd06da90 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/KeybaseKeyserver.java @@ -75,7 +75,7 @@ public class KeybaseKeyserver extends Keyserver { entry.setExtraData(username); final int algorithmId = match.getAlgorithmId(); - entry.setAlgorithm(PgpKeyHelper.getAlgorithmInfo(algorithmId)); + entry.setAlgorithm(PgpKeyHelper.getAlgorithmInfo(algorithmId, null, null)); final int bitStrength = match.getBitStrength(); entry.setBitStrength(bitStrength); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java index 0c640538f..22956c8af 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -24,10 +24,16 @@ import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.nist.NISTNamedCurves; +import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves; +import org.spongycastle.bcpg.ECPublicBCPGKey; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.util.Log; import java.security.DigestException; @@ -37,18 +43,14 @@ import java.util.Locale; public class PgpKeyHelper { - public static String getAlgorithmInfo(int algorithm) { - return getAlgorithmInfo(null, algorithm, 0); - } - - public static String getAlgorithmInfo(Context context, int algorithm) { - return getAlgorithmInfo(context, algorithm, 0); + public static String getAlgorithmInfo(int algorithm, Integer keySize, String oid) { + return getAlgorithmInfo(null, algorithm, keySize, oid); } /** * Based on OpenPGP Message Format */ - public static String getAlgorithmInfo(Context context, int algorithm, int keySize) { + public static String getAlgorithmInfo(Context context, int algorithm, Integer keySize, String oid) { String algorithmStr; switch (algorithm) { @@ -69,10 +71,19 @@ public class PgpKeyHelper { break; } - case PublicKeyAlgorithmTags.ECDSA: + case PublicKeyAlgorithmTags.ECDSA: { + if (oid == null) { + return "ECDSA"; + } + String oidName = PgpKeyHelper.getCurveInfo(context, oid); + return "ECDSA (" + oidName + ")"; + } case PublicKeyAlgorithmTags.ECDH: { - algorithmStr = "ECC"; - break; + if (oid == null) { + return "ECDH"; + } + String oidName = PgpKeyHelper.getCurveInfo(context, oid); + return "ECDH (" + oidName + ")"; } default: { @@ -90,6 +101,106 @@ public class PgpKeyHelper { return algorithmStr; } + public static String getAlgorithmInfo(Algorithm algorithm, Integer keySize, Curve curve) { + return getAlgorithmInfo(null, algorithm, keySize, curve); + } + + /** + * Based on OpenPGP Message Format + */ + public static String getAlgorithmInfo(Context context, Algorithm algorithm, Integer keySize, Curve curve) { + String algorithmStr; + + switch (algorithm) { + case RSA: { + algorithmStr = "RSA"; + break; + } + case DSA: { + algorithmStr = "DSA"; + break; + } + + case ELGAMAL: { + algorithmStr = "ElGamal"; + break; + } + + case ECDSA: { + algorithmStr = "ECDSA"; + if (curve != null) { + algorithmStr += " (" + getCurveInfo(context, curve) + ")"; + } + return algorithmStr; + } + case ECDH: { + algorithmStr = "ECDH"; + if (curve != null) { + algorithmStr += " (" + getCurveInfo(context, curve) + ")"; + } + return algorithmStr; + } + + default: { + if (context != null) { + algorithmStr = context.getResources().getString(R.string.unknown_algorithm); + } else { + algorithmStr = "unknown"; + } + break; + } + } + if (keySize != null && keySize > 0) + return algorithmStr + ", " + keySize + " bit"; + else + return algorithmStr; + } + + // Return name of a curve. These are names, no need for translation + public static String getCurveInfo(Context context, Curve curve) { + switch(curve) { + case NIST_P256: + return "NIST P-256"; + case NIST_P384: + return "NIST P-384"; + case NIST_P521: + return "NIST P-521"; + + /* see SaveKeyringParcel + case BRAINPOOL_P256: + return "Brainpool P-256"; + case BRAINPOOL_P384: + return "Brainpool P-384"; + case BRAINPOOL_P512: + return "Brainpool P-512"; + */ + } + if (context != null) { + return context.getResources().getString(R.string.unknown_algorithm); + } else { + return "unknown"; + } + } + + public static String getCurveInfo(Context context, String oidStr) { + ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(oidStr); + + String name; + name = NISTNamedCurves.getName(oid); + if (name != null) { + return name; + } + name = TeleTrusTNamedCurves.getName(oid); + if (name != null) { + return name; + } + if (context != null) { + return context.getResources().getString(R.string.unknown_algorithm); + } else { + return "unknown"; + } + } + /** * Converts fingerprint to hex (optional: with whitespaces after 4 characters) *
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 175045470..967a7caa9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -20,12 +20,12 @@ package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; -import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; import org.spongycastle.bcpg.sig.Features; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.jce.spec.ElGamalParameterSpec; import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPKeyFlags; import org.spongycastle.openpgp.PGPKeyPair; import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.PGPPublicKey; @@ -52,6 +52,8 @@ import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -66,6 +68,7 @@ import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.SignatureException; +import java.security.spec.ECGenParameterSpec; import java.util.Arrays; import java.util.Date; import java.util.Iterator; @@ -155,31 +158,65 @@ public class PgpKeyOperation { mProgress.peek().setProgress(message, current, 100); } + private ECGenParameterSpec getEccParameterSpec(Curve curve) { + switch (curve) { + case NIST_P256: return new ECGenParameterSpec("P-256"); + case NIST_P384: return new ECGenParameterSpec("P-384"); + case NIST_P521: return new ECGenParameterSpec("P-521"); + + // @see SaveKeyringParcel + // case BRAINPOOL_P256: return new ECGenParameterSpec("brainpoolp256r1"); + // case BRAINPOOL_P384: return new ECGenParameterSpec("brainpoolp384r1"); + // case BRAINPOOL_P512: return new ECGenParameterSpec("brainpoolp512r1"); + } + throw new RuntimeException("Invalid choice! (can't happen)"); + } + /** Creates new secret key. */ - private PGPKeyPair createKey(int algorithmChoice, int keySize, OperationLog log, int indent) { + private PGPKeyPair createKey(SubkeyAdd add, OperationLog log, int indent) { try { - if (keySize < 512) { - log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_KEYSIZE_512, indent); - return null; + // Some safety checks + if (add.mAlgorithm == Algorithm.ECDH || add.mAlgorithm == Algorithm.ECDSA) { + if (add.mCurve == null) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_NO_CURVE, indent); + return null; + } + } else { + if (add.mKeySize == null) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_NO_KEYSIZE, indent); + return null; + } + if (add.mKeySize < 512) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_KEYSIZE_512, indent); + return null; + } } int algorithm; KeyPairGenerator keyGen; - switch (algorithmChoice) { - case PublicKeyAlgorithmTags.DSA: { + switch (add.mAlgorithm) { + case DSA: { + if ((add.mFlags & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_FLAGS_DSA, indent); + return null; + } progress(R.string.progress_generating_dsa, 30); keyGen = KeyPairGenerator.getInstance("DSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME); - keyGen.initialize(keySize, new SecureRandom()); + keyGen.initialize(add.mKeySize, new SecureRandom()); algorithm = PGPPublicKey.DSA; break; } - case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: { + case ELGAMAL: { + if ((add.mFlags & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_FLAGS_ELGAMAL, indent); + return null; + } progress(R.string.progress_generating_elgamal, 30); keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME); - BigInteger p = Primes.getBestPrime(keySize); + BigInteger p = Primes.getBestPrime(add.mKeySize); BigInteger g = new BigInteger("2"); ElGamalParameterSpec elParams = new ElGamalParameterSpec(p, g); @@ -189,15 +226,44 @@ public class PgpKeyOperation { break; } - case PublicKeyAlgorithmTags.RSA_GENERAL: { + case RSA: { progress(R.string.progress_generating_rsa, 30); keyGen = KeyPairGenerator.getInstance("RSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME); - keyGen.initialize(keySize, new SecureRandom()); + keyGen.initialize(add.mKeySize, new SecureRandom()); algorithm = PGPPublicKey.RSA_GENERAL; break; } + case ECDSA: { + if ((add.mFlags & (PGPKeyFlags.CAN_ENCRYPT_COMMS | PGPKeyFlags.CAN_ENCRYPT_STORAGE)) > 0) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_FLAGS_ECDSA, indent); + return null; + } + progress(R.string.progress_generating_ecdsa, 30); + ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.mCurve); + keyGen = KeyPairGenerator.getInstance("ECDSA", Constants.BOUNCY_CASTLE_PROVIDER_NAME); + keyGen.initialize(ecParamSpec, new SecureRandom()); + + algorithm = PGPPublicKey.ECDSA; + break; + } + + case ECDH: { + // make sure there are no sign or certify flags set + if ((add.mFlags & (PGPKeyFlags.CAN_SIGN | PGPKeyFlags.CAN_CERTIFY)) > 0) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_FLAGS_ECDH, indent); + return null; + } + progress(R.string.progress_generating_ecdh, 30); + ECGenParameterSpec ecParamSpec = getEccParameterSpec(add.mCurve); + keyGen = KeyPairGenerator.getInstance("ECDH", Constants.BOUNCY_CASTLE_PROVIDER_NAME); + keyGen.initialize(ecParamSpec, new SecureRandom()); + + algorithm = PGPPublicKey.ECDH; + break; + } + default: { log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_UNKNOWN_ALGO, indent); return null; @@ -210,7 +276,8 @@ public class PgpKeyOperation { } catch(NoSuchProviderException e) { throw new RuntimeException(e); } catch(NoSuchAlgorithmException e) { - throw new RuntimeException(e); + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_UNKNOWN_ALGO, indent); + return null; } catch(InvalidAlgorithmParameterException e) { throw new RuntimeException(e); } catch(PGPException e) { @@ -252,13 +319,8 @@ public class PgpKeyOperation { return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); } - if (add.mAlgorithm == PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT) { - log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_MASTER_ELGAMAL, indent); - return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); - } - subProgressPush(10, 30); - PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize, log, indent); + PGPKeyPair keyPair = createKey(add, log, indent); subProgressPop(); // return null if this failed (an error will already have been logged by createKey) @@ -690,8 +752,8 @@ public class PgpKeyOperation { progress(R.string.progress_modify_subkeyadd, (i-1) * (100 / saveParcel.mAddSubKeys.size())); SaveKeyringParcel.SubkeyAdd add = saveParcel.mAddSubKeys.get(i); - log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent, Integer.toString(add.mKeysize), - PgpKeyHelper.getAlgorithmInfo(add.mAlgorithm) ); + log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent, + PgpKeyHelper.getAlgorithmInfo(add.mAlgorithm, add.mKeySize, add.mCurve) ); if (add.mExpiry == null) { log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_NULL_EXPIRY, indent +1); @@ -708,7 +770,7 @@ public class PgpKeyOperation { (i-1) * (100 / saveParcel.mAddSubKeys.size()), i * (100 / saveParcel.mAddSubKeys.size()) ); - PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize, log, indent); + PGPKeyPair keyPair = createKey(add, log, indent); subProgressPop(); if (keyPair == null) { log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_PGP, indent +1); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index caacb948e..9effe4e67 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -37,7 +37,6 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; -import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -58,7 +57,8 @@ import java.util.TreeSet; * This class and its relatives UncachedPublicKey and UncachedSecretKey are * used to move around pgp key rings in non crypto related (UI, mostly) code. * It should be used for simple inspection only until it saved in the database, - * all actual crypto operations should work with WrappedKeyRings exclusively. + * all actual crypto operations should work with CanonicalizedKeyRings + * exclusively. * * This class is also special in that it can hold either the PGPPublicKeyRing * or PGPSecretKeyRing derivate of the PGPKeyRing class, since these are @@ -591,7 +591,7 @@ public class UncachedKeyRing { } - // if we already have a cert, and this one is not newer: skip it + // if we already have a cert, and this one is older: skip it if (selfCert != null && cert.getCreationTime().before(selfCert.getCreationTime())) { log.add(LogLevel.DEBUG, LogType.MSG_KC_SUB_DUP, indent); redundantCerts += 1; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java index dda52d786..c7a8bb1d0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedPublicKey.java @@ -18,6 +18,10 @@ package org.sufficientlysecure.keychain.pgp; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.nist.NISTNamedCurves; +import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves; +import org.spongycastle.bcpg.ECPublicBCPGKey; import org.spongycastle.bcpg.sig.KeyFlags; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSignature; @@ -94,10 +98,23 @@ public class UncachedPublicKey { return mPublicKey.getAlgorithm(); } - public int getBitStrength() { + public Integer getBitStrength() { + if (isEC()) { + return null; + } return mPublicKey.getBitStrength(); } + public String getCurveOid() { + if ( ! isEC()) { + return null; + } + if ( ! (mPublicKey.getPublicKeyPacket().getKey() instanceof ECPublicBCPGKey)) { + return null; + } + return ((ECPublicBCPGKey) mPublicKey.getPublicKeyPacket().getKey()).getCurveOID().getId(); + } + /** Returns the primary user id, as indicated by the public key's self certificates. * * This is an expensive operation, since potentially a lot of certificates (and revocations) @@ -186,6 +203,10 @@ public class UncachedPublicKey { return getAlgorithm() == PGPPublicKey.DSA; } + public boolean isEC() { + return getAlgorithm() == PGPPublicKey.ECDH || getAlgorithm() == PGPPublicKey.ECDSA; + } + @SuppressWarnings("unchecked") // TODO make this safe public int getKeyUsage() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index 24d86dc4a..4f6e878b4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -39,6 +39,7 @@ public class KeychainContract { String FINGERPRINT = "fingerprint"; String KEY_SIZE = "key_size"; + String KEY_CURVE_OID = "key_curve_oid"; String CAN_SIGN = "can_sign"; String CAN_ENCRYPT = "can_encrypt"; String CAN_CERTIFY = "can_certify"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 36e94208d..0bb43d47f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -52,7 +52,7 @@ import java.io.IOException; */ public class KeychainDatabase extends SQLiteOpenHelper { private static final String DATABASE_NAME = "openkeychain.db"; - private static final int DATABASE_VERSION = 2; + private static final int DATABASE_VERSION = 3; static Boolean apgHack = false; public interface Tables { @@ -86,6 +86,7 @@ public class KeychainDatabase extends SQLiteOpenHelper { + KeysColumns.KEY_ID + " INTEGER, " + KeysColumns.KEY_SIZE + " INTEGER, " + + KeysColumns.KEY_CURVE_OID + " TEXT, " + KeysColumns.ALGORITHM + " INTEGER, " + KeysColumns.FINGERPRINT + " BLOB, " @@ -202,13 +203,20 @@ public class KeychainDatabase extends SQLiteOpenHelper { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - if (oldVersion == 1) { - // add has_secret for all who are upgrading from a beta version - try { - db.execSQL("ALTER TABLE keys ADD COLUMN has_secret BOOLEAN"); - } catch (Exception e) { - // never mind, the column probably already existed - } + // add has_secret for all who are upgrading from a beta version + switch (oldVersion) { + case 1: + try { + db.execSQL("ALTER TABLE keys ADD COLUMN has_secret BOOLEAN"); + } catch(Exception e){ + // never mind, the column probably already existed + } + case 2: + try { + db.execSQL("ALTER TABLE keys ADD COLUMN " + KeysColumns.KEY_CURVE_OID + " TEXT"); + } catch(Exception e){ + // never mind, the column probably already existed + } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index b2a47cccd..f6df4a3eb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -246,6 +246,7 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID); projectionMap.put(KeyRings.KEY_ID, Tables.KEYS + "." + Keys.KEY_ID); projectionMap.put(KeyRings.KEY_SIZE, Tables.KEYS + "." + Keys.KEY_SIZE); + projectionMap.put(KeyRings.KEY_CURVE_OID, Tables.KEYS + "." + Keys.KEY_CURVE_OID); projectionMap.put(KeyRings.IS_REVOKED, Tables.KEYS + "." + Keys.IS_REVOKED); projectionMap.put(KeyRings.CAN_CERTIFY, Tables.KEYS + "." + Keys.CAN_CERTIFY); projectionMap.put(KeyRings.CAN_ENCRYPT, Tables.KEYS + "." + Keys.CAN_ENCRYPT); @@ -412,6 +413,7 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(Keys.RANK, Tables.KEYS + "." + Keys.RANK); projectionMap.put(Keys.KEY_ID, Keys.KEY_ID); projectionMap.put(Keys.KEY_SIZE, Keys.KEY_SIZE); + projectionMap.put(Keys.KEY_CURVE_OID, Keys.KEY_CURVE_OID); projectionMap.put(Keys.IS_REVOKED, Keys.IS_REVOKED); projectionMap.put(Keys.CAN_CERTIFY, Keys.CAN_CERTIFY); projectionMap.put(Keys.CAN_ENCRYPT, Keys.CAN_ENCRYPT); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 16ff2286b..bb095c340 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -62,7 +62,6 @@ import org.sufficientlysecure.keychain.util.FileImportCache; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressFixedScaler; -import org.sufficientlysecure.keychain.util.ProgressScaler; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -328,6 +327,7 @@ public class ProviderHelper { values.put(Keys.KEY_ID, key.getKeyId()); values.put(Keys.KEY_SIZE, key.getBitStrength()); + values.put(Keys.KEY_CURVE_OID, key.getCurveOid()); values.put(Keys.ALGORITHM, key.getAlgorithm()); values.put(Keys.FINGERPRINT, key.getFingerprint()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 886f77068..b69ecef34 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -347,9 +347,14 @@ public class OperationResultParcel implements Parcelable { MSG_CR_ERROR_NO_CERTIFY (R.string.msg_cr_error_no_certify), MSG_CR_ERROR_NULL_EXPIRY(R.string.msg_cr_error_null_expiry), MSG_CR_ERROR_KEYSIZE_512 (R.string.msg_cr_error_keysize_512), + MSG_CR_ERROR_NO_KEYSIZE (R.string.msg_cr_error_no_keysize), + MSG_CR_ERROR_NO_CURVE (R.string.msg_cr_error_no_curve), MSG_CR_ERROR_UNKNOWN_ALGO (R.string.msg_cr_error_unknown_algo), MSG_CR_ERROR_INTERNAL_PGP (R.string.msg_cr_error_internal_pgp), - MSG_CR_ERROR_MASTER_ELGAMAL (R.string.msg_cr_error_master_elgamal), + MSG_CR_ERROR_FLAGS_DSA (R.string.msg_cr_error_flags_dsa), + MSG_CR_ERROR_FLAGS_ELGAMAL (R.string.msg_cr_error_flags_elgamal), + MSG_CR_ERROR_FLAGS_ECDSA (R.string.msg_cr_error_flags_ecdsa), + MSG_CR_ERROR_FLAGS_ECDH (R.string.msg_cr_error_flags_ecdh), // secret key modify MSG_MF (R.string.msg_mr), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 6e06c4fa9..996ce6a5a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -80,14 +80,16 @@ public class SaveKeyringParcel implements Parcelable { // performance gain for using Parcelable here would probably be negligible, // use Serializable instead. public static class SubkeyAdd implements Serializable { - public int mAlgorithm; - public int mKeysize; + public Algorithm mAlgorithm; + public Integer mKeySize; + public Curve mCurve; public int mFlags; public Long mExpiry; - public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) { + public SubkeyAdd(Algorithm algorithm, Integer keySize, Curve curve, int flags, Long expiry) { mAlgorithm = algorithm; - mKeysize = keysize; + mKeySize = keySize; + mCurve = curve; mFlags = flags; mExpiry = expiry; } @@ -95,7 +97,8 @@ public class SaveKeyringParcel implements Parcelable { @Override public String toString() { String out = "mAlgorithm: " + mAlgorithm + ", "; - out += "mKeysize: " + mKeysize + ", "; + out += "mKeySize: " + mKeySize + ", "; + out += "mCurve: " + mCurve + ", "; out += "mFlags: " + mFlags; out += "mExpiry: " + mExpiry; @@ -214,4 +217,20 @@ public class SaveKeyringParcel implements Parcelable { return out; } + + // All supported algorithms + public enum Algorithm { + RSA, DSA, ELGAMAL, ECDSA, ECDH + } + + // All curves defined in the standard + // http://www.bouncycastle.org/wiki/pages/viewpage.action?pageId=362269 + public enum Curve { + NIST_P256, NIST_P384, NIST_P521, + + // these are supported by gpg, but they are not in rfc6637 and not supported by BouncyCastle yet + // (adding support would be trivial though -> JcaPGPKeyConverter.java:190) + // BRAINPOOL_P256, BRAINPOOL_P384, BRAINPOOL_P512 + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index d804b9b70..69f4af04b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; @@ -165,9 +166,12 @@ public class CreateKeyFinalFragment extends Fragment { Bundle data = new Bundle(); SaveKeyringParcel parcel = new SaveKeyringParcel(); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.CERTIFY_OTHER, 0L)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.SIGN_DATA, 0L)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(PublicKeyAlgorithmTags.RSA_GENERAL, 4096, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.RSA, 4096, null, KeyFlags.CERTIFY_OTHER, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.RSA, 4096, null, KeyFlags.SIGN_DATA, 0L)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd( + Algorithm.RSA, 4096, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L)); String userId = KeyRing.createUserId(mName, mEmail, null); parcel.mAddUserIds.add(userId); parcel.mChangePrimaryUserId = userId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index 48e9da87f..92f38a44c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -167,7 +167,7 @@ public class ViewCertActivity extends ActionBarActivity mStatus.setTextColor(getResources().getColor(R.color.black)); } - String algorithmStr = PgpKeyHelper.getAlgorithmInfo(this, sig.getKeyAlgorithm(), 0); + String algorithmStr = PgpKeyHelper.getAlgorithmInfo(this, sig.getKeyAlgorithm(), null, null); mAlgorithm.setText(algorithmStr); mRowReason.setVisibility(View.GONE); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java index 1f809cc51..1fed58721 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -155,8 +155,8 @@ public class ImportKeysAdapter extends ArrayAdapter-1
, if key length is
* inappropriate.
*/
- private int getProperKeyLength(int algorithmId, int currentKeyLength) {
+ private int getProperKeyLength(Algorithm algorithm, int currentKeyLength) {
final int[] elGamalSupportedLengths = {1536, 2048, 3072, 4096, 8192};
int properKeyLength = -1;
- switch (algorithmId) {
- case PublicKeyAlgorithmTags.RSA_GENERAL:
+ switch (algorithm) {
+ case RSA:
if (currentKeyLength > 1024 && currentKeyLength <= 16384) {
properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8);
}
break;
- case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT:
+ case ELGAMAL:
int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length];
for (int i = 0; i < elGamalSupportedLengths.length; i++) {
elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength);
@@ -347,7 +388,7 @@ public class AddSubkeyDialogFragment extends DialogFragment {
}
properKeyLength = elGamalSupportedLengths[minimalIndex];
break;
- case PublicKeyAlgorithmTags.DSA:
+ case DSA:
if (currentKeyLength >= 512 && currentKeyLength <= 1024) {
properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64);
}
@@ -357,10 +398,10 @@ public class AddSubkeyDialogFragment extends DialogFragment {
}
private void setOkButtonAvailability(AlertDialog alertDialog) {
- final Choice selectedAlgorithm = (Choice) mAlgorithmSpinner.getSelectedItem();
- final int selectedKeySize = getSelectedKeyLength(); //Integer.parseInt((String) mKeySizeSpinner.getSelectedItem());
- final int properKeyLength = getProperKeyLength(selectedAlgorithm.getId(), selectedKeySize);
- alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(properKeyLength > 0);
+ Algorithm algorithm = ((Choice