Использование надувного замка для создания публичного ключа PGP, используемого Thunderbird
Я создал публичный и частный PGP
ключи с использованием org.bouncycastle.openpgp.PGPKeyRingGenerator. После внесения изменений, предложенных GregS, открытый ключ .asc
файл, а закрытый ключ .skr
файл. Мне нужно распространить открытый ключ сначала пользователям Thunderbird, а затем пользователям Outlook и других почтовых клиентов. Я прочитал эти инструкции для получения открытого ключа в Thunderbird, но инструкции просто указывают .asc
расширение без указания содержания / структуры .asc
файл.
Как настроить так, чтобы мой (измененный?) Код ниже создал открытый ключ, который может использоваться удаленными пользователями Thunderbird для отправки зашифрованных писем, которые затем могут быть расшифрованы моим личным ключом, также созданным (измененным?) Кодом ниже? Принятый ответ будет включать в себя пошаговые инструкции не только для внесения необходимых изменений в приведенный ниже код, но также для настройки каждого удаленного пользователя Thunderbird на использование генерируемого ниже открытого ключа для отправки электронных писем, которые могут быть расшифрованы с помощью закрытый ключ в моем приложении, созданный (измененным?) кодом ниже.
Вот мой первый набросок кода, генерирующего ключи:
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Date;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.bcpg.HashAlgorithmTags;
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.bouncycastle.bcpg.sig.Features;
import org.bouncycastle.bcpg.sig.KeyFlags;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.openpgp.PGPEncryptedData;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor;
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyEncryptorBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair;
public class RSAGen {
public static void main(String args[]) throws Exception {
char pass[] = {'h', 'e', 'l', 'l', 'o'};
PGPKeyRingGenerator krgen = generateKeyRingGenerator("alice@example.com", pass);
// Generate public key ring, dump to file.
PGPPublicKeyRing pkr = krgen.generatePublicKeyRing();
ArmoredOutputStream pubout = new ArmoredOutputStream(new BufferedOutputStream(new FileOutputStream("/home/user/dummy.asc")));
pkr.encode(pubout);
pubout.close();
// Generate private key, dump to file.
PGPSecretKeyRing skr = krgen.generateSecretKeyRing();
BufferedOutputStream secout = new BufferedOutputStream(new FileOutputStream("/home/user/dummy.skr"));
skr.encode(secout);
secout.close();
}
public final static PGPKeyRingGenerator generateKeyRingGenerator(String id, char[] pass) throws Exception{
return generateKeyRingGenerator(id, pass, 0xc0);
}
// Note: s2kcount is a number between 0 and 0xff that controls the number of times to iterate the password hash before use. More
// iterations are useful against offline attacks, as it takes more time to check each password. The actual number of iterations is
// rather complex, and also depends on the hash function in use. Refer to Section 3.7.1.3 in rfc4880.txt. Bigger numbers give
// you more iterations. As a rough rule of thumb, when using SHA256 as the hashing function, 0x10 gives you about 64
// iterations, 0x20 about 128, 0x30 about 256 and so on till 0xf0, or about 1 million iterations. The maximum you can go to is
// 0xff, or about 2 million iterations. I'll use 0xc0 as a default -- about 130,000 iterations.
public final static PGPKeyRingGenerator generateKeyRingGenerator(String id, char[] pass, int s2kcount) throws Exception {
// This object generates individual key-pairs.
RSAKeyPairGenerator kpg = new RSAKeyPairGenerator();
// Boilerplate RSA parameters, no need to change anything
// except for the RSA key-size (2048). You can use whatever key-size makes sense for you -- 4096, etc.
kpg.init(new RSAKeyGenerationParameters(BigInteger.valueOf(0x10001), new SecureRandom(), 2048, 12));
// First create the master (signing) key with the generator.
PGPKeyPair rsakp_sign = new BcPGPKeyPair(PGPPublicKey.RSA_SIGN, kpg.generateKeyPair(), new Date());
// Then an encryption subkey.
PGPKeyPair rsakp_enc = new BcPGPKeyPair(PGPPublicKey.RSA_ENCRYPT, kpg.generateKeyPair(), new Date());
// Add a self-signature on the id
PGPSignatureSubpacketGenerator signhashgen = new PGPSignatureSubpacketGenerator();
// Add signed metadata on the signature.
// 1) Declare its purpose
signhashgen.setKeyFlags(false, KeyFlags.SIGN_DATA|KeyFlags.CERTIFY_OTHER);
// 2) Set preferences for secondary crypto algorithms to use when sending messages to this key.
signhashgen.setPreferredSymmetricAlgorithms
(false, new int[] {
SymmetricKeyAlgorithmTags.AES_256,
SymmetricKeyAlgorithmTags.AES_192,
SymmetricKeyAlgorithmTags.AES_128
});
signhashgen.setPreferredHashAlgorithms
(false, new int[] {
HashAlgorithmTags.SHA256,
HashAlgorithmTags.SHA1,
HashAlgorithmTags.SHA384,
HashAlgorithmTags.SHA512,
HashAlgorithmTags.SHA224,
});
// 3) Request senders add additional checksums to the message (useful when verifying unsigned messages.)
signhashgen.setFeature(false, Features.FEATURE_MODIFICATION_DETECTION);
// Create a signature on the encryption subkey.
PGPSignatureSubpacketGenerator enchashgen = new PGPSignatureSubpacketGenerator();
// Add metadata to declare its purpose
enchashgen.setKeyFlags(false, KeyFlags.ENCRYPT_COMMS|KeyFlags.ENCRYPT_STORAGE);
// Objects used to encrypt the secret key.
PGPDigestCalculator sha1Calc = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA1);
PGPDigestCalculator sha256Calc = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA256);
// bcpg 1.48 exposes this API that includes s2kcount. Earlier versions use a default of 0x60.
PBESecretKeyEncryptor pske = (new BcPBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256, sha256Calc, s2kcount)).build(pass);
// Finally, create the keyring itself. The constructor takes parameters that allow it to generate the self signature.
PGPKeyRingGenerator keyRingGen =
new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, rsakp_sign,
id, sha1Calc, signhashgen.generate(), null,
new BcPGPContentSignerBuilder(rsakp_sign.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1), pske);
// Add our encryption subkey, together with its signature.
keyRingGen.addSubKey(rsakp_enc, enchashgen.generate(), null);
return keyRingGen;
}
}
Когда я запускаю приведенный выше код для генерации .asc
файл, а затем попробуйте импортировать .asc
файл в Thunderbird, я получаю следующее сообщение об ошибке:
Обратите внимание, что я не установил GnuPG на моем компьютере CentOS 7.
Кроме того, вы можете легко воссоздать эту проблему на своем компьютере, потому что Thunderbird бесплатен. Вы можете скачать Thunderbird бесплатно по этой ссылке. Как вариант, на моем CentOS 7
машина, я скачал Thunderbird с yum install thunderbird
, Вы можете скачать надувной замок, добавив следующее в ваш pom.xml
:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk15on</artifactId>
<version>1.51</version>
</dependency>
EDIT # 1:
Чтобы ответить на вопросы JRichardSnape, я обнаружил, что Maven также должен автоматически загружать org.bouncycastle.crypto
библиотека, потому что это зависимость bcpg-jdk15on
, JRichardSnape правильно, что RSAKeyGenerationParameters
а также RSAKeyPairGenerator
не в bcpg-jdk15on.jar
скачать руководство. (Примечание: версии в ссылках могут быть неактуальными.) Однако оба класса находятся в автоматической загрузке maven, которая получается в результате фрагмента одной зависимости от pom.xml
показано выше. Я говорю это, потому что нет другого bouncycastle
зависимости в моем pom.xml
, Я использую Java 7.
Eclipse описывает два класса, импортированных как:
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
Я добавил все import
заявления от RSAGen.java
к фрагменту кода в моем OP выше. Я думаю, что проблема может быть связана с необходимостью имени / подписи для ключа.
Поиск этой ошибки в Google приводит к следующим ссылкам:
Конвертировать userId в UTF8 перед генерацией подписи № 96
символы не ascii в поле Имя #92
Невозможно импортировать сертификат PGP в связку ключей
EDIT#2
По совету @JRichardSnape я пытался Enigmail->Key management ->File ->Import keys from file
, Это привело к следующему диалоговому окну, которое, кажется, указывает, что, хотя ключ был импортирован, ключ не был подписан. Таким образом, кажется, что нет имени или адреса электронной почты, связанных с .asc
файл, который был импортирован. Ключ также не отображается в списке ключей EnigMail впоследствии.
EDIT # 3
С помощью gpg --gen-key
Мне удалось заставить терминал CentOS 7 создать пару ключей, включая открытый ключ, который я смог успешно импортировать в Thunderbird, так что теперь Thunderbird может связать открытый ключ, созданный терминал-gpg, с предполагаемым получателем электронной почты. Но когда я предпринимаю все шаги для отправки зашифрованной электронной почты из Thunderbird с использованием открытого ключа, электронная почта и ее вложения, тем не менее, приходят в незашифрованном виде. Шаги, которые я предпринял для отправки зашифрованной электронной почты с открытым ключом с удаленного Thunderbird на сервер с закрытым ключом, описаны в этой публикации SuperUser.
При условии gpg --gen-key
Кажется, работает, главная остающаяся проблема в настоящее время, кажется, часть Thunderbird в этом вопросе щедрости. Я опубликовал большой прогресс в решении проблемы с Thunderbird в вопросе SuperUser в предыдущем абзаце. Ваша помощь в ответе на этот вопрос также будет иметь большое значение для ответа на этот вопрос.
EDIT # 4
Я до сих пор не могу получить BouncyCastle
созданный ключ для импорта в Thunderbird. Тем не менее, когда я использую ключи, созданные на CentOS 7
использование терминала gpg --gen-key
Я могу выполнить следующие шаги:
1.) I configured my Thunderbird to manage another (second)
email account I have not been using.
2.) I then created a gpg key for that second account and
configured encryption for that second account in Thunderbird.
3.) I sent an encrypted email containing an attachment from the
first Thunderbird account to the second Thunderbird account.
4.) I was able to see that the attachment remained encrypted in
the second account's inbox until I used the recipient key's
passphrase to decrypt it.
мой CentOS 7
Сервер по-прежнему создает незашифрованные вложения, когда я отправляю ему электронное письмо из той же "первой" учетной записи Thunderbird, как описано в этом редактировании. Я пытаюсь определить, происходит ли это из-за некоторого "автошифрования" в dovecot
/ postfix
/ mailx
/ gpg
в CentOS 7
сервер, или это связано с некоторыми настройками в отправителе Thunderbird. Я исследую это.
1 ответ
Я постараюсь обратиться к этим пунктам один за другим:
Генерация ключей Java
Java-код работает и создает полезную пару ключей. Я проверил это с различными электронными письмами и различными паролями без проблем. У меня была третья сторона, которая отправила мне электронное письмо с использованием открытого ключа и успешно расшифровала его с помощью закрытого ключа, сгенерированного этим кодом Java. Ключ работал со следующими комбинациями
- Thunderbird (31.4.0) + Enigmail (1.7.2) + gpg (Gpg4win) в Windows 8
- Thunderbird + Enigmail в Ubuntu 14.10 (с менеджером рабочего стола xfer)
тем не мение
ОП находит проблему при импорте ключей со сбоем, подразумевая, что в CentOS / Thunderbird / pgp
сочетание. Аналогично, его не удалось импортировать с ошибкой, сообщающей, что идентификатор пользователя не установлен на Windows / Outlook / Kleopatra
Плагин (проверено, хотя вопрос конкретно цитирует Thunderbird).
Я не могу воспроизвести ошибку - сильно подозреваю, что это связано либо с различиями конфигурации, либо с различиями версий в GNU PG. Моя настройка показывает следующее для gpg --version
gpg (GnuPG) 2.0.26 (Gpg4win 2.2.3)
libgcrypt 1.6.2
Тестирование Java сгенерированного ключа с помощью gpg напрямую
Вы можете сгенерировать ключи с помощью кода Java, перейти в командную строку и выполнить
gpg --import dummy.asc
Затем выполните тест, выполнив
gpg --edit-key alice@example.com
проверьте, есть ли у него идентификатор пользователя, набрав check
на gpg>
незамедлительный. Образец вывода:
uid alice@example.com
sig!3 14AEE94A 2015-02-05 [self-signature]
Если это работает - вы устранили проблему с gpg при импорте ключей - проверьте версии Thunderbird / Enigmail.
Использование Thunderbird
Кажется, что большинство проблем были решены моим комментарием, рекомендующим импорт ключей через Enigmail->Key management ->File ->Import keys from file
в сочетании с этим связанным вопросом от ОП на суперпользователя.
Также обратите внимание - в диалоге управления ключами для Enigmail есть опция "генерировать". Если генерация Java не требуется, это может быть использовано для генерации пар ключей - это, в общем-то, то же самое, что генерация напрямую через gpg, насколько мне известно.
Остающаяся проблема с использованием Thunderbird, по-видимому, заключается в отсутствии уверенности в шифровании, поскольку сообщение появляется в виде простого текста на сервере OP (кажется, что ключ должен использоваться в комбинации сервер / клиент, где клиенты отправляют зашифрованные электронные письма сервер).
Чтобы получить уверенность в том, что сообщение действительно зашифровано, я предлагаю изменить настройку Enigmail:
Enigmail
->Preference
->Sending tab
- Выбрать
"Manual encryption settings"
- Выбрать
"Always"
в"confirm before sending"
коробка
Затем вы увидите зашифрованную почту вместе с ящиком с сообщением, прежде чем оно будет отправлено.
Я не могу говорить о том, как остановить ваш сервер для автоматического дешифрования входящей почты, так как это зависит от конфигурации вашего сервера, и его лучше задать в качестве отдельного вопроса, вполне возможно, на сайтах StackExchange с правами суперпользователя или сервера.
Тестирование электронной почты PGP
Вы также можете подумать о том, чтобы последовать совету из учебника по Enigmail и отправить зашифрованное письмо
Адель, "Дружелюбный почтовый робот OpenPGP". Адель принимает сообщения OpenPGP и дает пояснительные ответы на любые сообщения OpenPGP.
Адрес adele <at> gnupp <dot> de