Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Подскажите мне про PGP шифрование с помощью Bouncy castle / 10 сообщений из 10, страница 1 из 1
18.10.2016, 13:52
    #39328960
RuslanGab
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите мне про PGP шифрование с помощью Bouncy castle
Сразу оговорюсь: я совершенный новичок в этом вопросе так что не ругайтесь шибко...

Итак, возникла необходимость в шифровке отправляемых писем с помощью PGP. Гугл подсказал что самая популярная бесплатная библиотека для данных целей на сегодня Bouncy castle, которая соответственно была выбрана.

Письмо (с приложениями, что важно в моем случае) создается таким незатейливым способом:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
            MimeMessage msg = mailSender.createMimeMessage();
            try {
                MimeMessageHelper helper = new MimeMessageHelper(msg, true);
                helper.setFrom("from@from.com");
                helper.setTo("to@to.com");
                helper.setSubject("ENCRYPTED MAIL TEST");
                helper.setText(BouncyCrypt.encryptString(                                    
                                    "crypted mail test text...", 
                                    BouncyCrypt.readPublicKey("G:\\public_key\\encrypt.asc")));
                helper.addAttachment("attachment.txt", new File(filePath")); 
                
                mailSender.send(msg);
                
            } catch(MessagingException | MailException ex) {
                ex.printStackTrace();
            }



Тут сам текст кодируется. Метод таков:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
    public static String encryptString(String clearData, PGPPublicKey encKey) throws IOException, NoSuchProviderException, PGPException {
        return new String(encryptBytes(clearData.getBytes(), encKey));
    }    
    
    
    private static byte[] encryptBytes(byte[] clearData, PGPPublicKey encKey) throws IOException, NoSuchProviderException, PGPException {
        String fileName = PGPLiteralData.CONSOLE;
        
        ByteArrayOutputStream encOut = new ByteArrayOutputStream();
        OutputStream out = new ArmoredOutputStream(encOut);
        
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();

        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedDataGenerator.ZIP);
        
        OutputStream cos = comData.open(bOut);
        PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();

        OutputStream pOut = lData.open(
                cos,
                PGPLiteralData.BINARY, fileName,
                clearData.length,
                new java.util.Date()
                );
        pOut.write(clearData);

        lData.close();
        comData.close();
        
        JcePGPDataEncryptorBuilder c = new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(true).setSecureRandom(new SecureRandom()).setProvider("BC");        
        PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(c);        

        cPk.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider(new BouncyCastleProvider()).setSecureRandom(new SecureRandom()));

        byte[] bytes = bOut.toByteArray();

        OutputStream cOut = cPk.open(out, bytes.length);

        cOut.write(bytes); // obtain the actual bytes from the compressed stream

        cOut.close();

        out.close();

        return encOut.toByteArray();
    }   



Ну и ключ достается таким образом:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
    static PGPPublicKey readPublicKey(String fileName) throws IOException, PGPException
    {
        PGPPublicKey pubKey;
        try (InputStream keyIn = new BufferedInputStream(new FileInputStream(fileName))) {
            pubKey = readPublicKey(keyIn);
        }
        return pubKey;
    }



Вышенаписанное работает ожидаемым образом. Письма приходят - почтовик просит пароль к приватному ключу и их показывает. Мир да благодать, но это увы не все.

Далее встает вопрос о шифровании приложений. Для этой цели создан вот такой метод:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
public static void encryptFile(OutputStream out, String fileName, PGPPublicKey encKey, boolean armor, boolean withIntegrityCheck) throws IOException, NoSuchProviderException, PGPException {
    	
        Security.addProvider(new BouncyCastleProvider());

        if (armor) { out = new ArmoredOutputStream(out); }

        ByteArrayOutputStream bOut = new ByteArrayOutputStream();

        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);

        PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));

        comData.close();

        JcePGPDataEncryptorBuilder c = new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC");
        
        PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(c);
        
        JcePublicKeyKeyEncryptionMethodGenerator d = new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider(new BouncyCastleProvider()).setSecureRandom(new SecureRandom());

        cPk.addMethod(d);

        byte[] bytes = bOut.toByteArray();

        OutputStream cOut = cPk.open(out, bytes.length);

        cOut.write(bytes);

        cOut.close();

        out.close();
    }


Метод сам по себе тоже как будто работает - файл получается зашифрованный. Если сохранить его на диск и дешифровать скажем в кассандре (под виндой) содержимое файла "восстанавливается".

ОДНАКО все вместе не работает. Т.е. если отправить письмо с зашифрованным текстом и вложением, то "почтовик" у клиента дешифрует только текст - вложение остается зашифрованным, что не происходит если отправить аналогичное письмо зашифрованным из почтовой программы. Вопрос: что не так?

В голове витает мысль что шифровать наверное стоит не "части", а MimeMessage все в целом, однако добиться этого пока не выходит. Нашел несколько примеров с шифрованием MessageBody, однако там используется некий Х509 сертификат (я так понимаю чтобы подписать это), чего мне не нужно. Без него не проходит (ну или я неверно попытался). Ткните пожалуйста что посмотреть!

Заранее огромное спасибо.
...
Рейтинг: 0 / 0
18.10.2016, 14:57
    #39329012
Andrei T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите мне про PGP шифрование с помощью Bouncy castle
Рекомендую сравнить письма, в частности заголовки Content-Type тела и аттачментов и наличие отметок о начале/конце PGP.
...
Рейтинг: 0 / 0
18.10.2016, 15:15
    #39329020
RuslanGab
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите мне про PGP шифрование с помощью Bouncy castle
Andrei T,
Спасибо уже за то что дочитали так много до конца:)
Попробую посмотреть с этого бока...

Так выглядит сообщение, зашифрованное средствами "почтовика":

...
Content-Type: multipart/mixed;
boundary="------------070003080703070604020509"
This is a multi-part message in MIME format.
--------------070003080703070604020509
Content-Type: text/plain; charset=ISO-8859-15
Content-Transfer-Encoding: quoted-printable


-----BEGIN PGP MESSAGE-----
Charset: ISO-8859-15
Version: GnuPG v2
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
=20
hQEOA36s1tjekYbVEAP/aIwC8+SfoAHlcuUdmbsLMGjRL3dXjPOVHIL5ssDm9s8s
...
-----END PGP MESSAGE-----


--=20
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.


--------------070003080703070604020509
Content-Type: application/octet-stream;
name="Nachvers.pdf.pgp"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="Nachvers.pdf.pgp"

hQEOA36s1tjekYbVEAQAmpN50g3oD/S7atXHmwKCrOTQ3L3kiHoz4cooJVCO
...

--------------070003080703070604020509--


А вот то что отсылает моя программа:

...
Content-Type: multipart/mixed;
boundary="----=_Part_0_1556173561.1476784377449"


------=_Part_0_1556173561.1476784377449
Content-Type: multipart/related;
boundary="----=_Part_1_179915314.1476784377459"


------=_Part_1_179915314.1476784377459
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

-----BEGIN PGP MESSAGE-----
Version: BCPG v1.55

hQEMAwONeOFeNcJpAQf9EBtz8GQqvr6WblIz/3MrL3zxM0Wl/Um9rD6YwGWKlcqR
...
-----END PGP MESSAGE-----

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.


------=_Part_1_179915314.1476784377459--

------=_Part_0_1556173561.1476784377449
Content-Type: application/octet-stream; name="C:\\Temp\\TESTcrypt.txt.pgp"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="C:\\Temp\\TESTcrypt.txt.pgp"

-----BEGIN PGP MESSAGE-----
Version: BCPG v1.55

hQEMAwONeOFeNcJpAQf/be82EXbt9psD7t6qE9ML3qbJ5UcJ11PTZFjgqtD2lIuw
...
-----END PGP MESSAGE-----

------=_Part_0_1556173561.1476784377449--

Из разницы "бросается" в глаза что у меня шифровка 7 бит а не base64 и что в оригинале есть фраза "This is a multi-part message in MIME format", которая говорит видимо о том что мы имеем сообщение со вложениями. Насчет первого можно поковыряться (однако текст таки "вскрывается" корректно, так что не думаю что это причина), а вот в чем может быть причина второго для меня загадка - ведь сообщение приходит с вложением....
...
Рейтинг: 0 / 0
18.10.2016, 15:53
    #39329066
Andrei T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите мне про PGP шифрование с помощью Bouncy castle
Я думаю проблема в том, что в вашем сообщении MIME-тип multipart/related, и при этом part1 идет перед part0, при чем не исключено, что это проблема специфична именно для вашего почтового клиента...
...
Рейтинг: 0 / 0
18.10.2016, 16:10
    #39329094
Andrei T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите мне про PGP шифрование с помощью Bouncy castle
Судя по тому что пишут в инете, стоит вообще избавиться от multipart/related, т.к. этот тип содержимого предполагается использовать только для inline-вложений (к примеру HTML + gif). Клиенты вроде как могут отображать отдельные части multipart/related-сообщения как аттачменты (по крайней мере такая инфа есть в багтрекере Thunderbird -- тут как раз может играть свою роль порядок номеров, про к-й я написал выше). Но с формальной т.з. такой формат является некорректным, плюс у вас еще и шифрование, вполне возможно что на такую ситуацию создатели юнит-тесты не подумали написать :)
...
Рейтинг: 0 / 0
19.10.2016, 11:17
    #39329630
RuslanGab
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите мне про PGP шифрование с помощью Bouncy castle
Уважаемый Andrei T,
низкий вам поклон и огромное СПАСИБО!
Ваши советы оказались именно тем что требовалось, и право сам бы я до этого не дошел.

Вышеприведенный код в целом верен. Окончательно помогло следующее:
стоит вообще избавиться от multipart/related
Код: java
1.
MimeMessageHelper helper = new MimeMessageHelper(msg, 1);


1 = MULTIPART_MODE_MIXED , а варинт с "true" возвращал "multipart/related":
@param multipart whether to create a multipart message that
* supports alternative texts, inline elements and attachments
* (corresponds to MULTIPART_MODE_MIXED_RELATED)




тут как раз может играть свою роль порядок номеров, про к-й я написал выше
Код: java
1.
2.
3.
4.
                helper.addAttachment("attachment.txt", new File(filePath")); 
                helper.setText(BouncyCrypt.encryptString(                                    
                                    "crypted mail test text...", 
                                    BouncyCrypt.readPublicKey("G:\\public_key\\encrypt.asc")));


т.е. сначала аттачмент, а потом текст, что для меня вообще не логично, но таки работет!

Придвижу дальше миллион проблем с другими почтовиками и прочими радостями, но хотя бы на сегодняшний день это выдает нужный результат.

Еще раз спасибо!!!
...
Рейтинг: 0 / 0
19.10.2016, 15:26
    #39329939
Andrei T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите мне про PGP шифрование с помощью Bouncy castle
Руслан, не за что! Если не затруднит, проясните пожалуйста - поменять местами addAttachment и setBody помогает само по себе, без изменения multipart_mode?
...
Рейтинг: 0 / 0
19.10.2016, 17:57
    #39330111
RuslanGab
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите мне про PGP шифрование с помощью Bouncy castle
Andrei T,

Не проверял только изменение порядка следования, потому что сделал сначала multipart - одно это не помогло. Проверю без проблем сработает ли только изменение порядка, но извините не могу прямо сейчас проверить - сервер упал. Завтра сделаю отпишусь.
...
Рейтинг: 0 / 0
20.10.2016, 11:13
    #39330434
RuslanGab
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите мне про PGP шифрование с помощью Bouncy castle
Andrei T,

Только изменение порядка следования шифрования с применением "дефолтного" MULTIPART_MODE_MIXED_RELATED не работает. Во всяком случае с thunderbird (win7) эффект достигается только в результате комбинации шифрования в "правильной" очереди с MULTIPART_MODE_MIXED.
...
Рейтинг: 0 / 0
20.10.2016, 17:48
    #39330940
Andrei T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите мне про PGP шифрование с помощью Bouncy castle
Атас!)) Спасибо что нашли время проверить))
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Подскажите мне про PGP шифрование с помощью Bouncy castle / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]