在我的上一篇文章中介紹了如何進行GPG加密解密。http://www.aygfsteel.com/usherlight/archive/2014/12/10/421238.html
加密解密的基本操作流程是,用戶使用公鑰對明文進行加密,解密方使用私鑰對密文進行解密。
在實際應用中,除了加密保證文本內容不泄露外,同時還要考慮能夠驗證密文發(fā)送方的身份,比較普遍使用的方法就是簽名。
本文主要對具體的方法進行介紹并附上源代碼。
舉例說明:
有用戶張三需要發(fā)送文本給李四,首先張三會生成一對公鑰1和私鑰1,張三自己保留私鑰1,并把公鑰1發(fā)送給李四用于加密。
現在的問題是張三在收到一份密文的時候,如何能夠確保這份密文是由李四而不是王五發(fā)的。
實現這個的過程我們稱之為簽名。
流程如下:李四也需要生成一對公鑰2和私鑰2,李四保留私鑰2,把公鑰2發(fā)給張三。
李四在發(fā)送密文的時候,除了使用公鑰1進行加密,還需要使用私鑰2進行簽名。
張三在收到密文后,隊了使用私鑰1進行解密,還需要使用公鑰2進行簽名驗證。
大致過程明白之后,可能會發(fā)現了一個問題,是先加密再簽名好呢,不是先簽名再加密?
驗證簽名的源代碼:函數中的兩個參數,第一個參數就是需要驗證簽名的內容輸入流,第二個參數是公鑰的輸入流
加密解密的基本操作流程是,用戶使用公鑰對明文進行加密,解密方使用私鑰對密文進行解密。
在實際應用中,除了加密保證文本內容不泄露外,同時還要考慮能夠驗證密文發(fā)送方的身份,比較普遍使用的方法就是簽名。
本文主要對具體的方法進行介紹并附上源代碼。
舉例說明:
有用戶張三需要發(fā)送文本給李四,首先張三會生成一對公鑰1和私鑰1,張三自己保留私鑰1,并把公鑰1發(fā)送給李四用于加密。
現在的問題是張三在收到一份密文的時候,如何能夠確保這份密文是由李四而不是王五發(fā)的。
實現這個的過程我們稱之為簽名。
流程如下:李四也需要生成一對公鑰2和私鑰2,李四保留私鑰2,把公鑰2發(fā)給張三。
李四在發(fā)送密文的時候,除了使用公鑰1進行加密,還需要使用私鑰2進行簽名。
張三在收到密文后,隊了使用私鑰1進行解密,還需要使用公鑰2進行簽名驗證。
大致過程明白之后,可能會發(fā)現了一個問題,是先加密再簽名好呢,不是先簽名再加密?
推薦先簽名再加密,因為先加密再簽名可能會有一些安全上的小漏洞。詳細的說明會比較長。
簡單的說:簽名并不能保證簽名者知道密文的內容。
一個簡單的小例子:小趙發(fā)了一個信息給管理員,內容如下:請把root密碼告訴我。然后小趙用管理員的公鑰進行了加密,然后用小趙自己的私鑰進行了簽名。
但是如果小錢截獲了密文,他可以使用小趙的公鑰去除掉簽名,然后使用小錢的私鑰進行簽名,發(fā)給管理員。管理員收到加密簽名的信息,就會把密碼發(fā)給小錢。
驗證簽名的源代碼:函數中的兩個參數,第一個參數就是需要驗證簽名的內容輸入流,第二個參數是公鑰的輸入流
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
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