java 实现PGP生成公私钥对生成,以及加解密文件

介绍

最近和联通的数据生成系统对接需要使用PGP工具,网上查了资料,调了一整天终于出来了,下面介绍下使用方法以及碰到的一些的小坑

使用方法

依赖jar包

  <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.56</version>
        </dependency>
 
<!-- OpenPGP包依赖 -->
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpg-jdk15on -->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpg-jdk15on</artifactId>
            <version>1.56</version>
        </dependency>

bcprov-jdk15on.jar 常用的加解密jar包,相信大家都很熟悉了,我们通过它来实现PGP加解密及生成公私钥对

生成公私钥对的方法

public class PgpUtil {

	
	/**
	 * 私有方法,用于生成指定位宽的PGP RSA密钥对
	 *
	 * @param rsaWidth_ RSA密钥位宽
	 * @return 未经私钥加密的PGP密钥对
	 * @throws Exception IO错误,数值错误等
	 */
	private static PGPKeyPair generateKeyPair(int rsaWidth_) throws Exception {
	    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");//获取密钥对生成器实例
	    kpg.initialize(rsaWidth_);//设定RSA位宽
	    KeyPair kp = kpg.generateKeyPair();//生成RSA密钥对
	    return new JcaPGPKeyPair(PGPPublicKey.RSA_GENERAL, kp, new Date());//返回根据日期,密钥对生成的PGP密钥对
	}
	 
	/**
	 * 获取PGP密钥
* 密钥是将密钥对的私钥部分用对称的加密方法CAST-128算法加密,再加上公钥部分 * * @param identity_ 密钥ID也就是key值,可以用来标记密钥属于谁 * @param passPhrase_ 密钥的密码,用来解出私钥 * @param rsaWidth_ RSA位宽 * @return PGP密钥 * @throws Exception IO错误和数值错误等 */
public static PGPSecretKey getSecretKey(String identity_, String passPhrase_, int rsaWidth_) throws Exception { char[] passPhrase = passPhrase_.toCharArray(); //将passPharse转换成字符数组 PGPKeyPair keyPair = PgpUtil.generateKeyPair(rsaWidth_); //生成RSA密钥对 PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(HashAlgorithmTags.SHA1); //使用SHA1作为证书的散列算法 /** * 用证书等级生成的认证,将公私钥对和PGP ID密码绑定构造PGP密钥(SecretKey) * * @param certificationLevel PGP密钥的证书等级 * @param keyPair 需要绑定的公私钥对 * @param id 需要绑定的ID * @param checksumCalculator 散列值计算器,用于计算私钥密码散列 * @param hashedPcks the hashed packets to be added to the certification.(先不管) * @param unhashedPcks the unhashed packets to be added to the certification.(也先不管) * @param certificationSignerBuilder PGP证书的生成器 * @param keyEncryptor 如果需要加密私钥,需要在这里传入私钥加密器 * @throws PGPException 一些PGP错误 */ return new PGPSecretKey( PGPSignature.DEFAULT_CERTIFICATION, keyPair, identity_, sha1Calc, null, null, new JcaPGPContentSignerBuilder(keyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1), //密钥的加密方式 new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.CAST5, sha1Calc).setProvider("BC").build(passPhrase) ); } @SuppressWarnings("restriction") public static void main(String[] args) throws Exception { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); String passPhrase_ = "123456789"; char[] passPhrase = passPhrase_.toCharArray(); //将passPharse转换成字符数组 PGPSecretKey secretKey = PgpUtil.getSecretKey("wathdata", passPhrase_, 2048); // 这里打印私钥-------------重要 String privateKeyString = new BASE64Encoder().encode(secretKey.getEncoded()); System.out.println(privateKeyString); PGPPublicKey publicKey = secretKey.getPublicKey(); //FileOutputStream fileOutputStream = new FileOutputStream("c://1.txt"); byte[] encoded = publicKey.getEncoded(); // 这里打印公钥----------------重要 String publicKeyString = new BASE64Encoder().encode(encoded); System.out.println(publicKeyString); } }

执行结果

私钥--------------------
lQO+BF6MRCABCADGKYKqSOtysDV4TX1ubaOVVxJbQ2gIlm9J/S0qQcvkip2nX/zfrDnFLH7eJFk5
gVcBX9Vc9uearmGI6xRzp8rqsyhVL/Nbp6zOkCTrRvglSnfrqPa2f7hzlKU976Za9NMwJHU4X0Mp
xTV6/fut3oYFU7uW/INoNc2NB65ajL0qzMP3MKX9k2OLhdHAB/4jsw9tUmTjr+2H5s+hLdpsq4cp
CscrfZf+Q2BZ+1b6BFMrMnf6aFBpiwL18zF5RME45mdrfb7VfGQR0mn5UmY8EXNNOjORLTZ4PTOb
y/VGBvMtOyJ++ggaRncrW9CNB1590A2CVy48Q7gNdVLFRmzPMCFjABEBAAH+AwMClr2r0h2iECpg
u+OVyOCH/GDpWN1NJ4F2kW34B0JSfQBHREJ56tbX4BD6k79pxfid9nift8YKUCc8fF/pkJOVKDGp
wcM66oinAfyYj4ZyLEY5l29FksEMD94YCZMU+Kcaz/hvO8WBC2a1MhIHzVwaNwIbKC3l0ZuW7qKM
u1nMnaIeTJHZcHpNluwaHY0NGZXf8TcCwIbncu4AVWo9JU3CAaCILMyezi2Rpc/lKRAK9a4zMb5M
PkXThDSUEFuLIxZYiJVncpGK1n65oxnrZvPIU8+Ha+yo2e+413J1/yyfwBfj0MhyCFpil99iibam
tQZnwx9XNvszSsXvbK68I9PD28PDJth/uDIHABfceQfZOiSnRL6ZT8bZPkqONENt2+Ia4U+PuK8l
FqA0flsOhOFb3Qnv/h8yRD+lFwscVWxfzwe8zvcoerotr87tjc0HNKNXLXQefWO9DV4iAt7O0vKI
QWqgvheMIK3zMiqR9i2510Y+1PQIqWBjyZtxjRAo5XDCu1BJcnQEUV58l0X1YCsRNMv+UxaQPIos
UnuiqLetrE7HC+Fxkv7DWkIeVAe/E7VExfwNiVFRdhnU3Djjp0IUEr9B6/CAQ4Kr6P9gLlN4UKV6
x8Wqz+/s2zAJj3bHNN884G71NnBnffb6iLIdv256D3Abfuo4y4ZwiVFs2URUfdKJmFEf9BngP5+A
ITs1z01OwkmlEsESjMGhSsUayLlOGo1obCubUIlXUfd5UxGRN2fQKGA8UNXUKWL53FczHYozuJER
9n7Q/guex6u/nfVJyhZW7DSuNp41FYPs/4ychVHo9sa5biGJ8X4MilvRnNfcdkKplJQs/h7KF+7a
aF+OrBN0H6kZAxwpfNjN28Um386zLjfTOYen6/b3oXNRknJ8ka53U3udq+cO2gCplLQId2F0aGRh
dGGJARwEEAECAAYFAl6MRCAACgkQxq3anzI2L9BCKAgAsF58+UyC8RK8Rasuluj5yNtYvzTI9AdZ
n5r18XjZ5PitodN9G3uq9nDKMogFb9l4Tl1r70oUNKu1QJ42mlDzMZ4icppaKjYARN7wIxFm/Mik
R5WtnQ76qJPsyAN0aE0jhRGaadQ9J4rw/M7wEoQ2r/O9AfNpCpcs30VNihWvhB5uqiDup8AIKf4f
yWSlH7dAKVbsrVWIjjdLuvSBFiu/LFP7V/Vn61WAmcVLhRWioWCfU8HbS0d14VKCpalTSuEaEY7+
PgBs1ThqyM+/n4QdKQcjpd2wqeDqQUb7SAuQ3/j91XuKNLXT/+YsuLPxT0mB0K1e8uBzUd3CmK/D
lCkPCg==
公钥-------------------
mQENBF6MRCABCADGKYKqSOtysDV4TX1ubaOVVxJbQ2gIlm9J/S0qQcvkip2nX/zfrDnFLH7eJFk5
gVcBX9Vc9uearmGI6xRzp8rqsyhVL/Nbp6zOkCTrRvglSnfrqPa2f7hzlKU976Za9NMwJHU4X0Mp
xTV6/fut3oYFU7uW/INoNc2NB65ajL0qzMP3MKX9k2OLhdHAB/4jsw9tUmTjr+2H5s+hLdpsq4cp
CscrfZf+Q2BZ+1b6BFMrMnf6aFBpiwL18zF5RME45mdrfb7VfGQR0mn5UmY8EXNNOjORLTZ4PTOb
y/VGBvMtOyJ++ggaRncrW9CNB1590A2CVy48Q7gNdVLFRmzPMCFjABEBAAG0CHdhdGhkYXRhiQEc
BBABAgAGBQJejEQgAAoJEMat2p8yNi/QQigIALBefPlMgvESvEWrLpbo+cjbWL80yPQHWZ+a9fF4
2eT4raHTfRt7qvZwyjKIBW/ZeE5da+9KFDSrtUCeNppQ8zGeInKaWio2AETe8CMRZvzIpEeVrZ0O
+qiT7MgDdGhNI4URmmnUPSeK8PzO8BKENq/zvQHzaQqXLN9FTYoVr4Qebqog7qfACCn+H8lkpR+3
QClW7K1ViI43S7r0gRYrvyxT+1f1Z+tVgJnFS4UVoqFgn1PB20tHdeFSgqWpU0rhGhGO/j4AbNU4
asjPv5+EHSkHI6XdsKng6kFG+0gLkN/4/dV7ijS10//mLLiz8U9JgdCtXvLgc1Hdwpivw5QpDwo=

文件加解密

/**
 * PGP加解密文件
 * @author zhibin.wang
 *
 */
public class KeyBasedFileProcessorKey

{
	
	/**
	 * 
	 * @param inputFileName 要解密的文件名
	 * @param key 私钥
	 * @param passwd 私钥解密key
	 * @param defaultFileName 输出解密的文件
	 * @throws IOException
	 * @throws NoSuchProviderException
	 */
	public static void decryptFile(

			String inputFileName,

			String key,

			char[] passwd,

			String defaultFileName)

			throws IOException, NoSuchProviderException

	{

		InputStream in = new BufferedInputStream(new FileInputStream(inputFileName));

		byte[] decode = Base64.getDecoder().decode(key);
		decryptFile(in, decode, passwd, defaultFileName);


		in.close();

	}

	/**
	 * 
	 * decrypt the passed in message stream
	 * 
	 */

	private static void decryptFile(

			InputStream in,

			byte[] keyIn,

			char[] passwd,

			String defaultFileName)

			throws IOException, NoSuchProviderException

	{

		in = PGPUtil.getDecoderStream(in);

		try

		{

			JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);

			PGPEncryptedDataList enc;

			Object o = pgpF.nextObject();

//

// the first object might be a PGP marker packet.

//

			if (o instanceof PGPEncryptedDataList)

			{

				enc = (PGPEncryptedDataList) o;

			}

			else

			{

				enc = (PGPEncryptedDataList) pgpF.nextObject();

			}

//

// find the secret key

//

			Iterator it = enc.getEncryptedDataObjects();

			PGPPrivateKey sKey = null;

			PGPPublicKeyEncryptedData pbe = null;

			PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(

keyIn, new JcaKeyFingerprintCalculator());

			while (sKey == null && it.hasNext())

			{

				pbe = (PGPPublicKeyEncryptedData) it.next();

				sKey = PGPExampleUtil.findSecretKey(pgpSec, pbe.getKeyID(), passwd);

			}

			if (sKey == null)

			{

				throw new IllegalArgumentException("secret key for message not found.");

			}

			InputStream clear = pbe
					.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(sKey));

			JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear);

			Object message = plainFact.nextObject();

			if (message instanceof PGPCompressedData)

			{

				PGPCompressedData cData = (PGPCompressedData) message;

				JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(cData.getDataStream());

				message = pgpFact.nextObject();

			}

			if (message instanceof PGPLiteralData)

			{

				PGPLiteralData ld = (PGPLiteralData) message;

				String outFileName = ld.getFileName();

				if (outFileName.length() == 0)

				{

					outFileName = defaultFileName;

				} else {

					/**
					 * 
					 * modify 20160520
					 * 
					 * set fileName
					 * 
					 * 不同的系统可能源文件的包含的路径信息不同。
					 * 
					 */

					String separator = "";

					if (outFileName.contains("/")) {

						separator = "/";

					} else if (outFileName.contains("\\")) {

						separator = "\\";

					}

					String fileName = outFileName.substring(outFileName.lastIndexOf(File.separator) + 1);

					//

					String defseparator = "";

					if (defaultFileName.contains("/")) {

						defseparator = "/";

					} else if (defaultFileName.contains("\\")) {

						defseparator = "\\";

					}

					defaultFileName = defaultFileName.substring(0, defaultFileName.lastIndexOf(defseparator));

					outFileName = defaultFileName + File.separator + fileName;

				}

				InputStream unc = ld.getInputStream();

				OutputStream fOut = new BufferedOutputStream(new FileOutputStream(outFileName));

				Streams.pipeAll(unc, fOut);

				fOut.close();

			}

			else if (message instanceof PGPOnePassSignatureList)

			{

				throw new PGPException("encrypted message contains a signed message - not literal data.");

			}

			else

			{

				throw new PGPException("message is not a simple encrypted file - type unknown.");

			}

			if (pbe.isIntegrityProtected())

			{

				if (!pbe.verify())

				{

					System.err.println("message failed integrity check");

				}

				else

				{

					System.err.println("message integrity check passed");

				}

			}

			else

			{

				System.err.println("no message integrity check");

			}

		}

		catch (PGPException e)

		{

			System.err.println(e);

			if (e.getUnderlyingException() != null)

			{

				e.getUnderlyingException().printStackTrace();

			}

		}

	}
	
	/**
	 * 
	 * @param outputFileName 输出的加密文件名 2.pgp
	 * @param inputFileName 输入的要加密的文件 
	 * @param encryKey  公钥
	 * @param armor true
	 * @param withIntegrityCheck true
	 * @throws IOException
	 * @throws NoSuchProviderException
	 * @throws PGPException
	 */
	public static void encryptFile(

			String outputFileName,

			String inputFileName,

			String encryKey,

			boolean armor,

			boolean withIntegrityCheck)

			throws IOException, NoSuchProviderException, PGPException

	{

		OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFileName));
		Decoder decoder = Base64.getDecoder();
		byte[] decode = decoder.decode(encryKey);
		PGPPublicKey encKey = PGPExampleUtil.readPublicKey(decode);

		encryptFile(out, inputFileName, encKey, armor, withIntegrityCheck);

		out.close();

	}

	private static void encryptFile(

			OutputStream out,

			String fileName,

			PGPPublicKey encKey,

			boolean armor,

			boolean withIntegrityCheck)

			throws IOException, NoSuchProviderException

	{

		if (armor)

		{

			out = new ArmoredOutputStream(out);

		}

		try

		{

			byte[] bytes = PGPExampleUtil.compressFile(fileName, CompressionAlgorithmTags.ZIP);

			PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(

					new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck)
							.setSecureRandom(new SecureRandom()).setProvider("BC"));

			encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider("BC"));

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

			cOut.write(bytes);

			cOut.close();

			if (armor)

			{

				out.close();

			}

		}

		catch (PGPException e)

		{

			System.err.println(e);

			if (e.getUnderlyingException() != null)

			{

				e.getUnderlyingException().printStackTrace();

			}

		}

	}

	public static void main(

			String[] args)

			throws Exception

	{
		String keyString = "mQENBF6MQAIBCACrMsize7pLL99P/r6SZc793tbQ6bwNlgPsMv4l+Yl0uD2AHaslg8/5BWNeIjzq" + 
				"0xL0W4+8oWHCOw68Xw5a4ah8zFhkXM92iTeGb6zivTBrLOGGD+8wJRLALKke6/c9YZTqAxUFbIxf" + 
				"0p9MuQLv2IQYDRr017N8q0bYN1tRz1sebEjvJ8noSkCEopkYIQ+vD6w2wOyN4bKHCa16qgM7S88D" + 
				"/QjPviYWrXkVr1AdMmzo4NGMs4yqRFxeGMhHPAf3Z0vuWJJssdyC1wcB3qnj9vtM2vxBJlhAYTdx" + 
				"C4WbB5eAXPZmBFWZ+Wb0CJaOxeCVpVHAJgTUjsRH7X3iZ0/a/EfbABEBAAG0CHdhdGhkYXRhiQEc" + 
				"BBABAgAGBQJejEACAAoJEMKE0EVeprn3fG4H/0G4Fp3GZmAYfLNgcxqLxMFLFPxSdft+6NE8mOmK" + 
				"DuKdsiHYcOpdBvm4YUeB9qyZGDeGHvRY3VzzDXU7QMD6/OXKZ3sDfcTcy0Cr2O1y7JNIJzC91cZ9" + 
				"kroP4p0tmcwSRGlo+BI7G5oDXSM/pf05+8JE55nXh8uQ0MaYy/wxyfp2EDeLj2FMFjFuW112a00K" + 
				"T1XzMqZ43Ubdsqe3sshiGFTA4tG3tQQh1sAjF6NLMnAo/pxzekcGB8RzkucW0M99IAmmhMksHPnH" + 
				"wQ3wKl8NAkJJXyXTmQtQ6/jbJ+fsdIj/FJNgpc5+pEbS+vUxkOUHXs2wTQ5y0Fag7R52Ps1MO3M=";
		
		String privateKeyString = "lQO+BF6MQAIBCACrMsize7pLL99P/r6SZc793tbQ6bwNlgPsMv4l+Yl0uD2AHaslg8/5BWNeIjzq" + 
				"0xL0W4+8oWHCOw68Xw5a4ah8zFhkXM92iTeGb6zivTBrLOGGD+8wJRLALKke6/c9YZTqAxUFbIxf" + 
				"0p9MuQLv2IQYDRr017N8q0bYN1tRz1sebEjvJ8noSkCEopkYIQ+vD6w2wOyN4bKHCa16qgM7S88D" + 
				"/QjPviYWrXkVr1AdMmzo4NGMs4yqRFxeGMhHPAf3Z0vuWJJssdyC1wcB3qnj9vtM2vxBJlhAYTdx" + 
				"C4WbB5eAXPZmBFWZ+Wb0CJaOxeCVpVHAJgTUjsRH7X3iZ0/a/EfbABEBAAH+AwMCV9cV6pssqM1g" + 
				"DSvDGApI59SQilmCijhWSJvEUwksqvMjyeiHjDvLmrxMpsnzWe7vSK1xABpph5A/HkVhQK3B+P8j" + 
				"MkI4kTiiFFcJ6ZpbjiBN/A8xgnHYdimXXsPe2lsZVAzQOS2NvQ56nRwtW1EKa2++X66u6syu3DzO" + 
				"9yqtfKzn7+oyWAsLu7xO5nYJQGZZJTIKZi3B9nR6Q8gpQ3qgFVEmQzF6x4MRypOH/TasspWnxV7Y" + 
				"0zXl6CU7KXpIBfakfslOI1mPK1LycduWugxkLhkGngwFTH60HnB5hziAWyEmh1VJUHnoOERMBRtM" + 
				"rFFyPR3ZKUBGDFm8dpBAgXEvow0dXhurTS3SEUkw5vEAa/0M1YB9TxQyGsIP9PMtI+TqBc9CS+xA" + 
				"X+Ls6forCLWykjxPaEKDafH4F8dumrNvLYHWtBI/XAwwmTelhMSQcLCH5pF1PM4Svn9DoPchXp3A" + 
				"BMVfcr66BStNuz35L5IW6UHNOYQHQMKjySU76yrXwn476ri0SYKp8+x1EQZuUK+T5zI2RvMLZa/8" + 
				"EhWT79EoIXUjHQbo7vjTRsmoboLNq3lfd6OUcQf8tB+2+QQkMHWH4Ew0VTxpaUfc4NpjVvxoneig" + 
				"qwnL8xFgtznEFAtiMqLWzbnTM+Fsy0EL3y0nQvYkl+4qJ+pwBdT2588zff8tCkAPqyd2KAD5e2pG" + 
				"GfIaKtAjrcZ0OQOZy5GkwP7DJIptKcjCZBHmrV6wLdHCNqg8+29dxJHjSDMS+COMNEDjECoPIcWY" + 
				"1K6VTzZqOqYxOuqJK79nVIIL7lkrYn1Sr4j7jLi4RqtGPEiVURPsfoCqHlZ0mQskztIvmF6dokOU" + 
				"rlz46ad6kJ5B16zck1Ubk7MSrbsWoJN08WvNKn5nzgpyxecpmaX3Z4DcPTWl1fHdb7QId2F0aGRh" + 
				"dGGJARwEEAECAAYFAl6MQAIACgkQwoTQRV6mufd8bgf/QbgWncZmYBh8s2BzGovEwUsU/FJ1+37o" + 
				"0TyY6YoO4p2yIdhw6l0G+bhhR4H2rJkYN4Ye9FjdXPMNdTtAwPr85cpnewN9xNzLQKvY7XLsk0gn" + 
				"ML3Vxn2Sug/inS2ZzBJEaWj4EjsbmgNdIz+l/Tn7wkTnmdeHy5DQxpjL/DHJ+nYQN4uPYUwWMW5b" + 
				"XXZrTQpPVfMypnjdRt2yp7eyyGIYVMDi0be1BCHWwCMXo0sycCj+nHN6RwYHxHOS5xbQz30gCaaE" + 
				"ySwc+cfBDfAqXw0CQklfJdOZC1Dr+Nsn5+x0iP8Uk2Clzn6kRtL69TGQ5QdezbBNDnLQVqDtHnY+" + 
				"zUw7cw==";

		Security.addProvider(new BouncyCastleProvider());
		encryptFile("c://2.pgp", "c://2.txt", keyString, true, true); // 加密文件
		decryptFile("c://2.pgp", privateKeyString, "123456789".toCharArray(), "c://3.txt");// 解密文件

	}

}

大家可以直接拿来使用上面的代码,文件加解密和公私钥对生成都已经提供测试方法
并且上面的方法已经通过了PGP Desktop工具验证
java 实现PGP生成公私钥对生成,以及加解密文件_第1张图片

你可能感兴趣的:(Java)