使用BouncyCastle java API进行PGP签名并使用gpg4win进行验证不起作用
我正在使用BouncyCastle API对文件进行签名。我正在使用bcpg-jdk15on-164.jar、bcprov-jdk15on-164.jar和bcprov-ext-jdk15on-164.jar 我以他们为例签署了一个文本文件。签名文件后,当我更改文本文件中的内容并尝试使用Gpg4Win进行验证时,我仍然看到签名有效,但没有迹象表明无法验证该文件 我为同一个文本文件创建了两个签名。一个使用下面的代码生成.asc文件,另一个使用Gpg4Win生成.sig文件。然后我修改了文本文件。我双击了每个签名,我希望签名会因为生成签名后文件被更改而变得无效。但是,BouncyCastle生成的签名仍然不表示文件已更改,如图所示。BouncyCastle签名显示为绿色,而Gpg4Win生成的签名显示为红色。 图片:使用BouncyCastle java API进行PGP签名并使用gpg4win进行验证不起作用,java,cryptography,bouncycastle,Java,Cryptography,Bouncycastle,我正在使用BouncyCastle API对文件进行签名。我正在使用bcpg-jdk15on-164.jar、bcprov-jdk15on-164.jar和bcprov-ext-jdk15on-164.jar 我以他们为例签署了一个文本文件。签名文件后,当我更改文本文件中的内容并尝试使用Gpg4Win进行验证时,我仍然看到签名有效,但没有迹象表明无法验证该文件 我为同一个文本文件创建了两个签名。一个使用下面的代码生成.asc文件,另一个使用Gpg4Win生成.sig文件。然后我修改了文本文件。我
导入java.io.File;
导入java.io.FileInputStream;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.OutputStream;
导入java.security.NoSuchAlgorithmException;
导入java.security.NoSuchProviderException;
导入java.security.security;
导入java.security.SignatureException;
导入java.util.Iterator;
导入org.bouncycastle.bcpg.ArmoredOutputStream;
导入org.bouncycastle.bcpg.BCPGOutputStream;
导入org.bouncycastle.jce.provider.BouncyCastleProvider;
导入org.bouncycastle.openpgp.PGPCompressedData;
导入org.bouncycastle.openpgp.pgpccompressedatagenerator;
导入org.bouncycastle.openpgp.PGPException;
导入org.bouncycastle.openpgp.PGPLiteralData;
导入org.bouncycastle.openpgp.PGPLiteralDataGenerator;
导入org.bouncycastle.openpgp.PGPOnePassSignature;
导入org.bouncycastle.openpgp.pgponepassignaturelist;
导入org.bouncycastle.openpgp.PGPPrivateKey;
导入org.bouncycastle.openpgp.PGPPublicKey;
导入org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
导入org.bouncycastle.openpgp.PGPSecretKey;
导入org.bouncycastle.openpgp.PGPSecretKeyRing;
导入org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
导入org.bouncycastle.openpgp.pgp签名;
导入org.bouncycastle.openpgp.PGPSignatureGenerator;
导入org.bouncycastle.openpgp.PGPSignatureList;
导入org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
导入org.bouncycastle.openpgp.PGPUtil;
导入org.bouncycastle.openpgp.operator.KeyFingerCalculator;
导入org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
导入org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
导入org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
导入org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
/**
*对文件进行签名和验证的简单实用程序类。
*
*签署文件:SignedFileProcessor-s[-a]fileName secretKey密码短语。
*如果指定了-a,则输出文件将为“ascii铠装”。
*
*要解密:SignedFileProcessor-v fileName publicKeyFile。
*
*注意:此示例将以静默方式覆盖文件,也不会注意
*文件名中“_CONSOLE”的规范。它还希望一个简单的短语
*将被使用。
*
*注意:该示例还使用PGP压缩。如果你很难得到它
*要与其他PGP程序进行互操作,请先尝试取消使用压缩。
*/
公共类SignedFileProcessor
{
/**
*生成一个封装的签名文件。
*
*@param文件名
*@param-keyIn
*@param out
*@param pass
*@param装甲
*@抛出异常
*@NoSuchAlgorithmException
*@throws-NoSuchProviderException
*@PGPException
*@抛出SignatureException
*/
私有静态无效签名文件(
字符串文件名,
输入流键入,
输出流输出,
char[]pass,
布尔装甲)
抛出IOException、NoSuchAlgorithmException、NoSuchProviderException、PGPEException、SignatureException
{
if(装甲)
{
out=新ArmorRedoutPutStream(out);
}
PGPSecretKey pgpSec=readSecretKey(keyIn);
PGPPrivateKey pgpPrivKey=pgpSec.extractPrivateKey(新的JcePBESecretKeyDecryptorBuilder().setProvider(“BC”).build(pass));
PGPSignatureGenerator sGen=新的PGPSignatureGenerator(新的JcaPGPContentSignerBuilder(pgpSec.getPublicKey().getAlgorithm(),PGPUtil.SHA1).setProvider(“BC”);
sGen.init(PGPSignature.BINARY_文档,pgpPrivKey);
迭代器it=pgpSec.getPublicKey().getUserId();
if(it.hasNext())
{
PGPSignatureSubpacketGenerator spGen=新的PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false,(String)it.next());
sGen.setHashedSubpackets(spGen.generate());
}
PGPCompressedDataGenerator cGen=新的PGPCompressedDataGenerator(PGPCompressedData.ZLIB);
BCPGOutputStream bOut=新的BCPGOutputStream(cGen.open(out));
sGen.generateOnePassVersion(false).编码(bOut);
文件=新文件(文件名);
PGPLiteralDataGenerator lGen=新的PGPLiteralDataGenerator();
OutputStream lOut=lGen.open(bOut,PGPLiteralData.BINARY,文件);
FileInputStream fIn=新的FileInputStream(文件);
int-ch;
而((ch=fIn.read())>=0)
{
lOut.write(ch);
sGen.update((字节)ch);
}
lGen.close();
sGen.generate().encode(bOut);
cGen.close();
if(装甲)
{
out.close();
}
}
公共静态真空总管(
斯特里
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.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.SignatureException;
import java.util.Iterator;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.bcpg.BCPGOutputStream;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPCompressedData;
import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPLiteralData;
import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
import org.bouncycastle.openpgp.PGPOnePassSignature;
import org.bouncycastle.openpgp.PGPOnePassSignatureList;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureGenerator;
import org.bouncycastle.openpgp.PGPSignatureList;
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
/**
* A simple utility class that signs and verifies files.
* <p>
* To sign a file: SignedFileProcessor -s [-a] fileName secretKey passPhrase.<br>
* If -a is specified the output file will be "ascii-armored".
* <p>
* To decrypt: SignedFileProcessor -v fileName publicKeyFile.
* <p>
* <b>Note</b>: this example will silently overwrite files, nor does it pay any attention to
* the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase
* will have been used.
* <p>
* <b>Note</b>: the example also makes use of PGP compression. If you are having difficulty getting it
* to interoperate with other PGP programs try removing the use of compression first.
*/
public class SignedFileProcessor
{
/**
* Generate an encapsulated signed file.
*
* @param fileName
* @param keyIn
* @param out
* @param pass
* @param armor
* @throws IOException
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
* @throws PGPException
* @throws SignatureException
*/
private static void signFile(
String fileName,
InputStream keyIn,
OutputStream out,
char[] pass,
boolean armor)
throws IOException, NoSuchAlgorithmException, NoSuchProviderException, PGPException, SignatureException
{
if (armor)
{
out = new ArmoredOutputStream(out);
}
PGPSecretKey pgpSec = readSecretKey(keyIn);
PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(pass));
PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setProvider("BC"));
sGen.init(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);
BCPGOutputStream bOut = new BCPGOutputStream(cGen.open(out));
sGen.generateOnePassVersion(false).encode(bOut);
File file = new File(fileName);
PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
OutputStream lOut = lGen.open(bOut, PGPLiteralData.BINARY, file);
FileInputStream fIn = new FileInputStream(file);
int ch;
while ((ch = fIn.read()) >= 0)
{
lOut.write(ch);
sGen.update((byte)ch);
}
lGen.close();
sGen.generate().encode(bOut);
cGen.close();
if (armor)
{
out.close();
}
}
public static void main(
String[] args)
throws Exception
{
Security.addProvider(new BouncyCastleProvider());
String rootFolder = System.getProperty("user.dir");
String fileName = rootFolder + "\\files\\helloworld.txt";
FileInputStream keyIn = new FileInputStream(rootFolder + "\\files\\sign-and-encrypt_priv.asc");
FileOutputStream out = new FileOutputStream(fileName + ".asc");
signFile(fileName, keyIn, out, "hongkong".toCharArray(), true);
System.out.println("DONE");
}
/**
* 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.
*/
static PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException
{
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
PGPUtil.getDecoderStream(input), new JcaKeyFingerprintCalculator());
//
// 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.");
}
}
private static void signFile(
String fileName,
InputStream keyIn,
OutputStream out,
char[] pass,
boolean armor)
throws IOException, NoSuchAlgorithmException, NoSuchProviderException, PGPException, SignatureException
{
if (armor)
{
out = new ArmoredOutputStream(out);
}
PGPSecretKey pgpSec = readSecretKey(keyIn);
PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(pass));
PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setProvider("BC"));
sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
BCPGOutputStream bOut = new BCPGOutputStream(out);
InputStream fIn = new BufferedInputStream(new FileInputStream(fileName));
int ch;
while ((ch = fIn.read()) >= 0)
{
sGen.update((byte)ch);
}
fIn.close();
sGen.generate().encode(bOut);
if (armor)
{
out.close();
}
}