Closed Bug 1671834 Opened 4 years ago Closed 4 years ago

How to import a PGP key to an identity via Javascript

Categories

(Thunderbird :: Security, enhancement)

enhancement

Tracking

(Not tracked)

RESOLVED WORKSFORME

People

(Reporter: it_support, Unassigned)

Details

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36

Steps to reproduce:

I should have posted this on the official forum, but it seems there is no way to post a new topic there.

I am importing many accounts in bulk via JS executed on the Error Console, but i can't figure out how to add the PGP keys to the identities via JS.
The keys have been already created via GnuPG, with the same email addresses i am importing to Thunderbird, and they have been saved to .asc files ready to be imported.

This is my code:

[CODE]

var hostname = "my.hostname.com";
var pop3Port = 995;
var smtpPort = 587;

(function () {

var arr = [
["user@domain.com", "name", "secret"],
// more credentials here...
];

var accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"].
getService(Components.interfaces.nsIMsgAccountManager);

for (var i = 0; i < arr.length; i++) {

// SMTP
var smtpServer = MailServices.smtp.createServer();
smtpServer.username = arr[i][0];
    smtpServer.hostname = hostname;
	smtpServer.password = arr[i][2];
    smtpServer.description = smtpServer.username;
    smtpServer.port = smtpPort;
    smtpServer.socketType = 3; // Components.interfaces.nsMsgSocketType.SSL;
    smtpServer.authMethod = 3; // normal password
    if (!MailServices.smtp.defaultServer ||
        !MailServices.smtp.defaultServer.hostname) {
      MailServices.smtp.defaultServer = smtpServer;
    }

// POP3 	
var username = arr[i][0];
var type = "pop3"; // imap or pop3
var incomingServer = accountManager.createIncomingServer(username, hostname, type);
incomingServer.port = pop3Port;
incomingServer.socketType = 3; // Components.interfaces.nsMsgSocketType.SSL;
incomingServer.authMethod = 3; // normal password
incomingServer.password = arr[i][2];
incomingServer.loginAtStartUp = true; // [check] Check for new messages at startup
incomingServer.doBiff = true;         // [check] Check for new messages every    minutes
incomingServer.biffMinutes = 15;      //         Check for new messages every 15 minutes
incomingServer.prettyName = username;
incomingServer.valid = true;
var identity = accountManager.createIdentity();
identity.fullName = arr[i][1];
identity.email = username;
identity.valid = true;
identity.smtpServerKey = smtpServer.key;
// TODO: how to import PGP key here?
var account = accountManager.createAccount();
account.addIdentity(identity);
account.incomingServer = incomingServer;
if (!accountManager.defaultAccount) {
  accountManager.defaultAccount = account;
}

}

})();
[/CODE]

Expected results:

The code works, but i also need to import the PGP key to the identity

Summary: How to link a PGP key to an identity via Javascript → How to import a PGP key to an identity via Javascript

Sorry i messed up with the code formatting, i am pasting the code here again:

 var hostname = "my.hostname.com";  
 var pop3Port = 995;
 var smtpPort = 587;


 (function () {

   var arr = [
     ["user@domain.com", "name", "secret"], 
    // more credentials here...
   ];

    var accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"].getService(Components.interfaces.nsIMsgAccountManager);

    for (var i = 0; i < arr.length; i++) {
  
  	    // SMTP
  	    var smtpServer = MailServices.smtp.createServer();
          smtpServer.username = arr[i][0];
          smtpServer.hostname = hostname;
  		smtpServer.password = arr[i][2];
          smtpServer.description = smtpServer.username;
          smtpServer.port = smtpPort;
          smtpServer.socketType = 3; // Components.interfaces.nsMsgSocketType.SSL;
          smtpServer.authMethod = 3; // normal password
          if (!MailServices.smtp.defaultServer ||
              !MailServices.smtp.defaultServer.hostname) {
            MailServices.smtp.defaultServer = smtpServer;
          }

        	// POP3 	
      var username = arr[i][0];
      var type = "pop3"; // imap or pop3
      var incomingServer = accountManager.createIncomingServer(username, hostname, type);
      incomingServer.port = pop3Port;
      incomingServer.socketType = 3; // Components.interfaces.nsMsgSocketType.SSL;
      incomingServer.authMethod = 3; // normal password
  	  incomingServer.password = arr[i][2];
      incomingServer.loginAtStartUp = true; // [check] Check for new messages at startup
      incomingServer.doBiff = true;         // [check] Check for new messages every    minutes
      incomingServer.biffMinutes = 15;      //         Check for new messages every 15 minutes
      incomingServer.prettyName = username;
      incomingServer.valid = true;
      var identity = accountManager.createIdentity();
      identity.fullName = arr[i][1];
      identity.email = username;
      identity.valid = true;
  	  identity.smtpServerKey = smtpServer.key;
      // TODO: how to import PGP key here?
      var account = accountManager.createAccount();
      account.addIdentity(identity);
      account.incomingServer = incomingServer;
      if (!accountManager.defaultAccount) {
        accountManager.defaultAccount = account;
      }
	

    }

  })();

Sorry bugzilla is not an add-on support forum. You can check searchfox for some inspiration: https://searchfox.org/comm-central/source/mail/extensions/am-e2e/am-e2e.js

Actually the methods to be called are already integrated into Thunderbird 78+, so it's not about an add-on.
Anyway i have figured out how to add a PGP key to Thunderbird, in case anyone finds it useful:

var pcUser = "Administrator"; // <== Put your Windows user name
var privateKeysFolder = "C:\\Users\\" + pcUser + "\\Desktop\\gpg-private-keys"; // <== place your priv keys here!

Components.utils.import("resource://gre/modules/FileUtils.jsm");
var EnigmailKeyRing = ChromeUtils.import("chrome://openpgp/content/modules/keyRing.jsm").EnigmailKeyRing;

function importSecretKeyFromFile(filename){
	var file = new FileUtils.File(filename);
	let resultKeys = {};
	let errorMsgObj = {};
	EnigmailKeyRing.importKeyFromFile(
		window,
		function(win, fpr, userFlags){ resultFlags.canceled = false; return ""; }, // <== returns key passphrase, if any
		file,
		errorMsgObj,
		resultKeys,
		false,
		true);
	return resultKeys.keys[0];
}

var k = importSecretKeyFromFile(privateKeysFolder + "\\privatekey_email@example.com.asc");
console.log("imported key id::" + k);

I just need to associate the imported key to an identity now. Will get back soon

I have tried associating a PGP key to a newly created identity via JS, using Services.prefs.setStringPref

var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
......
......
var k = importSecretKeyFromFile(privateKeysFolder + "\\privatekey.asc");	// works
k = k.substring(2); // remove the leading "0x" from the key id
console.log("setStringPref mail.identity." + identity.key + ".openpgp_key_id = " + k);
Services.prefs.setStringPref( "mail.identity." + identity.key + ".openpgp_key_id", k ); // associate this pgp key with identity... won't work

But it has no effect. From the identity manager popup of the Thunderbird UI i don't see any PGP key for the identity, under "End-to-end cryptography" tab.
I have even tried leaving the leading "0x" in the key id, it's the same.

I see the PGP key in the OpenPGP key manager popup though, and the email of the key matches with
identity.email

What am i missing? Thanks

I think i figured it out:

...
...
...

Components.utils.import("resource://gre/modules/FileUtils.jsm");
var EnigmailFiles = ChromeUtils.import("chrome://openpgp/content/modules/files.jsm").EnigmailFiles;
var EnigmailKey = ChromeUtils.import("chrome://openpgp/content/modules/key.jsm").EnigmailKey;
var EnigmailKeyRing = ChromeUtils.import("chrome://openpgp/content/modules/keyRing.jsm").EnigmailKeyRing;
var { PgpSqliteDb2 } = ChromeUtils.import( "chrome://openpgp/content/modules/sqliteDb.jsm" );
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");

function importSecretKeyFromFile(filename){
var file = new FileUtils.File(filename);
let resultKeys = {};
let errorMsgObj = {};
EnigmailKeyRing.importKeyFromFile(
window,
function(win, fpr, userFlags){ resultFlags.canceled = false; return ""; },
file,
errorMsgObj,
resultKeys,
false,
true);
if(resultKeys.keys.length == 0) return [];
let keyBlockStr = EnigmailFiles.readFile(file);
resultKeys = EnigmailKey.getKeyListFromKeyBlock(
keyBlockStr,
errorMsgObj,
interactive = false,
false,
true );
PgpSqliteDb2.acceptAsPersonalKey(resultKeys[0].fpr);
return resultKeys[0].id;
}

...
...
...
var k = importSecretKeyFromFile(privateKeysFolder + "\privatekey_" + username + ".asc");
Services.prefs.setStringPref( "mail.identity." + identity.key + ".openpgp_key_id", k ); // associate this pgp key with identity

Status: UNCONFIRMED → RESOLVED
Closed: 4 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.