云自無心水自閑

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

          openpgp 驗證簽名

          Posted on 2015-12-11 21:40 云自無心水自閑 閱讀(1289) 評論(0)  編輯  收藏 所屬分類: Java心得體會密碼
          在我的上一篇文章中介紹了如何進行GPG加密解密。http://www.aygfsteel.com/usherlight/archive/2014/12/10/421238.html
          加密解密的基本操作流程是,用戶使用公鑰對明文進行加密,解密方使用私鑰對密文進行解密。 

          在實際應(yīng)用中,除了加密保證文本內(nèi)容不泄露外,同時還要考慮能夠驗證密文發(fā)送方的身份,比較普遍使用的方法就是簽名。
          本文主要對具體的方法進行介紹并附上源代碼。
          舉例說明:
          有用戶張三需要發(fā)送文本給李四,首先張三會生成一對公鑰1和私鑰1,張三自己保留私鑰1,并把公鑰1發(fā)送給李四用于加密。
          現(xiàn)在的問題是張三在收到一份密文的時候,如何能夠確保這份密文是由李四而不是王五發(fā)的。
          實現(xiàn)這個的過程我們稱之為簽名。
          流程如下:李四也需要生成一對公鑰2和私鑰2,李四保留私鑰2,把公鑰2發(fā)給張三。

          李四在發(fā)送密文的時候,除了使用公鑰1進行加密,還需要使用私鑰2進行簽名。
          張三在收到密文后,隊了使用私鑰1進行解密,還需要使用公鑰2進行簽名驗證。

          大致過程明白之后,可能會發(fā)現(xiàn)了一個問題,是先加密再簽名好呢,不是先簽名再加密?
          推薦先簽名再加密,因為先加密再簽名可能會有一些安全上的小漏洞。詳細的說明會比較長。
          簡單的說:簽名并不能保證簽名者知道密文的內(nèi)容。
          一個簡單的小例子:小趙發(fā)了一個信息給管理員,內(nèi)容如下:請把root密碼告訴我。然后小趙用管理員的公鑰進行了加密,然后用小趙自己的私鑰進行了簽名。
          但是如果小錢截獲了密文,他可以使用小趙的公鑰去除掉簽名,然后使用小錢的私鑰進行簽名,發(fā)給管理員。管理員收到加密簽名的信息,就會把密碼發(fā)給小錢。

          驗證簽名的源代碼:函數(shù)中的兩個參數(shù),第一個參數(shù)就是需要驗證簽名的內(nèi)容輸入流,第二個參數(shù)是公鑰的輸入流
           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 


          主站蜘蛛池模板: 墨竹工卡县| 凤冈县| 洛扎县| 高清| 盐城市| 禹城市| 伊宁县| 揭西县| 建瓯市| 永州市| 沭阳县| 中牟县| 昌宁县| 积石山| 景德镇市| 神木县| 左权县| 育儿| 汉阴县| 湟中县| 台江县| 祁阳县| 将乐县| 新营市| 安国市| 榕江县| 全椒县| 区。| 潮安县| 二连浩特市| 包头市| 理塘县| 宝清县| 张家川| 勐海县| 西青区| 洛宁县| 凭祥市| 盐源县| 开鲁县| 沙河市|