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

JIRA 3.3.2注册与DSA签名算法研究

Posted on 2005-10-24 13:58 在路上... 阅读(1598) 评论(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
唉,实在惭愧,还不知怎么用。

只有注册用户登录后才能发表评论。


网站导航: