В настоящее время я пытаюсь адаптировать несколько скриптов, которые мы используем для подписи файлов шифрования/дешифрования xml с использованием OpenSSL и S/MIME с использованием Java и BouncyCastle.
Команда для подписания и шифрования нашего файла:
openssl smime -sign -signer Pub1.crt -inkey Priv.key -in foo.xml | openssl smime -encrypt -out foo.xml.smime Pub2.crt Pub1.crt
Это создает подписанный и зашифрованный smime файл, содержащий наш XML файл. В настоящее время это происходит с помощью набора сценариев оболочки под Linux, используя библиотеку OpenSSL. В будущем мы хотим интегрировать этот процесс в наше Java-приложение.
Я узнал, что это должно быть возможно с помощью библиотеки BouncyCastle (см. Этот пост). В ответе есть два Java-класса, показывающие, как подписывать и шифровать электронную почту, используя BouncyCastle и S/MIME. Сравнивая это с нашей командой OpenSSL, кажется, что многие вещи, необходимые для подписи шифрования электронной почты, не нужны в нашем подходе.
Еще одна метаинформация из наших сгенерированных файлов:
Подписанный файл
MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----709621D94E0377688356FAAE5A2C1321"
Зашифрованный файл
MIME-Version: 1.0
Content-Disposition: attachment; filename="smime.p7m"
Content-Type: application/x-pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"
Content-Transfer-Encoding: base64
Можно ли даже подписывать и шифровать простой файл так, как мы это делали, используя OpenSSL? Мои текущие знания о подписи и дешифровании на данный момент не очень высоки, поэтому простите меня за то, что вы не предоставили образцы кода. Я предполагаю, что то, что я ищу, больше влияет на то, что мне нужно сделать, а может быть, и на тех, кто уже сделал это. Надеюсь, это подходящее место, чтобы спросить об этом. Если нет, пожалуйста, поправьте меня.
У меня был такой же вопрос, как вы, но мне удалось его решить. Я должен предупредить вас, мои знания о подписании и шифровании не так уж и высоки. Но этот код, похоже, работал на меня.
В моем случае я использовал сертификат personalsign pro 3 от globalsign, ранее я просто вызвал openssl из java. Но я хотел очистить свой код и решил вместо этого использовать надувной замок.
public static boolean signAllFiles(List<File> files) {
Boolean signingSucceeded = true;
KeyStore ks = null;
char[] password = null;
Security.addProvider(new BouncyCastleProvider());
try {
ks = KeyStore.getInstance("PKCS12");
password = "yourpass".toCharArray();
ks.load(new FileInputStream("full/path/to/your/original/certificate.pfx"), password);
} catch (Exception e) {
signingSucceeded = false;
}
// Get privatekey and certificate
X509Certificate cert = null;
PrivateKey privatekey = null;
try {
Enumeration<String> en = ks.aliases();
String ALIAS = "";
Vector<Object> vectaliases = new Vector<Object>();
while (en.hasMoreElements())
vectaliases.add(en.nextElement());
String[] aliases = (String[])(vectaliases.toArray(new String[0]));
for (int i = 0; i < aliases.length; i++)
if (ks.isKeyEntry(aliases[i]))
{
ALIAS = aliases[i];
break;
}
privatekey = (PrivateKey)ks.getKey(ALIAS, password);
cert = (X509Certificate)ks.getCertificate(ALIAS);
// publickey = ks.getCertificate(ALIAS).getPublicKey();
} catch (Exception e) {
signingSucceeded = false;
}
for (File source : files) {
String fileName = "the/path/andNameOfYourOutputFile";
try {
// Reading files which need to be signed
File fileToSign = source;
byte[] buffer = new byte[(int)fileToSign.length()];
DataInputStream in = new DataInputStream(new FileInputStream(fileToSign));
in.readFully(buffer);
in.close();
// Generate signature
ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>();
certList.add(cert);
Store<?> certs = new JcaCertStore(certList);
CMSSignedDataGenerator signGen = new CMSSignedDataGenerator();
ContentSigner sha1signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(
privatekey);
signGen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder().build()).build(sha1signer, cert));
signGen.addCertificates(certs);
CMSTypedData content = new CMSProcessableByteArray(buffer);
CMSSignedData signedData = signGen.generate(content, false);
byte[] signeddata = signedData.getEncoded();
// Write signature to Fi File
FileOutputStream envfos = new FileOutputStream(fileName);
byte[] outputString = Base64.encode(signeddata);
int fullLines = (int)Math.floor(outputString.length / 64);
for (int i = 0; i < fullLines; i++) {
envfos.write(outputString, i * 64, 64);
envfos.write("\r\n".getBytes());
}
envfos.write(outputString, fullLines * 64, outputString.length % 64);
envfos.close();
} catch (Exception e) {
signingSucceeded = false;
}
}
return signingSucceeded;
}
Это всего лишь код для подписи файла, надеюсь, это поможет.