- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
几个星期以来,我一直在用头撞墙,试图弄清楚为什么我们的银行无法解密使用 BouncyCaSTLe PGP 单程签名和加密的消息。该银行使用 McAfee E-Business Server 8.6 进行解密。
数据使用银行的公钥加密,并使用我们的私钥签名。
使用我们自己的公钥进行加密,我能够成功解密并验证使用以下代码生成的文件的签名。 Gnupg 可以很好地解密和验证文件。
但是,银行无法解密该文件。我试过先关闭压缩,然后关闭 ASCII 装甲。这两个选项似乎都不起作用,而且无论我尝试什么选项,它们总是收到相同的错误消息:
event 1: initial
event 13: BeginLex
event 8: Analyze
File is encrypted. event 9: Recipients
Secret key is required to read it.
Key for user ID "XXXXXXXXX <XXXXXX@XXXX>"
event 6: Passphrase
event 23: Decryption
symmetric cipher used: CAST5
event 3: error -11391
event 2: final
Error decrypting file '/somepath/FILENAME'.
Corrupt data.
Bad packet
exitcode = 32
这是我用来进行单次通过签名和加密的代码:
public class PGPService {
private static final Logger log = Logger.getLogger(PGPService.class);
static {
Security.addProvider(new BouncyCastleProvider());
}
/**
* A simple routine that opens a key ring file and loads the first available key
* suitable for signature generation.
*
* @param input stream to read the secret key ring collection from.
* @return a secret key.
* @throws IOException on a problem with using the input stream.
* @throws PGPException if there is an issue parsing the input stream.
*/
@SuppressWarnings("rawtypes")
private static PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException {
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
PGPUtil.getDecoderStream(input));
// We just loop through the collection till we find a key suitable for encryption, in the real
// world you would probably want to be a bit smarter about this.
Iterator keyRingIter = pgpSec.getKeyRings();
while (keyRingIter.hasNext()) {
PGPSecretKeyRing keyRing = (PGPSecretKeyRing)keyRingIter.next();
Iterator keyIter = keyRing.getSecretKeys();
while (keyIter.hasNext()) {
PGPSecretKey key = (PGPSecretKey)keyIter.next();
if (key.isSigningKey()) {
return key;
}
}
}
throw new IllegalArgumentException("Can't find signing key in key ring.");
}
/**
* Single pass signs and encrypts the given file to the given output file using the provided keys.
*
* @param fileNameIn - The name and location of the source input file.
* @param fileNameOut - The name and location of the destination output file.
* @param privateKeyIn - The input stream for the private key file.
* @param privateKeyPassword - The password for the private key file.
* @param publicEncryptionKey - The public encryption key.
* @param armoredOutput - Whether or not to ASCII armor the output.
*/
@SuppressWarnings("rawtypes")
public static void signAndEncrypt(String fileNameIn, String fileNameOut, InputStream privateKeyIn, String privateKeyPassword, PGPPublicKey publicEncryptionKey, boolean armoredOutput, boolean compress) {
int bufferSize = 1<<16;
InputStream input = null;
OutputStream finalOut = null;
OutputStream encOut = null;
OutputStream compressedOut = null;
OutputStream literalOut = null;
PGPEncryptedDataGenerator encryptedDataGenerator = null;
PGPCompressedDataGenerator compressedDataGenerator = null;
PGPSignatureGenerator signatureGenerator = null;
PGPLiteralDataGenerator literalDataGenerator = null;
try {
File output = new File(fileNameOut);
OutputStream out = new FileOutputStream(output);
if (armoredOutput) out = new ArmoredOutputStream(out);
// ? Use BCPGOutputStreams ?
// Init encrypted data generator
encryptedDataGenerator = new PGPEncryptedDataGenerator(PGPEncryptedDataGenerator.CAST5, true, new SecureRandom(), "BC");
encryptedDataGenerator.addMethod(publicEncryptionKey);
finalOut = new BufferedOutputStream(out, bufferSize);
encOut = encryptedDataGenerator.open(finalOut, new byte[bufferSize]);
// Init compression
if (compress) {
compressedDataGenerator = new PGPCompressedDataGenerator(PGPCompressedData.ZLIB);
compressedOut = new BufferedOutputStream(compressedDataGenerator.open(encOut));
}
// Init signature
PGPSecretKey pgpSec = readSecretKey(privateKeyIn);
PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(privateKeyPassword.toCharArray(), "BC");
signatureGenerator = new PGPSignatureGenerator(pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1, "BC");
signatureGenerator.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, pgpPrivKey);
Iterator it = pgpSec.getPublicKey().getUserIDs();
if (it.hasNext()) {
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false, (String)it.next());
signatureGenerator.setHashedSubpackets(spGen.generate());
}
PGPOnePassSignature onePassSignature = signatureGenerator.generateOnePassVersion(false);
if (compress) onePassSignature.encode(compressedOut);
else onePassSignature.encode(encOut);
// Create the Literal Data generator Output stream which writes to the compression stream
literalDataGenerator = new PGPLiteralDataGenerator(true);
if (compress) literalOut = literalDataGenerator.open(compressedOut, PGPLiteralData.BINARY, output.getName(), new Date(), new byte[bufferSize]);
else literalOut = literalDataGenerator.open(encOut, PGPLiteralData.TEXT, fileNameIn, new Date(), new byte[bufferSize]);
// Update sign and encrypt
byte[] buffer = new byte[bufferSize];
int bytesRead = 0;
input = new FileInputStream(fileNameIn);
while((bytesRead = input.read(buffer)) != -1) {
literalOut.write(buffer,0,bytesRead);
signatureGenerator.update(buffer,0,bytesRead);
literalOut.flush();
}
// Close Literal data stream and add signature
literalOut.close();
literalDataGenerator.close();
if (compress) signatureGenerator.generate().encode(compressedOut);
else signatureGenerator.generate().encode(encOut);
} catch (Exception e) {
log.error(e);
throw new RuntimeException(e);
} finally {
// Close all streams
if (literalOut != null) try { literalOut.close(); } catch (IOException e) {}
if (literalDataGenerator != null) try { literalDataGenerator.close(); } catch (IOException e) {}
if (compressedOut != null) try { compressedOut.close(); } catch (IOException e) {}
if (compressedDataGenerator != null) try { compressedDataGenerator.close(); } catch (IOException e) {}
if (encOut != null) try { encOut.close(); } catch (IOException e) {}
if (encryptedDataGenerator != null) try { encryptedDataGenerator.close(); } catch (IOException e) {}
if (finalOut != null) try { finalOut.close(); } catch (IOException e) {}
if (input != null) try { input.close(); } catch (IOException e) {}
}
}
@SuppressWarnings("rawtypes")
private static PGPPublicKey readPublicKeyFromCol(InputStream in) throws Exception {
PGPPublicKeyRing pkRing = null;
PGPPublicKeyRingCollection pkCol = new PGPPublicKeyRingCollection(in);
log.info("Key ring size = " + pkCol.size());
Iterator it = pkCol.getKeyRings();
while (it.hasNext()) {
pkRing = (PGPPublicKeyRing) it.next();
Iterator pkIt = pkRing.getPublicKeys();
while (pkIt.hasNext()) {
PGPPublicKey key = (PGPPublicKey) pkIt.next();
log.info("Encryption key = " + key.isEncryptionKey() + ", Master key = " +
key.isMasterKey());
if (key.isEncryptionKey()) {
// Find out a little about the keys in the public key ring.
log.info("Key Strength = " + key.getBitStrength());
log.info("Algorithm = " + key.getAlgorithm());
log.info("Bit strength = " + key.getBitStrength());
log.info("Version = " + key.getVersion());
return key;
}
}
}
return null;
}
private static PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass)
throws IOException, PGPException, NoSuchProviderException {
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn));
PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
if (pgpSecKey == null) {
return null;
}
return pgpSecKey.extractPrivateKey(pass, "BC");
}
}
知道是什么原因造成的吗?我使用 Google 发现了大量报告,但没有解决方案或后续行动。
最佳答案
我正在回答我自己的问题,希望它能帮助其他人,因为这个问题的答案很难在网上找到。
McAfee E-Business Server 8.6 之前的版本与 BouncyCaSTLe PGP 存在兼容性问题,似乎大多数人都无法让它工作。因此,如果您的供应商/客户/银行使用的是 8.6 之前的 E-Business Server 版本,您很可能是 SOL,可能需要找到不同的加密包。
来源:https://kc.mcafee.com/corporate/index?page=content&id=KB60816&cat=CORP_EBUSINESS_SERVER&actp=LIST
"Decrypting a file that was encrypted with Bouncy Castle v1.37 may result in Access Violation Error (or SIGSEG on UNIX platforms). This issue has been addressed in this release."
幸运的是,我们的银行正在使用 McAfee E-Business Server 8.6。然而,这只是等式的一部分。为了解决不兼容问题,我们不得不关闭压缩和 ASCII 装甲,它们才能成功解密和验证我们的文件。因此,使用我发布的原始代码,对于使用 E-Business Server 8.6 的客户端,您将这样调用它:
PGPService.signAndEncrypt(clearTextFileName, secureFileName, privKeyIn, privateKeyFilePassword, pubKeyIn, true, false, false);
当然,这意味着您不能使用 ASCII 装甲,这对您来说可能是个问题,也可能不是。如果是,BouncyCaSTLe 开发邮件列表上的 David 建议您在非数据包模式下使用 BouncyCaSTLe。 IE:不要将字节缓冲区传递到流中的打开命令中。或者分两次对文件进行签名和加密。
例如调用:
public static void signFile(String fileNameIn, String fileNameOut, InputStream privKeyIn, String password, boolean armoredOutput) {
OutputStream out = null;
BCPGOutputStream bOut = null;
OutputStream lOut = null;
InputStream fIn = null;
try {
out = new FileOutputStream(fileNameOut);
if (armoredOutput) {
out = new ArmoredOutputStream(out);
}
PGPSecretKey pgpSec = readSecretKey(privKeyIn);
PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(password.toCharArray(), "BC");
PGPSignatureGenerator sGen = new PGPSignatureGenerator(pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1, "BC");
sGen.initSign(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
Iterator it = pgpSec.getPublicKey().getUserIDs();
if (it.hasNext()) {
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false, (String)it.next());
sGen.setHashedSubpackets(spGen.generate());
}
PGPCompressedDataGenerator cGen = new PGPCompressedDataGenerator(PGPCompressedData.ZLIB);
bOut = new BCPGOutputStream(cGen.open(out));
sGen.generateOnePassVersion(false).encode(bOut);
File file = new File(fileNameIn);
PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
lOut = lGen.open(bOut, PGPLiteralData.BINARY, file);
fIn = new FileInputStream(file);
int ch = 0;
while ((ch = fIn.read()) >= 0) {
lOut.write(ch);
sGen.update((byte) ch);
}
lGen.close();
sGen.generate().encode(bOut);
cGen.close();
} catch (Exception e) {
log.error(e);
throw new RuntimeException(e);
} finally {
if (lOut != null) try { lOut.close(); } catch (IOException e) {}
if (bOut != null) try { bOut.close(); } catch (IOException e) {}
if (out != null) try { out.close(); } catch (IOException e) {}
if (fIn != null) try { fIn.close(); } catch (IOException e) {}
}
}
接着调用:
public static byte[] encrypt(byte[] data, InputStream pubKeyIn, boolean isPublicKeyArmored) {
FileOutputStream fos = null;
BufferedReader isr = null;
try {
if (isPublicKeyArmored) pubKeyIn = new ArmoredInputStream(pubKeyIn);
PGPPublicKey key = readPublicKeyFromCol(pubKeyIn);
log.info("Creating a temp file...");
// Create a file and write the string to it.
File tempfile = File.createTempFile("pgp", null);
fos = new FileOutputStream(tempfile);
fos.write(data);
fos.close();
log.info("Temp file created at: " + tempfile.getAbsolutePath());
log.info("Reading the temp file to make sure that the bits were written...\n");
isr = new BufferedReader(new FileReader(tempfile));
String line = "";
while ((line = isr.readLine()) != null ) {
log.info(line + "\n");
}
int count = 0;
for (java.util.Iterator iterator = key.getUserIDs(); iterator.hasNext();) {
count++;
log.info(iterator.next());
}
log.info("Key Count = " + count);
// Encrypt the data.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
_encrypt(tempfile.getAbsolutePath(), baos, key);
log.info("Encrypted text length = " + baos.size());
tempfile.delete();
return baos.toByteArray();
} catch (PGPException e) {
log.error(e);
throw new RuntimeException(e);
} catch (Exception e) {
log.error(e);
throw new RuntimeException(e);
} finally {
if (fos != null) try { fos.close(); } catch (IOException e) {}
if (isr != null) try { isr.close(); } catch (IOException e) {}
}
}
注意买者,因为我无法测试此方法以查看这是否甚至可以解决不兼容问题。但如果您别无选择并且必须为电子商务服务器目标使用 ASCII 装甲,那么这是您可以尝试的途径。
可以在 BouncyCaSTLe 开发邮件列表存档中找到更多信息,如果您决定走这条路,这些信息可能会有所帮助。特别是这个线程:http://www.bouncycastle.org/devmailarchive/msg12080.html
关于java - BouncyCaSTLe PGP 和 McAfee eBusiness Server 8.6 不兼容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6617720/
查看release notes Bounty CaSTLe 的版本,我没有看到任何日期或任何提及它符合 PGP 版本的内容。也许我的想法是错误的。 最佳答案 “PGP”代表产品和公司名称,是一个商标。
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 8年前关闭。 Improve this q
有没有办法转换(二进制).key文件到 ASCII 装甲 .asc文件? 之前有一篇帖子似乎暗示文件扩展名无关紧要,文件内容相同:What is the difference b/w .pkr and
我已使用 Bouncy Castle API 加密了一个文件。我已使用相同的 API 成功解密该文件。 但是我无法使用 PGP command line 解密该文件 没有显示错误消息,但未生成解密文件
我正在写一些 needs to do electronic signatures . 有些用户会像我一样是极客,并且已经拥有自己的 PGP key 。大多数人不会,也不想安装或维护它。 作为变通解决方
PGPKeyRingGenerator 构造函数采用密码短语来加密私钥。它用于执行此操作的算法是什么?它有一个名为 encAlgorithm 的字段,但我找不到任何解释这些算法是什么的文档。 最佳答案
我正在开发一个简单的 Java 代码,该代码使用 BouncyCaSTLe v1.51 打开 PGP 公钥并验证其中包含的签名。 目前,我能够加载公钥并迭代所有签名。但是,即使我使用与生成签名的私钥相
我正在使用 Bouncy CaSTLes 来压缩和加密一些数据。压缩方法因空引用异常而失败。以下方法执行压缩: private byte[] Compress(byte[] data)
我真的很苦恼,我需要在 C# 中使用 BouncyCaSTLe 加密和解密字符串。我确实确实尝试过自己做这件事。我确实设法创建了自己的 key (私钥和公钥)。 请记住,我刚从大学毕业。 最佳答案 我
我有一个应用程序使用 gpg key 并提示输入密码才能读取它。这是我这样做的方式(基于我在其他地方找到的示例: func Decrypt(publicKeyring string, secretKe
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
我想在脚本中将 PGP 公钥导入我的钥匙串(keychain),但我不希望它将内容写入文件。现在我的脚本是这样做的: curl http://example.com/pgp-public-key -o
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 8年前关闭。 Improve this que
我需要检查文件是否是有效的 pgp 加密文件。我们得到的一些 pgp 文件具有 pgp 的扩展名,而有些则没有。我需要检查哪些文件是 pgp 加密文件,哪些不是。请让我知道是否有办法告诉。 最佳答案
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 8年前关闭。 Improve this que
修订控制 PGP 加密文本文件的好方法是什么? 目标是 仅将 PGP 加密(最好使用 ASCII 装甲)文本文件存储在本地存储库(工作副本)和远程存储库(逻辑上的“中央”存储库)中。 在存储修订历史记
我正在尝试使用 BouncyCaSTLe 来调试和扩展现有的 Java 代码,以解密和验证安全附件。 我已经查看了 BouncyCaSTLe 示例,但从中提取 PGP 安全附件的模型比较困难。从代码和
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭10 年前。 Improve th
有谁知道Java中的充气城堡中的以下命令(GnuPG 2.17.2)相当于什么? gpg -e -r "recipient" --output output.gpg input.zip 最佳答案 创建
我正在使用公钥使用 openpgp 创建我的 java 产品的许可证。产品附带私钥,用于读取许可证文件。这是正确的方法吗?私钥可以用来生成公钥吗? 谢谢 最佳答案 没有。私钥应保密。 使用签名机制。使
我是一名优秀的程序员,十分优秀!