云自無心水自閑

          天平山上白云泉,云自無心水自閑。何必奔沖山下去,更添波浪向人間!
          posts - 288, comments - 524, trackbacks - 0, articles - 6
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          openpgp 驗證簽名

          Posted on 2015-12-11 21:40 云自無心水自閑 閱讀(1278) 評論(0)  編輯  收藏 所屬分類: Java心得體會密碼
          在我的上一篇文章中介紹了如何進行GPG加密解密。http://www.aygfsteel.com/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 


          主站蜘蛛池模板: 武宣县| 桂阳县| 新干县| 怀来县| 三江| 灵丘县| 桐柏县| 武邑县| 铅山县| 内乡县| 黑水县| 金堂县| 喜德县| 武穴市| 桂林市| 潼南县| 重庆市| 东兴市| 东台市| 丰原市| 阜新| 临汾市| 温泉县| 贺州市| 梅河口市| 鄂托克旗| 手机| 扎囊县| 尚志市| 西贡区| 万年县| 琼结县| 西丰县| 自治县| 且末县| 报价| 扎赉特旗| 南康市| 郸城县| 丁青县| 冕宁县|