summaryrefslogtreecommitdiffstats
path: root/comm/mail/extensions/openpgp/test/unit/rnp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/extensions/openpgp/test/unit/rnp')
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpgbin0 -> 9727 bytes
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg.asc200
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg.gpgbin0 -> 9387 bytes
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/data/plaintext-with-key-and-windows-1252-encoded-eml-attachment.eml109
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/data/plaintext-with-windows-1252-encoded-eml-attachment.eml39
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/test_alias.js321
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/test_badKeys.js69
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/test_encryptAndOrSign.js278
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/test_secretKeys.js384
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/test_strip.js137
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/test_uid.js132
-rw-r--r--comm/mail/extensions/openpgp/test/unit/rnp/xpcshell.ini14
12 files changed, 1683 insertions, 0 deletions
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg b/comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg
new file mode 100644
index 0000000000..6bc9b4f3af
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg
Binary files differ
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg.asc b/comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg.asc
new file mode 100644
index 0000000000..c67d0dd057
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg.asc
@@ -0,0 +1,200 @@
+-----BEGIN PGP MESSAGE-----
+
+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
+OqSc9tGDcmANF3LQEj1htma9yReOKmZdQTDY
+=s6vG
+-----END PGP MESSAGE-----
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg.gpg b/comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg.gpg
new file mode 100644
index 0000000000..1feb515938
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/data/bluebird50.jpg.gpg
Binary files differ
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/data/plaintext-with-key-and-windows-1252-encoded-eml-attachment.eml b/comm/mail/extensions/openpgp/test/unit/rnp/data/plaintext-with-key-and-windows-1252-encoded-eml-attachment.eml
new file mode 100644
index 0000000000..599d5f64f4
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/data/plaintext-with-key-and-windows-1252-encoded-eml-attachment.eml
@@ -0,0 +1,109 @@
+Content-Type: multipart/mixed; boundary=\"xy23ZrTYskosBXu9d5LEB0IV1ZMMCLTf7\";
+ protected-headers=\"v1\"
+Subject: Key And Windows 1252 Encoded Attachment
+From: Bob Babbage <bob@openpgp.example>
+To: alice@openpgp.example
+Message-ID: <ce639032-0823-5c4d-30a3-76a874950908@openpgp.example>
+
+--xy23ZrTYskosBXu9d5LEB0IV1ZMMCLTf7
+Content-Type: multipart/mixed; boundary=\"------------azSRG4BClDM2kDHcC4FYbiRW\"
+
+--------------azSRG4BClDM2kDHcC4FYbiRW
+Content-Type: text/plain; charset=UTF-8; format=flowed
+Content-Transfer-Encoding: quoted-printable
+
+Please see attached.
+
+--------------azSRG4BClDM2kDHcC4FYbiRW
+Content-Type: message/rfc822; name=\"win1252.eml\"
+Content-Disposition: attachment; filename=\"win1252.eml\"
+Content-Transfer-Encoding: 8bit
+
+To: bob@openpgp.example
+From: carol@openpgp.example
+Subject: Windows 1252
+Date: Wed, 4 Nov 2020 16:32:02 -0400
+User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
+ Thunderbird/78.4.0
+MIME-Version: 1.0
+Content-Type: text/plain; charset=windows-1252; format=flowed
+Content-Transfer-Encoding: 8bit
+Content-Language: en-US
+
+This message has 6 ü ü ü ü ü ü.
+
+--------------azSRG4BClDM2kDHcC4FYbiRW
+Content-Type: application/pgp-keys; name=\"OpenPGP_0xFBFCC82A015E7330.asc\"
+Content-Disposition: attachment; filename=\"OpenPGP_0xFBFCC82A015E7330.asc\"
+Content-Transfer-Encoding: quoted-printable
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+xsDNBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv/seOXpgec=
+TdO
+cVttfzC8ycIKrt3aQTiwOG/ctaR4Bk/t6ayNFfdUNxHWk4WCKzdz/56fW2O0F23qIRd8UUJp5=
+IIl
+N4RDdRCtdhVQIAuzvp2oVy/LaS2kxQoKvph/5pQ/5whqsyroEWDJoSV0yOb25B/iwk/pLUFoy=
+hDG
+9bj0kIzDxrEqW+7Ba8nocQlecMF3X5KMN5kp2zraLv9dlBBpWW43XktjcCZgMy20SouraVma8=
+Je/
+ECwUWYUiAZxLIlMv9CurEOtxUw6N3RdOtLmYZS9uEnn5y1UkF88o8Nku890uk6BrewFzJyLAx=
+5wR
+Z4F0qV/yq36UWQ0JB/AUGhHVPdFf6pl6eaxBwT5GXvbBUibtf8YI2og5RsgTWtXfU7ebSGXrl=
+5ZM
+pbA6mbfhd0R8aPxWfmDWiIOhBufhMCvUHh1sApMKVZnvIff9/0Dca3wbvLIwa3T4CyshfT0AE=
+QEA
+Ac0hQm9iIEJhYmJhZ2UgPGJvYkBvcGVucGdwLmV4YW1wbGU+wsEOBBMBCgA4AhsDBQsJCAcCB=
+hUK
+CQgLAgQWAgMBAh4BAheAFiEE0aZuGiOxgsmYD3iM+/zIKgFeczAFAl2lnvoACgkQ+/zIKgFec=
+zBv
+bAv/VNk90a6hG8Od9xTzXxH5YRFUSGfIA1yjPIVOnKqhMwps2U+sWE3urL+MvjyQRlyRV8oY9=
+IOh
+Q5Esm6DOZYrTnE7qVETm1ajIAP2OFChEc55uH88x/anpPOXOJY7S8jbn3naC9qad75BrZ+3g9=
+EBU
+Wiy5p8TykP05WSnSxNRt7vFKLfEB4nGkehpwHXOVF0CRNwYle42bg8lpmdXFDcCZCi+qEbafm=
+TQz
+kAqyzS3nCh3IAqq6Y0kBuaKLm2tSNUOlZbD+OHYQNZ5Jix7cZUzs6Xh4+I55NRWl5smrLq66y=
+OQo
+FPy9jot/Qxikx/wP3MsAzeGaZSEPc0fHp5G16rlGbxQ3vl8/usUV7W+TMEMljgwd5x8POR6HC=
+8Ea
+CDfVnUBCPi/Gv+egLjsIbPJZZEroiE40e6/UoCiQtlpQB5exPJYSd1Q1txCwueih99PHepsDh=
+mUQ
+KiACszNU+RRozAYau2VdHqnRJ7QYdxHDiH49jPK4NTMyb/tJh2TiIwcmsIpGzsDNBF2lnPIBD=
+ADW
+ML9cbGMrp12CtF9b2P6z9TTT74S8iyBOzaSvdGDQY/sUtZXRg21HWamXnn9sSXvIDEINOQ6A9=
+Qxd
+xoqWdCHrOuW3ofneYXoG+zeKc4dC86wa1TR2q9vW+RMXSO4uImA+Uzula/6k1DogDf28qhCxM=
+wG/
+i/m9g1c/0aApuDyKdQ1PXsHHNlgd/Dn6rrd5y2AObaifV7wIhEJnvqgFXDN2RXGjLeCOHV4Q2=
+WTY
+Pg/S4k1nMXVDwZXrvIsA0YwIMgIT86Rafp1qKlgPNbiIlC1g9RY/iFaGN2b4Ir6GDohBQSfZW=
+2+L
+XoPZuVE/wGlQ01rh827KVZW4lXvqsge+wtnWlszcselGATyzqOK9LdHPdZGzROZYI2e8c+paL=
+NDd
+VPL6vdRBUnkCaEkOtl1mr2JpQi5nTU+gTX4IeInC7E+1a9UDF/Y85ybUz8XV8rUnR76UqVC7K=
+idN
+epdHbZjjXCt8/Zo+Tec9JNbYNQB/e9ExmDntmlHEsSEQzFwzj8sxH48AEQEAAcLA9gQYAQoAI=
+BYh
+BNGmbhojsYLJmA94jPv8yCoBXnMwBQJdpZzyAhsMAAoJEPv8yCoBXnMw6f8L/26C34dkjBffT=
+zMj
+5Bdzm8MtF67OYneJ4TQMw7+41IL4rVcSKhIhk/3Ud5knaRtP2ef1+5F66h9/RPQOJ5+tvBwhB=
+AcU
+WSupKnUrdVaZQanYmtSxcVV2PL9+QEiNN3tzluhaWO//rACxJ+K/ZXQlIzwQVTpNhfGzAaMVV=
+9zp
+f3u0k14itcv6alKY8+rLZvO1wIIeRZLmU0tZDD5HtWDvUV7rIFI1WuoLb+KZgbYn3OWjCPHVd=
+Trd
+Z2CqnZbG3SXw6awH9bzRLV9EXkbhIMez0deCVdeo+wFFklh8/5VK2b0vk/+wqMJxfpa1lHvJL=
+obz
+OP9fvrswsr92MA2+k901WeISR7qEzcI0Fdg8AyFAExaEK6VyjP7SXGLwvfisw34OxuZr3qmx1=
+Suf
+u4toH3XrB7QJN8XyqqbsGxUCBqWif9RSK4xjzRTe56iPeiSJJOIciMP9i2ldI+KgLycyeDvGo=
+Bj0
+HCLO3gVaBe4ubVrj5KjhX2PVNEJd3XZRzaXZE2aAMQ=3D=3D
+=3DF9yX
+-----END PGP PUBLIC KEY BLOCK-----
+--------------azSRG4BClDM2kDHcC4FYbiRW--
+
+
+--xy23ZrTYskosBXu9d5LEB0IV1ZMMCLTf7--
+
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/data/plaintext-with-windows-1252-encoded-eml-attachment.eml b/comm/mail/extensions/openpgp/test/unit/rnp/data/plaintext-with-windows-1252-encoded-eml-attachment.eml
new file mode 100644
index 0000000000..b43d9883bf
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/data/plaintext-with-windows-1252-encoded-eml-attachment.eml
@@ -0,0 +1,39 @@
+Content-Type: multipart/mixed; boundary=\"mzik1s6PCI8wO850i5PykshHnKiAGShJ0\";
+ protected-headers=\"v1\"
+Subject: Key And Windows 1252 Encoded Attachment
+From: Bob Babbage <bob@openpgp.example>
+To: alice@openpgp.example
+Message-ID: <26826c45-bac5-f173-9d60-dab5c907156d@openpgp.example>
+
+--mzik1s6PCI8wO850i5PykshHnKiAGShJ0
+Content-Type: multipart/mixed; boundary=\"------------voUvzEdWKr8OR9mQliQ0aHDW\"
+
+--------------voUvzEdWKr8OR9mQliQ0aHDW
+Content-Type: text/plain; charset=UTF-8; format=flowed
+Content-Transfer-Encoding: quoted-printable
+
+Please see attached.
+
+--------------voUvzEdWKr8OR9mQliQ0aHDW
+Content-Type: message/rfc822; name=\"win1252.eml\"
+Content-Disposition: attachment; filename=\"win1252.eml\"
+Content-Transfer-Encoding: 8bit
+
+To: bob@openpgp.example
+From: carol@openpgp.example
+Subject: Windows 1252
+Date: Wed, 4 Nov 2020 16:32:02 -0400
+User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
+ Thunderbird/78.4.0
+MIME-Version: 1.0
+Content-Type: text/plain; charset=windows-1252; format=flowed
+Content-Transfer-Encoding: 8bit
+Content-Language: en-US
+
+This message has 6 ü ü ü ü ü ü.
+
+--------------voUvzEdWKr8OR9mQliQ0aHDW--
+
+
+--mzik1s6PCI8wO850i5PykshHnKiAGShJ0--
+
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/test_alias.js b/comm/mail/extensions/openpgp/test/unit/rnp/test_alias.js
new file mode 100644
index 0000000000..cc30b52a8a
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/test_alias.js
@@ -0,0 +1,321 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Tests for OpenPGP encryption alias rules.
+ */
+
+"use strict";
+
+const { RNP } = ChromeUtils.import("chrome://openpgp/content/modules/RNP.jsm");
+const { EnigmailConstants } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/constants.jsm"
+);
+const { EnigmailKeyRing } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/keyRing.jsm"
+);
+const { EnigmailEncryption } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/encryption.jsm"
+);
+const { OpenPGPAlias } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/OpenPGPAlias.jsm"
+);
+
+const { OpenPGPTestUtils } = ChromeUtils.import(
+ "resource://testing-common/mozmill/OpenPGPTestUtils.jsm"
+);
+
+const keyDir = "../../../../../test/browser/openpgp/data/keys";
+const mailNewsDir = "../../../../../../mailnews/test/data";
+
+// Alice's key: EB85BB5FA33A75E15E944E63F231550C4F47E38E
+// Bob's key: D1A66E1A23B182C9980F788CFBFCC82A015E7330
+// Carol's key: B8F2F6F4BD3AD3F82DC446833099FF1238852B9F
+
+const tests = [
+ {
+ info: "Should find Alice's key directly",
+ filename: undefined,
+ to: "alice@openpgp.example",
+ expectedMissing: false,
+ expectedAliasKeys: null,
+ },
+ {
+ info: "Key absent, no alias defined for address",
+ filename: `${mailNewsDir}/alias-1.json`,
+ to: "nobody@openpgp.example",
+ expectedMissing: true,
+ expectedAliasKeys: null,
+ },
+ {
+ info: "File maps Alice's address to Bob's (id) and Carol's (fingerprint) keys",
+ filename: `${mailNewsDir}/alias-1.json`,
+ to: "alice@openpgp.example",
+ expectedMissing: false,
+ expectedAliasKeys: [
+ "D1A66E1A23B182C9980F788CFBFCC82A015E7330",
+ "B8F2F6F4BD3AD3F82DC446833099FF1238852B9F",
+ ],
+ },
+ {
+ info: "File maps Alice's address to an absent key",
+ filename: `${mailNewsDir}/alias-2.json`,
+ to: "alice@openpgp.example",
+ expectedMissing: true,
+ expectedAliasKeys: null,
+ },
+ {
+ info: "File maps Alice's address to Alice's key (unnecessary alias)",
+ filename: `${mailNewsDir}/alias-3.json`,
+ to: "alice@openpgp.example",
+ expectedMissing: false,
+ expectedAliasKeys: ["EB85BB5FA33A75E15E944E63F231550C4F47E38E"],
+ },
+ {
+ info: "File maps an address to several keys, all available",
+ filename: `${mailNewsDir}/alias-4.json`,
+ to: "nobody@example.com",
+ expectedMissing: false,
+ expectedAliasKeys: [
+ "EB85BB5FA33A75E15E944E63F231550C4F47E38E",
+ "D1A66E1A23B182C9980F788CFBFCC82A015E7330",
+ "B8F2F6F4BD3AD3F82DC446833099FF1238852B9F",
+ ],
+ },
+ {
+ info: "File maps an address to several keys, one not available",
+ filename: `${mailNewsDir}/alias-5.json`,
+ to: "nobody@example.com",
+ expectedMissing: true,
+ expectedAliasKeys: null,
+ },
+ {
+ info: "File maps the domain to Carol's key",
+ filename: `${mailNewsDir}/alias-6.json`,
+ to: "someone@example.com",
+ expectedMissing: false,
+ expectedAliasKeys: ["B8F2F6F4BD3AD3F82DC446833099FF1238852B9F"],
+ },
+ {
+ info: "Multiple rules, should match domain1 rule",
+ filename: `${mailNewsDir}/alias-7.json`,
+ to: "someone@domain1.example.com",
+ expectedMissing: false,
+ expectedAliasKeys: ["EB85BB5FA33A75E15E944E63F231550C4F47E38E"],
+ },
+ {
+ info: "Multiple rules, should match domain2 rule",
+ filename: `${mailNewsDir}/alias-7.json`,
+ to: "contact@domain2.example.com",
+ expectedMissing: false,
+ expectedAliasKeys: ["D1A66E1A23B182C9980F788CFBFCC82A015E7330"],
+ },
+ {
+ info: "Multiple rules, should match email contact@domain1 rule",
+ filename: `${mailNewsDir}/alias-7.json`,
+ to: "contact@domain1.example.com",
+ expectedMissing: false,
+ expectedAliasKeys: [
+ "D1A66E1A23B182C9980F788CFBFCC82A015E7330",
+ "EB85BB5FA33A75E15E944E63F231550C4F47E38E",
+ ],
+ },
+ {
+ info: "Multiple rules, shouldn't match",
+ filename: `${mailNewsDir}/alias-7.json`,
+ to: "contact@domain2.example",
+ expectedMissing: true,
+ expectedAliasKeys: null,
+ },
+ {
+ info: "Mixed case test a",
+ filename: `${mailNewsDir}/alias-8.json`,
+ to: "a@UPPERDOM.EXAMPLE",
+ expectedMissing: false,
+ expectedAliasKeys: ["EB85BB5FA33A75E15E944E63F231550C4F47E38E"],
+ },
+ {
+ info: "Mixed case test b",
+ filename: `${mailNewsDir}/alias-8.json`,
+ to: "b@lowerdom.example",
+ expectedMissing: false,
+ expectedAliasKeys: ["D1A66E1A23B182C9980F788CFBFCC82A015E7330"],
+ },
+ {
+ info: "Mixed case test c",
+ filename: `${mailNewsDir}/alias-8.json`,
+ to: "C@MIXed.EXample",
+ expectedMissing: false,
+ expectedAliasKeys: ["B8F2F6F4BD3AD3F82DC446833099FF1238852B9F"],
+ },
+ {
+ info: "Mixed case test d",
+ filename: `${mailNewsDir}/alias-13.json`,
+ to: "NAME@DOMAIN.NET",
+ expectedMissing: false,
+ expectedAliasKeys: ["D1A66E1A23B182C9980F788CFBFCC82A015E7330"],
+ },
+ {
+ info: "Mixed case test e",
+ filename: `${mailNewsDir}/alias-14.json`,
+ to: "name@domain.net",
+ expectedMissing: false,
+ expectedAliasKeys: ["D1A66E1A23B182C9980F788CFBFCC82A015E7330"],
+ },
+ {
+ info: "Mixed case test f",
+ filename: `${mailNewsDir}/alias-15.json`,
+ to: "name@domain.net",
+ expectedMissing: false,
+ expectedAliasKeys: ["D1A66E1A23B182C9980F788CFBFCC82A015E7330"],
+ },
+ {
+ info: "JSON with bad syntax, should find Alice's key directly",
+ filename: `${mailNewsDir}/alias-9.json`,
+ to: "alice@openpgp.example",
+ expectedMissing: false,
+ expectedAliasKeys: null,
+ expectException: true,
+ },
+ {
+ info: "JSON with missing keys entry, should find Alice's key directly",
+ filename: `${mailNewsDir}/alias-10.json`,
+ to: "alice@openpgp.example",
+ expectedMissing: false,
+ expectedAliasKeys: null,
+ },
+ {
+ info: "JSON with empty keys entry, should find Alice's key directly",
+ filename: `${mailNewsDir}/alias-11.json`,
+ to: "alice@openpgp.example",
+ expectedMissing: false,
+ expectedAliasKeys: null,
+ },
+ {
+ info: "JSON with bad type keys entry, should find Alice's key directly",
+ filename: `${mailNewsDir}/alias-12.json`,
+ to: "alice@openpgp.example",
+ expectedMissing: false,
+ expectedAliasKeys: null,
+ },
+];
+
+/**
+ * Initialize OpenPGP add testing keys.
+ */
+add_setup(async function () {
+ do_get_profile();
+
+ await OpenPGPTestUtils.initOpenPGP();
+
+ await OpenPGPTestUtils.importPublicKey(
+ null,
+ do_get_file(`${keyDir}/alice@openpgp.example-0xf231550c4f47e38e-pub.asc`)
+ );
+
+ await OpenPGPTestUtils.importPublicKey(
+ null,
+ do_get_file(`${keyDir}/bob@openpgp.example-0xfbfcc82a015e7330-pub.asc`)
+ );
+
+ await OpenPGPTestUtils.importPublicKey(
+ null,
+ do_get_file(`${keyDir}/carol@example.com-0x3099ff1238852b9f-pub.asc`)
+ );
+});
+
+add_task(async function testAlias() {
+ let aliasFilename = "openpgp-alias-rules.json";
+ let profileDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
+
+ for (let test of tests) {
+ if (test.filename) {
+ info(`Running alias test with rules from: ${test.filename}`);
+
+ // Copy test file to profile directory (which is a relative path),
+ // because load function only works with simple filenames
+ // or absolute file URLs.
+
+ let inFile = do_get_file(test.filename);
+ inFile.copyTo(profileDir, aliasFilename);
+
+ try {
+ await OpenPGPAlias._loadFromFile(aliasFilename);
+ Assert.ok(
+ !("expectException" in test) || !test.expectException,
+ "expected no load exception"
+ );
+ } catch (ex) {
+ console.log(
+ "exception when loading alias file " + aliasFilename + " : " + ex
+ );
+ Assert.ok(
+ "expectException" in test && test.expectException,
+ "expected load exception"
+ );
+ }
+ } else {
+ info(`Running alias test without rules`);
+ OpenPGPAlias._clear();
+ }
+ info(test.info);
+
+ let addresses = [test.to];
+ let resultDetails = {};
+
+ let isMissing = await EnigmailKeyRing.getValidKeysForAllRecipients(
+ addresses,
+ resultDetails
+ );
+
+ Assert.ok(
+ (isMissing && test.expectedMissing) ||
+ (!isMissing && !test.expectedMissing),
+ "Should have the expected result from getValidKeysForAllRecipients"
+ );
+
+ if (isMissing || test.expectedMissing) {
+ continue;
+ }
+
+ let errorMsgObj = { value: "" };
+ let logFileObj = {};
+ let encryptArgs = EnigmailEncryption.getCryptParams(
+ "",
+ test.to,
+ "",
+ "SHA256",
+ EnigmailConstants.SEND_ENCRYPTED,
+ 0,
+ errorMsgObj,
+ logFileObj
+ );
+
+ let foundAliasKeys = encryptArgs.aliasKeys.get(test.to.toLowerCase());
+
+ if (!test.expectedAliasKeys) {
+ Assert.ok(!foundAliasKeys, "foundAliasKeys should be empty");
+ } else {
+ Assert.equal(foundAliasKeys.length, test.expectedAliasKeys.length);
+
+ test.expectedAliasKeys.forEach((val, i) => {
+ Assert.ok(foundAliasKeys.includes(val));
+ });
+
+ let encryptResult = {};
+ let encrypted = await RNP.encryptAndOrSign(
+ "plaintext",
+ encryptArgs,
+ encryptResult
+ );
+
+ Assert.ok(
+ !encryptResult.exitCode,
+ "RNP.encryptAndOrSign() should exit ok"
+ );
+
+ Assert.ok(encrypted.includes("END PGP MESSAGE"));
+ }
+ }
+});
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/test_badKeys.js b/comm/mail/extensions/openpgp/test/unit/rnp/test_badKeys.js
new file mode 100644
index 0000000000..3ca7709dc6
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/test_badKeys.js
@@ -0,0 +1,69 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Tests for bad OpenPGP keys.
+ */
+
+"use strict";
+
+const { RNP } = ChromeUtils.import("chrome://openpgp/content/modules/RNP.jsm");
+const { EnigmailConstants } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/constants.jsm"
+);
+const { EnigmailKeyRing } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/keyRing.jsm"
+);
+const { EnigmailEncryption } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/encryption.jsm"
+);
+const { OpenPGPAlias } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/OpenPGPAlias.jsm"
+);
+const { OpenPGPTestUtils } = ChromeUtils.import(
+ "resource://testing-common/mozmill/OpenPGPTestUtils.jsm"
+);
+
+const KEY_DIR = "../../../../../test/browser/openpgp/data/keys";
+
+add_setup(async function () {
+ do_get_profile();
+
+ await OpenPGPTestUtils.initOpenPGP();
+});
+
+// Attempt to import a key with a single user ID, which is invalid,
+// because it doesn't have a valid signature.
+// Our code should reject the attempt to import the key.
+add_task(async function testFailToImport() {
+ let ids = await OpenPGPTestUtils.importKey(
+ null,
+ do_get_file(`${KEY_DIR}/invalid-pubkey-nosigs.pgp`),
+ true
+ );
+ Assert.ok(!ids.length, "importKey should return empty list of imported keys");
+});
+
+// Import a key with two encryption subkeys. One is good, the other one
+// has an invalid signature. When attempting to encrypt, our code should
+// skip the bad subkey, and should use the expected good subkey.
+add_task(async function testAvoidBadSubkey() {
+ let ids = await OpenPGPTestUtils.importKey(
+ null,
+ do_get_file(`${KEY_DIR}/encryption-subkey-bad.pgp`),
+ true
+ );
+ await OpenPGPTestUtils.updateKeyIdAcceptance(
+ ids,
+ OpenPGPTestUtils.ACCEPTANCE_VERIFIED
+ );
+
+ let primaryKey = await RNP.findKeyByEmail(
+ "<encryption-subkey@example.org>",
+ true
+ );
+ let encSubKey = RNP.getSuitableSubkey(primaryKey, "encrypt");
+ let keyId = RNP.getKeyIDFromHandle(encSubKey);
+ Assert.ok(keyId == "BC63472A109D5859", "should obtain key ID of good subkey");
+});
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/test_encryptAndOrSign.js b/comm/mail/extensions/openpgp/test/unit/rnp/test_encryptAndOrSign.js
new file mode 100644
index 0000000000..a52911d288
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/test_encryptAndOrSign.js
@@ -0,0 +1,278 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Tests for RNP.encryptAndOrSign().
+ */
+
+"use strict";
+
+const { RNP } = ChromeUtils.import("chrome://openpgp/content/modules/RNP.jsm");
+const { EnigmailConstants } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/constants.jsm"
+);
+
+const { OpenPGPTestUtils } = ChromeUtils.import(
+ "resource://testing-common/mozmill/OpenPGPTestUtils.jsm"
+);
+
+const keyDir = "../../../../../test/browser/openpgp/data/keys";
+const mailNewsDir = "../../../../../../mailnews/test/data";
+
+const tests = [
+ // Base64 encoded bodies.
+ {
+ filename: `${mailNewsDir}/01-plaintext.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/02-plaintext+attachment.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/03-HTML.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/04-HTML+attachment.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/05-HTML+embedded-image.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/06-plaintext+HMTL.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/07-plaintext+(HTML+embedded-image).eml`,
+ },
+ {
+ filename: `${mailNewsDir}/08-plaintext+HTML+attachment.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/09-(HTML+embedded-image)+attachment.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/10-plaintext+(HTML+embedded-image)+attachment.eml`,
+ },
+
+ // Bodies with non-ASCII characters in UTF-8 and other charsets.
+ {
+ filename: `${mailNewsDir}/11-plaintext.eml`,
+ skip: true,
+ },
+ // using ISO-8859-7 (Greek)
+ {
+ filename: `${mailNewsDir}/12-plaintext+attachment.eml`,
+ encoding: "iso-8859-7",
+ skip: true,
+ },
+ {
+ filename: `${mailNewsDir}/13-HTML.eml`,
+ skip: true,
+ },
+ {
+ filename: `${mailNewsDir}/14-HTML+attachment.eml`,
+ skip: true,
+ },
+ {
+ filename: `${mailNewsDir}/15-HTML+embedded-image.eml`,
+ skip: true,
+ },
+ // text part is base64 encoded
+ {
+ filename: `${mailNewsDir}/16-plaintext+HMTL.eml`,
+ skip: true,
+ },
+ // HTML part is base64 encoded
+ {
+ filename: `${mailNewsDir}/17-plaintext+(HTML+embedded-image).eml`,
+ skip: true,
+ },
+ {
+ filename: `${mailNewsDir}/18-plaintext+HTML+attachment.eml`,
+ skip: true,
+ },
+ {
+ filename: `${mailNewsDir}/19-(HTML+embedded-image)+attachment.eml`,
+ skip: true,
+ },
+ // using windows-1252
+ {
+ filename: `${mailNewsDir}/20-plaintext+(HTML+embedded-image)+attachment.eml`,
+ encoding: "windows-1252",
+ skip: true,
+ },
+
+ // Bodies with non-ASCII characters in UTF-8 and other charsets, all encoded
+ // with quoted printable.
+ {
+ filename: `${mailNewsDir}/21-plaintext.eml`,
+ },
+ // using ISO-8859-7 (Greek)
+ {
+ filename: `${mailNewsDir}/22-plaintext+attachment.eml`,
+ encoding: "iso-8859-7",
+ },
+ {
+ filename: `${mailNewsDir}/23-HTML.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/24-HTML+attachment.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/25-HTML+embedded-image.eml`,
+ },
+ // text part is base64 encoded
+ {
+ filename: `${mailNewsDir}/26-plaintext+HMTL.eml`,
+ },
+ // HTML part is base64 encoded
+ {
+ filename: `${mailNewsDir}/27-plaintext+(HTML+embedded-image).eml`,
+ },
+ {
+ filename: `${mailNewsDir}/28-plaintext+HTML+attachment.eml`,
+ },
+ {
+ filename: `${mailNewsDir}/29-(HTML+embedded-image)+attachment.eml`,
+ },
+ // using windows-1252
+ {
+ filename: `${mailNewsDir}/30-plaintext+(HTML+embedded-image)+attachment.eml`,
+ encoding: "windows-1252",
+ },
+
+ // Bug 1669107
+ {
+ filename:
+ "data/plaintext-with-key-and-windows-1252-encoded-eml-attachment.eml",
+ encoding: "windows-1252",
+ skip: true,
+ },
+ {
+ filename: "data/plaintext-with-windows-1252-encoded-eml-attachment.eml",
+ encoding: "windows-1252",
+ skip: true,
+ },
+];
+
+/**
+ * Initialize OpenPGP add testing keys.
+ */
+add_setup(async function () {
+ do_get_profile();
+
+ await OpenPGPTestUtils.initOpenPGP();
+
+ await OpenPGPTestUtils.importPrivateKey(
+ null,
+ do_get_file(`${keyDir}/bob@openpgp.example-0xfbfcc82a015e7330-secret.asc`)
+ );
+
+ await OpenPGPTestUtils.importPublicKey(
+ null,
+ do_get_file(`${keyDir}/alice@openpgp.example-0xf231550c4f47e38e-pub.asc`)
+ );
+});
+
+/**
+ * Test the decrypted output of RNP.encryptOrSign() against its source text
+ * with various inputs.
+ */
+add_task(async function testEncryptAndOrSignResults() {
+ for (let test of tests) {
+ let chunks = test.filename.split("/");
+ let filename = chunks[chunks.length - 1];
+ if (test.skip) {
+ info(`Skipped input from: ${filename}`);
+ continue;
+ }
+
+ info(`Running test with input from: ${filename}`);
+
+ let buffer = await IOUtils.read(do_get_file(test.filename).path);
+ const textDecoder = new TextDecoder(test.encoding || "utf-8");
+
+ let sourceText = textDecoder.decode(buffer);
+ let encryptResult = {};
+
+ let encryptArgs = {
+ aliasKeys: new Map(),
+ armor: true,
+ bcc: [],
+ encrypt: true,
+ encryptToSender: true,
+ sender: "0xFBFCC82A015E7330",
+ senderKeyIsExternal: false,
+ sigTypeClear: false,
+ sigTypeDetached: false,
+ sign: false,
+ signatureHash: "SHA256",
+ to: ["<alice@openpgp.example>"],
+ };
+
+ let encrypted = await RNP.encryptAndOrSign(
+ sourceText,
+ encryptArgs,
+ encryptResult
+ );
+
+ Assert.ok(
+ !encryptResult.exitCode,
+ `${filename}: RNP.encryptAndOrSign() exited ok`
+ );
+
+ let decryptOptions = {
+ fromAddr: "bob@openpgp.example",
+ maxOutputLength: encrypted.length * 100,
+ noOutput: false,
+ uiFlags: EnigmailConstants.UI_PGP_MIME,
+ verifyOnly: false,
+ msgDate: null,
+ };
+
+ let { exitCode, decryptedData } = await RNP.decrypt(
+ encrypted,
+ decryptOptions
+ );
+
+ Assert.ok(!exitCode, `${filename}: RNP.decrypt() exited ok`);
+
+ Assert.equal(
+ sourceText,
+ decryptedData,
+ `${filename}: source text and decrypted text should be the same`
+ );
+ }
+});
+
+/**
+ * Test that we correctly produce binary files when decrypting,
+ * for both binary OpenPGP input and ASCII armored OpenPGP input.
+ *
+ * Image source: openclipart.org (public domain)
+ * https://openclipart.org/detail/191741/blue-bird
+ */
+add_task(async function testDecryptAttachment() {
+ let expected = String.fromCharCode(
+ ...(await IOUtils.read(do_get_file("data/bluebird50.jpg").path))
+ );
+
+ for (let filename of ["data/bluebird50.jpg.asc", "data/bluebird50.jpg.gpg"]) {
+ let encrypted = String.fromCharCode(
+ ...(await IOUtils.read(do_get_file(filename).path))
+ );
+ let options = {};
+ options.fromAddr = "";
+ options.msgDate = null;
+ let result = await RNP.decrypt(encrypted, options);
+
+ Assert.ok(!result.exitCode, `${filename}: RNP.decrypt() exited ok`);
+
+ // Don't use Assert.equal to avoid logging the raw binary data
+ let isEqual = expected === result.decryptedData;
+
+ Assert.ok(
+ isEqual,
+ `${filename}: decrypted data should match the expected binary file`
+ );
+ }
+});
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/test_secretKeys.js b/comm/mail/extensions/openpgp/test/unit/rnp/test_secretKeys.js
new file mode 100644
index 0000000000..772c5caae4
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/test_secretKeys.js
@@ -0,0 +1,384 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Tests for secret keys.
+ */
+
+"use strict";
+
+const { RNP, RnpPrivateKeyUnlockTracker } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/RNP.jsm"
+);
+const { OpenPGPMasterpass } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/masterpass.jsm"
+);
+const { EnigmailConstants } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/constants.jsm"
+);
+const { EnigmailKeyRing } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/keyRing.jsm"
+);
+const { FileUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/FileUtils.sys.mjs"
+);
+const { OpenPGPTestUtils } = ChromeUtils.import(
+ "resource://testing-common/mozmill/OpenPGPTestUtils.jsm"
+);
+
+const keyDir = "../../../../../test/browser/openpgp/data/keys";
+
+/**
+ * Initialize OpenPGP add testing keys.
+ */
+add_setup(async function () {
+ do_get_profile();
+
+ await OpenPGPTestUtils.initOpenPGP();
+});
+
+add_task(async function testSecretKeys() {
+ let pass = await OpenPGPMasterpass.retrieveOpenPGPPassword();
+ let newKeyId = await RNP.genKey(
+ "Erin <erin@example.com>",
+ "ECC",
+ 0,
+ 30,
+ pass
+ );
+
+ Assert.ok(
+ newKeyId != null && typeof newKeyId == "string",
+ "RNP.genKey() should return a non null string with a key ID"
+ );
+
+ let keyObj = EnigmailKeyRing.getKeyById(newKeyId);
+ Assert.ok(
+ keyObj && keyObj.secretAvailable,
+ "EnigmailKeyRing.getKeyById should return an object with a secret key"
+ );
+
+ let fpr = keyObj.fpr;
+
+ Assert.ok(
+ keyObj.iSimpleOneSubkeySameExpiry(),
+ "check iSimpleOneSubkeySameExpiry should succeed"
+ );
+
+ let allFingerprints = [fpr, keyObj.subKeys[0].fpr];
+
+ let keyTrackers = [];
+ for (let fp of allFingerprints) {
+ let tracker = RnpPrivateKeyUnlockTracker.constructFromFingerprint(fp);
+ await tracker.unlock();
+ keyTrackers.push(tracker);
+ }
+
+ let expiryChanged = await RNP.changeExpirationDate(
+ allFingerprints,
+ 100 * 24 * 60 * 60
+ );
+ Assert.ok(expiryChanged, "changeExpirationDate should return success");
+
+ for (let t of keyTrackers) {
+ t.release();
+ }
+
+ let backupPassword = "new-password-1234";
+
+ let backupKeyBlock = await RNP.backupSecretKeys([fpr], backupPassword);
+
+ let expectedString = "END PGP PRIVATE KEY BLOCK";
+
+ Assert.ok(
+ backupKeyBlock.includes(expectedString),
+ "backup of secret key should contain the string: " + expectedString
+ );
+
+ await RNP.deleteKey(fpr, true);
+
+ EnigmailKeyRing.clearCache();
+
+ keyObj = EnigmailKeyRing.getKeyById(newKeyId);
+ Assert.ok(
+ !keyObj,
+ "after deleting the key we should be unable to find it in the keyring"
+ );
+
+ let alreadyProvidedWrongPassword = false;
+
+ let getWrongPassword = function (win, keyId, resultFlags) {
+ if (alreadyProvidedWrongPassword) {
+ resultFlags.canceled = true;
+ return "";
+ }
+
+ alreadyProvidedWrongPassword = true;
+ return "wrong-password";
+ };
+
+ let importResult = await RNP.importSecKeyBlockImpl(
+ null,
+ getWrongPassword,
+ false,
+ backupKeyBlock
+ );
+
+ Assert.ok(importResult.exitCode != 0, "import should have failed");
+
+ let getGoodPassword = function (win, keyId, resultFlags) {
+ return backupPassword;
+ };
+
+ importResult = await RNP.importSecKeyBlockImpl(
+ null,
+ getGoodPassword,
+ false,
+ backupKeyBlock
+ );
+
+ Assert.ok(importResult.exitCode == 0, "import result code should be 0");
+
+ keyObj = EnigmailKeyRing.getKeyById(newKeyId);
+
+ Assert.ok(
+ keyObj && keyObj.secretAvailable,
+ "after import, EnigmailKeyRing.getKeyById should return an object with a secret key"
+ );
+});
+
+add_task(async function testImportSecretKeyIsProtected() {
+ let carolFile = do_get_file(
+ `${keyDir}/carol@example.com-0x3099ff1238852b9f-secret.asc`
+ );
+ let carolSec = await IOUtils.readUTF8(carolFile.path);
+
+ // Carol's secret key is protected with password "x".
+ let getCarolPassword = function (win, keyId, resultFlags) {
+ return "x";
+ };
+
+ let importResult = await RNP.importSecKeyBlockImpl(
+ null,
+ getCarolPassword,
+ false,
+ carolSec
+ );
+
+ Assert.equal(
+ importResult.exitCode,
+ 0,
+ "Should be able to import Carol's secret key"
+ );
+
+ let aliceFile = do_get_file(
+ `${keyDir}/alice@openpgp.example-0xf231550c4f47e38e-secret.asc`
+ );
+ let aliceSec = await IOUtils.readUTF8(aliceFile.path);
+
+ // Alice's secret key is unprotected.
+ importResult = await RNP.importSecKeyBlockImpl(null, null, false, aliceSec);
+
+ Assert.equal(
+ importResult.exitCode,
+ 0,
+ "Should be able to import Alice's secret key"
+ );
+
+ let [prot, unprot] = OpenPGPTestUtils.getProtectedKeysCount();
+ Assert.notEqual(prot, 0, "Should have protected secret keys");
+ Assert.equal(unprot, 0, "Should not have any unprotected secret keys");
+});
+
+add_task(async function testImportOfflinePrimaryKey() {
+ let importResult = await OpenPGPTestUtils.importPrivateKey(
+ null,
+ do_get_file(`${keyDir}/ofelia-secret-subkeys.asc`)
+ );
+
+ Assert.equal(
+ importResult[0],
+ "0x97DCDA5E56EBB822",
+ "expected key id should have been reported"
+ );
+
+ let primaryKey = await RNP.findKeyByEmail("<ofelia@openpgp.example>", false);
+
+ let encSubKey = RNP.getSuitableSubkey(primaryKey, "encrypt");
+ let keyId = RNP.getKeyIDFromHandle(encSubKey);
+ Assert.equal(
+ keyId,
+ "31C31DF1DFB67601",
+ "should obtain key ID of encryption subkey"
+ );
+
+ let sigSubKey = RNP.getSuitableSubkey(primaryKey, "sign");
+ let keyIdSig = RNP.getKeyIDFromHandle(sigSubKey);
+ Assert.equal(
+ keyIdSig,
+ "1BC8F5764D348FE1",
+ "should obtain key ID of signing subkey"
+ );
+
+ // Test that we can sign with a signing subkey
+ // (this ensures that our code can unlock the secret subkey).
+ // Ofelia's key has no secret key for the primary key available,
+ // which further ensures that signing used the subkey.
+
+ let sourceText = "we-sign-this-text";
+ let signResult = {};
+
+ let signArgs = {
+ aliasKeys: new Map(),
+ armor: true,
+ bcc: [],
+ encrypt: false,
+ encryptToSender: false,
+ sender: "0x97DCDA5E56EBB822",
+ senderKeyIsExternal: false,
+ sigTypeClear: true,
+ sigTypeDetached: false,
+ sign: true,
+ signatureHash: "SHA256",
+ to: ["<alice@openpgp.example>"],
+ };
+
+ await RNP.encryptAndOrSign(sourceText, signArgs, signResult);
+
+ Assert.ok(!signResult.exitCode, "signing with subkey should work");
+});
+
+add_task(async function testSecretForPreferredSignSubkeyIsMissing() {
+ let secBlock = await IOUtils.readUTF8(
+ do_get_file(
+ `${keyDir}/secret-for-preferred-sign-subkey-is-missing--a-without-second-sub--sec.asc`
+ ).path
+ );
+
+ let cancelPassword = function (win, keyId, resultFlags) {
+ resultFlags.canceled = true;
+ return "";
+ };
+
+ let importResult = await RNP.importSecKeyBlockImpl(
+ null,
+ cancelPassword,
+ false,
+ secBlock
+ );
+
+ Assert.ok(importResult.exitCode == 0);
+
+ let pubBlock = await IOUtils.readUTF8(
+ do_get_file(
+ `${keyDir}/secret-for-preferred-sign-subkey-is-missing--b-with-second-sub--pub.asc`
+ ).path
+ );
+
+ importResult = await RNP.importPubkeyBlockAutoAcceptImpl(
+ null,
+ pubBlock,
+ null // acceptance
+ );
+
+ Assert.ok(importResult.exitCode == 0);
+
+ let primaryKey = await RNP.findKeyByEmail(
+ "<secret-for-preferred-sign-subkey-is-missing@example.com>",
+ false
+ );
+
+ let signSubKey = RNP.getSuitableSubkey(primaryKey, "sign");
+ let keyId = RNP.getKeyIDFromHandle(signSubKey);
+ Assert.equal(
+ keyId,
+ "625D4819F02EE727",
+ "should obtain key ID of older, non-preferred subkey that has the secret key available"
+ );
+});
+
+// If we an existing public key, with multiple subkeys, and then we
+// import the secret key, but one of the existing public subkeys is
+// missing, test that we don't fail to import (bug 1795698).
+add_task(async function testNoSecretForExistingPublicSubkey() {
+ let pubBlock = await IOUtils.readUTF8(
+ do_get_file(`${keyDir}/two-enc-subkeys-still-both.pub.asc`).path
+ );
+
+ let importResult = await RNP.importPubkeyBlockAutoAcceptImpl(
+ null,
+ pubBlock,
+ null // acceptance
+ );
+
+ Assert.ok(importResult.exitCode == 0);
+
+ let secBlock = await IOUtils.readUTF8(
+ do_get_file(`${keyDir}/two-enc-subkeys-one-deleted.sec.asc`).path
+ );
+
+ let cancelPassword = function (win, keyId, resultFlags) {
+ resultFlags.canceled = true;
+ return "";
+ };
+
+ importResult = await RNP.importSecKeyBlockImpl(
+ null,
+ cancelPassword,
+ false,
+ secBlock
+ );
+
+ Assert.ok(importResult.exitCode == 0);
+});
+
+add_task(async function testImportAndBackupUntweakedECCKey() {
+ const untweakedFile = do_get_file(`${keyDir}/untweaked-secret.asc`);
+ const untweakedSecKey = await IOUtils.readUTF8(untweakedFile.path);
+
+ const getGoodPasswordForTweaked = function (win, keyId, resultFlags) {
+ return "pass112233";
+ };
+
+ const importResult = await RNP.importSecKeyBlockImpl(
+ null,
+ getGoodPasswordForTweaked,
+ false,
+ untweakedSecKey
+ );
+
+ Assert.ok(importResult.exitCode == 0);
+ const fpr = "492965A6F56DAD2423B3506E849F29B0020707F7";
+
+ const backupPassword = "new-password-1234";
+ const backupKeyBlock = await RNP.backupSecretKeys([fpr], backupPassword);
+ const expectedString = "END PGP PRIVATE KEY BLOCK";
+
+ Assert.ok(
+ backupKeyBlock.includes(expectedString),
+ "backup of secret key should contain the string: " + expectedString
+ );
+
+ await RNP.deleteKey(fpr, true);
+
+ EnigmailKeyRing.clearCache();
+});
+
+// Sanity check for bug 1790610 and bug 1792450, test that our passphrase
+// reading code, which can run through repair code for corrupted profiles,
+// will not replace our existing and good data.
+// Ideally this test should restart the application, but is is difficult.
+// We simulate a restart by erasing the cache and forcing it to read
+// data again from disk (which will run the consistency checks and
+// could potentially execute the repair code).
+add_task(async function testRereadingPassphrase() {
+ let pass1 = await OpenPGPMasterpass.retrieveOpenPGPPassword();
+ OpenPGPMasterpass.cachedPassword = null;
+ let pass2 = await OpenPGPMasterpass.retrieveOpenPGPPassword();
+ Assert.equal(
+ pass1,
+ pass2,
+ "openpgp passphrase should remain the same after cache invalidation"
+ );
+});
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/test_strip.js b/comm/mail/extensions/openpgp/test/unit/rnp/test_strip.js
new file mode 100644
index 0000000000..4260921ef2
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/test_strip.js
@@ -0,0 +1,137 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Tests stripping keys.
+ */
+
+"use strict";
+
+const { RNP } = ChromeUtils.import("chrome://openpgp/content/modules/RNP.jsm");
+const { EnigmailKeyRing } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/keyRing.jsm"
+);
+const { OpenPGPTestUtils } = ChromeUtils.import(
+ "resource://testing-common/mozmill/OpenPGPTestUtils.jsm"
+);
+const { MailStringUtils } = ChromeUtils.import(
+ "resource:///modules/MailStringUtils.jsm"
+);
+
+const keyDir = "../../../../../test/browser/openpgp/data/keys";
+
+/**
+ * Initialize OpenPGP add testing keys.
+ */
+add_setup(async function () {
+ do_get_profile();
+
+ await OpenPGPTestUtils.initOpenPGP();
+});
+
+add_task(async function testStripSignatures() {
+ await OpenPGPTestUtils.importPublicKey(
+ null,
+ do_get_file(`${keyDir}/heisenberg-signed-by-pinkman.asc`)
+ );
+
+ let heisenbergFpr = "8E3D32E652A254F05BEA9F66CF3EB4AFCAC29340";
+ let foundKeys = await RNP.getKeys(["0x" + heisenbergFpr]);
+
+ Assert.equal(foundKeys.length, 1);
+
+ let sigs = RNP.getKeyObjSignatures(foundKeys[0]);
+
+ // Signatures for one user ID
+ Assert.equal(sigs.length, 1);
+
+ // The key in the file has two signatures: one self signature,
+ // plus one foreign certification signature.
+ Assert.equal(sigs[0].sigList.length, 2);
+
+ let reducedKey = RNP.getMultiplePublicKeys([], ["0x" + heisenbergFpr], []);
+
+ // Delete the key we have previously imported
+ await RNP.deleteKey(heisenbergFpr);
+ foundKeys = await RNP.getKeys(["0x" + heisenbergFpr]);
+ Assert.equal(foundKeys.length, 0);
+
+ // Import the reduced key
+ let errorObj = {};
+ let fingerPrintObj = {};
+ let result = await EnigmailKeyRing.importKeyAsync(
+ null,
+ false,
+ reducedKey,
+ false,
+ null,
+ errorObj,
+ fingerPrintObj,
+ false,
+ [],
+ false
+ );
+ Assert.equal(result, 0);
+
+ foundKeys = await RNP.getKeys(["0x" + heisenbergFpr]);
+ Assert.equal(foundKeys.length, 1);
+
+ sigs = RNP.getKeyObjSignatures(foundKeys[0]);
+
+ // The imported stripped key should have only the self signature.
+ Assert.equal(sigs[0].sigList.length, 1);
+});
+
+add_task(async function testKeyWithUnicodeComment() {
+ let keyFile = do_get_file(`${keyDir}/key-with-utf8-comment.asc`);
+ let keyBlock = await IOUtils.readUTF8(keyFile.path);
+
+ let errorObj = {};
+ let fingerPrintObj = {};
+ let result = await EnigmailKeyRing.importKeyAsync(
+ null,
+ false,
+ keyBlock,
+ false,
+ null,
+ errorObj,
+ fingerPrintObj,
+ false,
+ [],
+ false
+ );
+ Assert.equal(result, 0);
+
+ let fpr = "72514F43D0060FC588E80238852C55E6D2AFD7EF";
+ let foundKeys = await RNP.getKeys(["0x" + fpr]);
+
+ Assert.equal(foundKeys.length, 1);
+});
+
+add_task(async function testBinaryKey() {
+ let keyFile = do_get_file(`${keyDir}/key-binary.gpg`);
+ let keyData = await IOUtils.read(keyFile.path);
+ let keyBlock = MailStringUtils.uint8ArrayToByteString(keyData);
+
+ let errorObj = {};
+ let fingerPrintObj = {};
+ let result = await EnigmailKeyRing.importKeyAsync(
+ null,
+ false,
+ keyBlock,
+ true,
+ null,
+ errorObj,
+ fingerPrintObj,
+ false,
+ [],
+ false
+ );
+ Assert.equal(result, 0);
+
+ let fpr = "683F775BA2E5F0ADEBB29697A2D1B914F722004E";
+ let foundKeys = await RNP.getKeys(["0x" + fpr]);
+
+ Assert.equal(foundKeys.length, 1);
+});
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/test_uid.js b/comm/mail/extensions/openpgp/test/unit/rnp/test_uid.js
new file mode 100644
index 0000000000..b87e068e0d
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/test_uid.js
@@ -0,0 +1,132 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Tests for OpenPGP encryption alias rules.
+ */
+
+"use strict";
+
+const { OpenPGPTestUtils } = ChromeUtils.import(
+ "resource://testing-common/mozmill/OpenPGPTestUtils.jsm"
+);
+const { EnigmailFuncs } = ChromeUtils.import(
+ "chrome://openpgp/content/modules/funcs.jsm"
+);
+
+const tests = [
+ {
+ input: "Cherry Blossom (桜の花) (description) <email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input:
+ "Cherry Blossom (桜の花) (description) (more information) <email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input: "First Last <email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input: "Last, First <email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input: "email@example.com",
+ email: "email@example.com",
+ },
+ {
+ input: "<email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input: "First Last email@example.com>",
+ email: "",
+ },
+ {
+ input: "First Last (comment) <email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input: "First Last (a) (b) (c) (comment) <email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input: "First Last (comment <email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input: "First Last )comment) <email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input: "",
+ email: "",
+ },
+ {
+ input: "First Last () <>",
+ email: "",
+ },
+ {
+ input: "First Last () <> <> <>",
+ email: "",
+ },
+ {
+ input: "First Last () <> <email1@example.com>",
+ email: "",
+ },
+ {
+ input: "First <Last> (comment) <email1@example.com>",
+ email: "",
+ },
+ {
+ input: "First Last <email@example.com> (bad comment)",
+ email: "email@example.com",
+ },
+ {
+ input: "First Last <email@example.com> extra text",
+ email: "email@example.com",
+ },
+ {
+ input: "First Last <not-an-email> extra text",
+ email: "",
+ },
+ {
+ input: "First Last (comment (nested)) <email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input:
+ "First Last (comment (no second closing bracket) <email@example.com>",
+ email: "email@example.com",
+ },
+ {
+ input: "<a@example.org b@example.org>",
+ email: "",
+ },
+ {
+ input: "<a@@example.org>",
+ email: "",
+ },
+];
+
+/**
+ * Initialize OpenPGP add testing keys.
+ */
+add_setup(async function () {
+ do_get_profile();
+
+ await OpenPGPTestUtils.initOpenPGP();
+});
+
+add_task(async function testAlias() {
+ for (let test of tests) {
+ console.debug("testing input: " + test.input);
+
+ let email = EnigmailFuncs.getEmailFromUserID(test.input);
+
+ Assert.equal(test.email, email);
+ }
+});
diff --git a/comm/mail/extensions/openpgp/test/unit/rnp/xpcshell.ini b/comm/mail/extensions/openpgp/test/unit/rnp/xpcshell.ini
new file mode 100644
index 0000000000..f0601aefae
--- /dev/null
+++ b/comm/mail/extensions/openpgp/test/unit/rnp/xpcshell.ini
@@ -0,0 +1,14 @@
+[DEFAULT]
+head =
+tail =
+support-files =
+ ../../../../../test/browser/openpgp/data/keys/*
+ ../../../../../../mailnews/test/data/*
+ data/*
+
+[test_encryptAndOrSign.js]
+[test_secretKeys.js]
+[test_alias.js]
+[test_badKeys.js]
+[test_uid.js]
+[test_strip.js]