diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index c7c8d78e4c..9d8a502b31 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -3422,14 +3422,28 @@ public class FragmentCompose extends FragmentBase { CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator(); cmsGenerator.addCertificates(store); + String signAlgorithm = prefs.getString("sign_algo_smime", "SHA256"); + + // https://datatracker.ietf.org/doc/html/rfc5751#page-29 + String micalg = signAlgorithm.toLowerCase(Locale.ROOT); + if (micalg.startsWith("sha")) + micalg = micalg.substring(0, 3) + "-" + micalg.substring(3); + String algorithm = privkey.getAlgorithm(); - Log.i("Private key algorithm=" + algorithm); + if (TextUtils.isEmpty(algorithm) || "RSA".equals(algorithm)) + Log.i("Private key algorithm=" + algorithm); + else + Log.e("Private key algorithm=" + algorithm); + if (TextUtils.isEmpty(algorithm)) algorithm = "RSA"; else if ("EC".equals(algorithm)) algorithm = "ECDSA"; - ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256with" + algorithm) + algorithm = signAlgorithm + "with" + algorithm; + Log.i("Sign algorithm=" + algorithm); + + ContentSigner contentSigner = new JcaContentSignerBuilder(algorithm) .build(privkey); DigestCalculatorProvider digestCalculator = new JcaDigestCalculatorProviderBuilder() .build(); @@ -3451,7 +3465,7 @@ public class FragmentCompose extends FragmentBase { // Build signature if (EntityMessage.SMIME_SIGNONLY.equals(type)) { ContentType ct = new ContentType("application/pkcs7-signature"); - ct.setParameter("micalg", "sha-256"); + ct.setParameter("micalg", micalg); EntityAttachment sattachment = new EntityAttachment(); sattachment.message = draft.id; diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java b/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java index fd43f1b929..4125974a26 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsEncryption.java @@ -80,6 +80,7 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre private SwitchCompat swAutocryptMutual; private SwitchCompat swEncryptSubject; + private Spinner spSignAlgoSmime; private SwitchCompat swCheckCertificate; private Button btnManageCertificates; private Button btnImportKey; @@ -93,7 +94,7 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre private final static String[] RESET_OPTIONS = new String[]{ "sign_default", "encrypt_default", "auto_decrypt", "auto_undecrypt", "openpgp_provider", "autocrypt", "autocrypt_mutual", "encrypt_subject", - "check_certificate" + "sign_algo_smime", "check_certificate" }; @Override @@ -119,6 +120,7 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre swAutocryptMutual = view.findViewById(R.id.swAutocryptMutual); swEncryptSubject = view.findViewById(R.id.swEncryptSubject); + spSignAlgoSmime = view.findViewById(R.id.spSignAlgoSmime); swCheckCertificate = view.findViewById(R.id.swCheckCertificate); btnManageCertificates = view.findViewById(R.id.btnManageCertificates); btnImportKey = view.findViewById(R.id.btnImportKey); @@ -253,6 +255,19 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre // S/MIME + spSignAlgoSmime.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int position, long id) { + String[] values = getResources().getStringArray(R.array.smimeSignAlgo); + prefs.edit().putString("sign_algo_smime", values[position]).apply(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + prefs.edit().remove("sign_algo_smime").apply(); + } + }); + swCheckCertificate.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { @@ -409,6 +424,14 @@ public class FragmentOptionsEncryption extends FragmentBase implements SharedPre swAutocryptMutual.setEnabled(swAutocrypt.isChecked()); swEncryptSubject.setChecked(prefs.getBoolean("encrypt_subject", false)); + String signAlgorithm = prefs.getString("sign_algo_smime", "SHA256"); + String[] smimeSignAlgo = getResources().getStringArray(R.array.smimeSignAlgo); + for (int pos = 0; pos < smimeSignAlgo.length; pos++) + if (smimeSignAlgo[pos].equals(signAlgorithm)) { + spSignAlgoSmime.setSelection(pos); + break; + } + swCheckCertificate.setChecked(prefs.getBoolean("check_certificate", true)); } diff --git a/app/src/main/res/layout/fragment_options_encryption.xml b/app/src/main/res/layout/fragment_options_encryption.xml index 9a18a29a12..d1fbdeaf24 100644 --- a/app/src/main/res/layout/fragment_options_encryption.xml +++ b/app/src/main/res/layout/fragment_options_encryption.xml @@ -264,6 +264,28 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + + +