Posted on 2015-12-11 21:40
云自无心水自闲 阅读(1247)
评论(0) 编辑 收藏 所属分类:
Java 、
心得体会 、
密码
在我的上一篇文章中介绍了如何进行GPG加密解密。
http://www.blogjava.net/usherlight/archive/2014/12/10/421238.html加密解密的基本操作流程是,用户使用公钥对明文进行加密,解密方使用私钥对密文进行解密。 在实际应用中,除了加密保证文本内容不泄露外,同时还要考虑能够验证密文发送方的身份,比较普遍使用的方法就是签名。
本文主要对具体的方法进行介绍并附上源代码。
举例说明:有用户张三需要发送文本给李四,首先张三会生成一对公钥1和私钥1,张三自己保留私钥1,并把公钥1发送给李四用于加密。现在的问题是张三在收到一份密文的时候,如何能够确保这份密文是由李四而不是王五发的。实现这个的过程我们称之为签名。
流程如下:李四也需要生成一对公钥2和私钥2,李四保留私钥2,把公钥2发给张三。李四在发送密文的时候,除了使用公钥1进行加密,还需要使用私钥2进行签名。张三在收到密文后,队了使用私钥1进行解密,还需要使用公钥2进行签名验证。大致过程明白之后,可能会发现了一个问题,是先加密再签名好呢,不是先签名再加密?推荐先签名再加密,因为先加密再签名可能会有一些安全上的小漏洞。详细的说明会比较长。
简单的说:签名并不能保证签名者知道密文的内容。
一个简单的小例子:小赵发了一个信息给管理员,内容如下:请把root密码告诉我。然后小赵用管理员的公钥进行了加密,然后用小赵自己的私钥进行了签名。
但是如果小钱截获了密文,他可以使用小赵的公钥去除掉签名,然后使用小钱的私钥进行签名,发给管理员。管理员收到加密签名的信息,就会把密码发给小钱。
验证签名的源代码:函数中的两个参数,第一个参数就是需要验证签名的内容输入流,第二个参数是公钥的输入流
1 /*
2 * verify the passed in file as being correctly signed.
3 */
4 private static void verifyFile(
5 InputStream in,
6 InputStream keyIn)
7 throws Exception
8 {
9 in = PGPUtil.getDecoderStream(in);
10 JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(in);
11 PGPCompressedData c1 = (PGPCompressedData)pgpFact.nextObject();
12 pgpFact = new JcaPGPObjectFactory(c1.getDataStream());
13 PGPOnePassSignatureList p1 = (PGPOnePassSignatureList)pgpFact.nextObject();
14 PGPOnePassSignature ops = p1.get(0);
15 PGPLiteralData p2 = (PGPLiteralData)pgpFact.nextObject();
16 InputStream dIn = p2.getInputStream();
17 int ch;
18 PGPPublicKeyRingCollection pgpRing = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(keyIn), new JcaKeyFingerprintCalculator());
19 PGPPublicKey key = pgpRing.getPublicKey(ops.getKeyID());
20 FileOutputStream out = new FileOutputStream(p2.getFileName());
21 ops.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), key);
22 while ((ch = dIn.read()) >= 0)
23 {
24 ops.update((byte)ch);
25 out.write(ch);
26 }
27 out.close();
28 PGPSignatureList p3 = (PGPSignatureList)pgpFact.nextObject();
29 if (ops.verify(p3.get(0)))
30 {
31 System.out.println("signature verified.");
32 }
33 else
34 {
35 System.out.println("signature verification failed.");
36 }
37 }
38