云自無心水自閑

          天平山上白云泉,云自無心水自閑。何必奔沖山下去,更添波浪向人間!
          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
          加密解密的基本操作流程是,用戶使用公鑰對明文進行加密,解密方使用私鑰對密文進行解密。 

          在實際應用中,除了加密保證文本內容不泄露外,同時還要考慮能夠驗證密文發(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 


          主站蜘蛛池模板: 乐安县| 康保县| 新建县| 霸州市| 洛扎县| 繁峙县| 会同县| 新民市| 西华县| 鞍山市| 富裕县| 周口市| 宁武县| 临西县| 依安县| 云南省| 盐津县| 楚雄市| 平顶山市| 余江县| 灵宝市| 云梦县| 盐津县| 连江县| 闽清县| 游戏| 仁寿县| 汝南县| 甘肃省| 迁安市| 阿合奇县| 木里| 孝昌县| 宁强县| 吉安市| 宜宾县| 遵化市| 正镶白旗| 舒兰市| 婺源县| 永定县|