криптография с открытым ключом с Java и OpenSSL

В приложении я хочу хранить конфиденциальные данные (которые могут быть сколь угодно большими), чтобы впоследствии их можно было использовать для исследований. Дело в том, что я не хочу, чтобы данные лежали незащищенными, поэтому я хочу зашифровать их перед сохранением.

На другом компьютере (в более надежной среде) я хочу расшифровать эти данные позже. Расшифровка должна быть возможной с помощью легкодоступных инструментов, например OpenSSL. Теперь мой вопрос: как мне все это сделать?

Я уже знаю абстрактные шаги:

  1. Раз и навсегда сгенерируйте пару открытый/закрытый ключ.
  2. Зашифруйте byte[] в Java с помощью открытого ключа и сохраните его где-нибудь.
  3. Скопируйте зашифрованные данные на «более безопасный» компьютер.
  4. Расшифруйте сохраненные данные с помощью простой командной строки OpenSSL.

Чего мне сейчас не хватает, так это деталей:

  • Какая пара ключей мне нужна?
  • Какую схему шифрования следует использовать? (вероятно, это что-то вроде «rsa-шифровать симметричный ключ, а затем шифровать данные с помощью этого ключа»)
  • Как выглядит простая командная строка OpenSSL?

[Обновление от 13 февраля 2011 г.]

После небольшого исследования я нашел страницу, которая точно описывает, что я хочу сделать: резервных копий/" rel="nofollow">http://blog.altudov.com/2010/09/27/using-openssl-for-asymmetric-encryption-of-backups/. В основном ответом на мой шаг 4 является эта командная строка:

openssl smime -decrypt \
  -in data.smime -binary -inform DER \
  -inkey key.pem \
  -out data

Теперь мой вопрос: как я могу создать файл из Java, формат которого совместим с OpenSSL, чтобы я мог распаковать его с помощью этой командной строки? Я хочу делать это сотни раз в секунду, поэтому вызов внешнего процесса кажется слишком медленным. Вот почему я хочу сделать это прямо на Java.


person Roland Illig    schedule 06.02.2011    source источник


Ответы (2)


Наконец-то я нашел именно то, что искал. Меня только что смутили все такие термины, как S/MIME, ASN.1, DER и так далее. Но, наконец, и, казалось бы, случайно, я добрался до пакета CMS (что бы это ни значило) от bouncycastle, который делает все, что я хочу. Итак, вот мой код:

package de.roland_illig.crypto;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import org.apache.commons.io.IOUtils;
import org.bouncycastle.cms.CMSEnvelopedDataStreamGenerator;
import org.bouncycastle.cms.CMSEnvelopedGenerator;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class CryptDemo {

  private static final File DIR = new File("c:/program files/cygwin/home/roland/crypto/");

  private static X509Certificate certificate() throws IOException, GeneralSecurityException {
    InputStream is = new FileInputStream(new File(DIR, "key.pub.der"));
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
    is.close();
    return cert;
  }

  private static void encrypt() throws IOException, GeneralSecurityException, CMSException {
    CMSEnvelopedDataStreamGenerator gen = new CMSEnvelopedDataStreamGenerator();
    gen.addKeyTransRecipient(certificate());

    InputStream is = new FileInputStream(new File(DIR, "secret"));
    OutputStream out = new FileOutputStream(new File(DIR, "secret.encrypted"));
    OutputStream encryptingOut = gen.open(out, CMSEnvelopedGenerator.AES128_CBC, "BC");

    IOUtils.copy(is, encryptingOut);

    is.close();
    encryptingOut.close();
    out.close();
  }

  public static void main(String[] args) throws Exception {
    Security.addProvider(new BouncyCastleProvider());

    encrypt();
  }
}
person Roland Illig    schedule 14.02.2011
comment
Я серьезно не понимаю, почему вы все еще настаиваете на добавлении PKI в свое решение, хотя у вас, очевидно, нет для этого причин, и это не дает никакой дополнительной ценности в двухточечных решениях, таких как ваше ... Это, к сожалению, демонстрирует, что вы не совсем понял ранее обсуждавшиеся концепции... :( Но в любом случае, я рад, что вы довольны своим решением. - person erloewe; 14.02.2011
comment
Зашифрованные данные содержат информацию, которую нелегко расшифровать. Поэтому, если я использую симметричное шифрование, мне придется оставить ключ где-то на сервере. Если этот ключ будет раскрыт (в результате какой-либо атаки на сервер), то в первую очередь нет смысла шифровать данные. Поэтому я хотел использовать асимметричное шифрование. Причина упоминания OpenSSL заключалась в том, что я хочу иметь возможность расшифровывать данные с помощью легкодоступных инструментов, а OpenSSL, похоже, достаточно широко распространен. - person Roland Illig; 15.02.2011
comment
Теперь я понимаю вашу точку зрения. Я не должен использовать PKI, когда достаточно простой пары открытый/закрытый ключ. Итак, можете ли вы сказать мне, как я могу достичь своей цели более простым способом? - person Roland Illig; 15.02.2011

Вы должны понимать, что SSL предназначен для шифрования сетевого трафика. Системы с открытым ключом с сертификатами и т. д. хороши для проверки доверия между сторонами. Если вам нужно защитить что-то, что вы будете использовать позже, вам, вероятно, следует не смешивать предыдущие концепции в своем решении. Это делает вашу жизнь проще.

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

person erloewe    schedule 06.02.2011
comment
Я думаю, что уже понял все концепции. Я просто хочу иметь зашифрованный формат, который можно легко понять с помощью инструментов, которые уже установлены на большинстве машин, вместо того, чтобы создавать собственный формат файлов для фрагментов зашифрованных данных. - person Roland Illig; 14.02.2011
comment
@Roland В этом случае что-то вроде bsdsupport.org/2007/01/q-how-do-i-use-openssl-to-encrypt-files подойдет :) - person erloewe; 14.02.2011
comment
Спасибо за ссылку. Я просто написал там комментарий, что rsautl не может шифровать большие файлы, так что это не решение. Во всяком случае, я обновил вопрос с тем, что я получил до сих пор. - person Roland Illig; 14.02.2011