posts - 33, comments - 46, trackbacks - 0, articles - 2

          JIRA 3.3.2注冊與DSA簽名算法研究

          Posted on 2005-10-24 13:58 在路上... 閱讀(1640) 評論(2)  編輯  收藏 所屬分類: java軟件研究
          最近安裝了一個JIRA,順便研究了一下它的注冊機制,屬于一個典型的DSA簽名算法的實現,按照常理,很自然的想到自己生成一對publickey和privatekey替換掉原來軟件帶的publickey,就可以生成自己的注冊碼了。
          但是搞定才發現網上有很多的注冊機,想不到DSA算法的privatekey也有人能夠分析出來??經過驗證,事實就擺在面前了,的確從JIRA 2.6.1開始這對密匙就沒變過,所以注冊機就可以一直沿用到現在了,難道在早期的版本不小心將私匙給泄漏出來了?或者所謂的黑客真的破解了JIRA的密匙?
          首先分析一下JIRA的內部機制,與注冊相關的對象都放在com.atlassian.license包下面,其中publickey的文件名是bug.class,在com\atlassian\jira\issue下面,其中WEB-INF\classes和atlassian-extras-0.7.10.jar中各有一個。利用下面代碼就可以讀出publickey的內容了:
          InputStream keyfis=new FileInputStream(pubfilename);
                      
          byte encKey[] = new byte[keyfis.available()];
                      keyfis.read(encKey);
                      keyfis.close();
                      X509EncodedKeySpec pubKeySpec 
          = new X509EncodedKeySpec(encKey);
                      KeyFactory keyFactory 
          = KeyFactory.getInstance("DSA");
                      PublicKey pubkey
          =keyFactory.generatePublic(pubKeySpec);
                      DSAPublicKeySpec pubkeyspec
          =(DSAPublicKeySpec) keyFactory.getKeySpec(pubkey, DSAPublicKeySpec.class);
                      System.out.println(
          "P="+pubkeyspec.getP());
                      System.out.println(
          "Q="+pubkeyspec.getQ());
                      System.out.println(
          "G="+pubkeyspec.getG());
                      System.out.println(
          "Y="+pubkeyspec.getY());

          運行結果如下:
          P=178011905478542266528237562450159990145232156369120674273274450314442865788737020770612695252123463079567156784778466449970650770920727857050009668388144034129745221171818506047231150039301079959358067395348717066319802262019714966524135060945913707594956514672855690606794135837542707371727429551343320695239
          Q
          =864205495604807476120572616017955259175325408501
          G
          =174068207532402095185811980123523436538604490794561350978495831040599953488455823147851597408940950725307797094915759492368300574252438761037084473467180148876118103083043754985190983472601550494691329488083395492313850000361646482644608492304078721818959999056496097769368017749273708962006689187956744210730
          Y
          =104878378611578608516131988304241730575226860461304117604293580069983220227094632807881557460560834347944389679413307090500106772833435437017122610074687673247552012771759005247409187709312922876281831426019398155097541955193653855246734321859930303643524786168850036251099739995507172205951987756012523624501

          如果有興趣可以從這里入手去找尋privatekey的X,難度可想而知,但是在網上可以下載的注冊機中就有X,不管你是否相信,真讓人懷疑DSA的安全性,值如下:
          X=240907294874328356661328650403099424255880489796
          這下就可以很方便的生成注冊碼了:
          明文:licenseTypeCode ^ dateCreated ^ datePurchased ^ organisation
          其中licenseTypeCode =267就是JIRA Enterprise: Commercial Server
          dateCreated =datePurchased =new Date()就可以了
          organisation隨便
          代碼如下:
          import com.atlassian.license.LicensePair;

          import java.math.BigInteger;
          import java.security.KeyFactory;
          import java.security.Signature;
          import java.security.interfaces.DSAPrivateKey;
          import java.security.spec.DSAPrivateKeySpec;
          import java.util.Date;

          public class JIRAKeyGen {
              
          public static void main(String[] args) {
                  Date dt 
          = new Date();
                  
          long d = dt.getTime();
                  BigInteger x 
          = new BigInteger("240907294874328356661328650403099424255880489796");
                  BigInteger p 
          = new BigInteger("178011905478542266528237562450159990145232156369120674273274450314442865788737020770612695252123463079567156784778466449970650770920727857050009668388144034129745221171818506047231150039301079959358067395348717066319802262019714966524135060945913707594956514672855690606794135837542707371727429551343320695239");
                  BigInteger q 
          = new BigInteger("864205495604807476120572616017955259175325408501");
                  BigInteger g 
          = new BigInteger("174068207532402095185811980123523436538604490794561350978495831040599953488455823147851597408940950725307797094915759492368300574252438761037084473467180148876118103083043754985190983472601550494691329488083395492313850000361646482644608492304078721818959999056496097769368017749273708962006689187956744210730");
                  
          try {
                      DSAPrivateKeySpec keyspec 
          = new DSAPrivateKeySpec(x, p, q, g);
                      KeyFactory keyFactory 
          = KeyFactory.getInstance("DSA");
                      DSAPrivateKey prikey 
          = (DSAPrivateKey) keyFactory.generatePrivate(keyspec);
                      String messageString 
          = "267^" + d + "^" + d + "^blogjava";
                      
          //生成簽名hash
                      Signature signature = Signature.getInstance("SHA1withDSA");
                      signature.initSign(prikey);
                      signature.update(messageString.getBytes());
                      
          byte[] lichash = signature.sign();
                      
          //編碼
                      LicensePair pair = new LicensePair(messageString.getBytes(), lichash);
                      System.out.println(pair.toString());
                  }
           catch (Exception ex) {
                      ex.printStackTrace();
                  }

              }

          }

            當然還有另外一種方法,自己生成DSA算法的key,然后覆蓋原來的bug.class,利用與上面相同的辦法就可以生成license了。
          示例代碼如下:

          public void genDSAKey() {
                  
          try {
                      
          //生成DSA key
                      KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA");
                      KeyPair kp 
          = gen.genKeyPair();
                      DSAPublicKey pubkey 
          = (DSAPublicKey) kp.getPublic();
                      DSAPrivateKey prikey 
          = (DSAPrivateKey) kp.getPrivate();
                      saveEncodedData(pubkey.getEncoded(), 
          "bug.class");
                      saveEncodedData(prikey.getEncoded(), 
          "privatekey.key");
                      
          //簽名計算,下次需要直接從文件中讀取privatekey.key,初始化prikey
                      Signature signature = Signature.getInstance("SHA1withDSA");
                      signature.initSign(prikey);
                      Date dt
          =new Date();
                      
          long d = dt.getTime();
                      String messageString 
          = "267^" + d + "^" + d + "^blogjava";
                      System.out.println(dt.getTime());
                      signature.initSign(prikey);
                      signature.update(messageString.getBytes());
                      
          byte[] lichash=signature.sign();
                      LicensePair pair
          =new LicensePair(messageString.getBytes(),lichash);
                      System.out.println(pair.toString());
                  }
           catch (Exception ex) {
                      ex.printStackTrace();
                  }

              }


              
          public boolean saveEncodedData(byte[] data, String filename) {
                  
          boolean res = true;
                  
          try {
                      FileOutputStream fs 
          = new FileOutputStream(filename);
                      fs.write(data);
                      fs.close();
                  }
           catch (Exception ex) {
                      res 
          = false;
                      ex.printStackTrace();
                  }

                  
          return res;
              }

          注意上面的代碼需要調用atlassian-extras-0.7.10,在WEB-INF\lib目錄下面可以找到

          Feedback

          # re: JIRA 3.3.2注冊與DSA簽名算法研究  回復  更多評論   

          2006-06-13 15:15 by lhy
          果然好用

          # re: JIRA 3.3.2注冊與DSA簽名算法研究  回復  更多評論   

          2009-01-20 12:43 by lucktu
          唉,實在慚愧,還不知怎么用。

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 神木县| 布拖县| 门源| 阿城市| 图片| 玉山县| 沈丘县| 安龙县| 礼泉县| 贵州省| 镇雄县| 衡阳市| 嘉鱼县| 睢宁县| 怀安县| 康马县| 临高县| 宝山区| 福海县| 临清市| 库伦旗| 思南县| 吉林省| 通化县| 黄冈市| 白水县| 山西省| 扶风县| 桐城市| 开封市| 师宗县| 秀山| 竹北市| 武平县| 成武县| 政和县| 兴化市| 绍兴县| 伊金霍洛旗| 蕲春县| 苏州市|