|
大眼夾的鳥(niǎo)巢
2012-12-273387 閱讀 JIRA在Atlassian開(kāi)發(fā)的各種產(chǎn)品中算是最著名的一個(gè),它主要是用來(lái)做產(chǎn)品缺陷跟蹤和項(xiàng)目管理的。JIRA是商業(yè)軟件,它的授權(quán)是按使用用戶數(shù)劃分的,最便宜的10用戶版本只要10美元,這極大地方便了小型團(tuán)隊(duì)的開(kāi)發(fā),不過(guò)25個(gè)用戶的授權(quán)版本就高達(dá)1200美元了。今天來(lái)講一講JIRA的軟件許可證是如何授權(quán)的。事實(shí)上Atlassian的諸多產(chǎn)品例如協(xié)作和內(nèi)容共享應(yīng)用Confluence、版本控制解決方案Stash等都是采用的類(lèi)似的授權(quán)機(jī)制。 more從一條Lincense談起在Atlassian網(wǎng)站上,用戶可以申請(qǐng)JIRA的一個(gè)月試用許可證。授權(quán)信息的生成需要用戶提供一個(gè)Server ID,它是在安裝完JIRA第一次啟動(dòng)時(shí)由客戶端生成的。隨后便可以得到一個(gè)完整的許可證字符串: AAABDg0ODAoPeNptUNtKxDAQfc9XBHyOpKlttZCH2gas9LK0VRF8idlRI91akrS4f293q4iyMAPDnMsc5uwBtjgDhVmI6VXsRbEf4rTtMKMeQxlYZfTo9MfAb/MmeYqxmGU/ycMGpQaOQyYd8AOfLMUi9 K6NPC+0gsGC2OqjWlSdaDZN3gr068CdmeAPvduPUMkd8LQuS9GkeVKsuFROz7AK+pV7D8YeTBgqp R4cDHJQID5HbfY/iXxCPcJCVJtXOWi7Hk17PY7a4Q6sW82rafcMpn65s4slJx5qwcxg8oxf06AgNTzSZFEAWkuxCNqRcWXJgXzaHQZROg7+0Iv8uwUcjrUZjLqTVr4/74vnyt/nTAsAhR8v6Zm5YfvZWVBnwouY7xhT+jwUgIUbRhGVaC8P9JCvDPT1MXIwnCgGqA=X02dp 明眼人一看這顯然是經(jīng)過(guò)Base64編碼的,不過(guò)在補(bǔ)齊長(zhǎng)度的結(jié)尾 解碼Base64以下的內(nèi)容用Python演示,首先將其解碼。 >>> license = 'AAABDg0ODAoPeNptUNtKxDAQfc9XBHyOpKlttZCH2gas9LK0VRF8idlRI91akrS4f
q4iyMAPDnMsc5uwBtjgDhVmI6VXsRbEf4rTtMKMeQxlYZfTo9MfAb/MmeYqxmGU/ycMGpQaOQyYd8
AOfLMUi9K6NPC+0gsGC2OqjWlSdaDZN3gr068CdmeAPvduPUMkd8LQuS9GkeVKsuFROz7AK+pV7D8YeT
BgqpR4cDHJQID5HbfY/iXxCPcJCVJtXOWi7Hk17PY7a4Q6sW82rafcMpn65s4slJx5qwcxg8oxf06AgN
TzSZFEAWkuxCNqRcWXJgXzaHQZROg7+0Iv8uwUcjrUZjLqTVr4/74vnyt/nTAsAhR8v6Zm5YfvZWVBn
wouY7xhT+jwUgIUbRhGVaC8P9JCvDPT1MXIwnCgGqA='>>> len(license)>>> import base64>>> s = base64.b64decode(license)>>> s'\x00\x00\x01\x0e\r\x0e\x0c\n\x0fx\xdamP\xdbJ\xc40\x10}\xcfW\x04|\x8e\xa4\xa9m\x
b5\x90\x87\xda\x06\xac\xf4\xb2\xb4U\x11|\x89\xd9Q#\xddZ\x92\xb4\xb8\x7fow\xab\x8
\xb20\x03\xc3\x9c\xcb\x1c\xe6\xec\x01\xb68\x03\x85Y\x88\xe9U\xecE\xb1\x1f\xe2\x
b4\xed0\xa3\x1eC\x19Xe\xf4\xe8\xf4\xc7\xc0o\xf3&y\x8a\xb1\x98e?\xc9\xc3\x06\xa5x06\x8eC&\x1d\xf0\x03\x9f,\xc5"\xf4\xae\x8d</\xb4\x82\xc1\x82\xd8\xea\xa3ZT\x9dh
M\xde\n\xf4\xeb\xc0\x9d\x99\xe0\x0f\xbd\xdb\x8fP\xc9\x1d\xf0\xb4.K\xd1\xa4yR\xa
c\xb8TN\xcf\xb0\n\xfa\x95{\x0f\xc6\x1eL\x18*\xa5\x1e\x1c\x0crP >Gm\xf6?\x89|B=\x
c2BT\x9bW9h\xbb\x1eM{=\x8e\xda\xe1\x0e\xac[\xcd\xabi\xf7\x0c\xa6~\xb9\xb3\x8b%\'
\x1ej\xc1\xcc`\xf2\x8c_\xd3\xa0 7\xb4\xf3I\x91D\x01i.\xc4#jE\xc5\x97&\x05\xf3htx19D\xe8;\xfbB/\xf2\xec\x14r:\xd4f2\xeaMZ\xf8\xff\xbe/\x9f+\x7f\x9d0,\x02\x14|\x
bf\xa6f\xe5\x87\xefeeA\x9f\n.c\xbcaO\xe8\xf0R\x02\x14m\x18FU\xa0\xbc?\xd2B\xbc3xd3\xd4\xc5\xc8\xc2p\xa0\x1a\xa0'解碼出來(lái)的內(nèi)容,由三部分組成。第一部分是前四個(gè)字節(jié),代表著第二部分的長(zhǎng)度,因此根據(jù)第一部分的值便可以切割出后面兩個(gè)部分。 在上面的例子中,一個(gè)部分的值是 (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff)) Java的內(nèi)部編碼基本遵循UTF-32BE,即將Unicode全部字符用四字節(jié)固定長(zhǎng)度編碼,并且字節(jié)序?yàn)锽ig Endian。在Python端,我們可以這樣解碼: >>> ord(s[:4].decode('UTF-32BE'))得到了這個(gè)長(zhǎng)度,便可以將上面的內(nèi)容分割成兩部分了,稱前一部分為 >>> licenseText, licenseSig = s[4:4 + 270], s[4 + 270:]>>> licenseText'\r\x0e\x0c\n\x0fx\xdamP\xdbJ\xc40\x10}\xcfW\x04|\x8e\xa4\xa9m\xb5\x90\x87\xda\x
\xac\xf4\xb2\xb4U\x11|\x89\xd9Q#\xddZ\x92\xb4\xb8\x7fow\xab\x88\xb20\x03\xc3\x
c\xcb\x1c\xe6\xec\x01\xb68\x03\x85Y\x88\xe9U\xecE\xb1\x1f\xe2\xb4\xed0\xa3\x1eC
\x19Xe\xf4\xe8\xf4\xc7\xc0o\xf3&y\x8a\xb1\x98e?\xc9\xc3\x06\xa5\x06\x8eC&\x1d\xf
\x03\x9f,\xc5"\xf4\xae\x8d</\xb4\x82\xc1\x82\xd8\xea\xa3ZT\x9dh6M\xde\n\xf4\xeb
\xc0\x9d\x99\xe0\x0f\xbd\xdb\x8fP\xc9\x1d\xf0\xb4.K\xd1\xa4yR\xac\xb8TN\xcf\xb0n\xfa\x95{\x0f\xc6\x1eL\x18*\xa5\x1e\x1c\x0crP >Gm\xf6?\x89|B=\xc2BT\x9bW9h\xbbx1eM{=\x8e\xda\xe1\x0e\xac[\xcd\xabi\xf7\x0c\xa6~\xb9\xb3\x8b%\'\x1ej\xc1\xcc`\x
f2\x8c_\xd3\xa0 7\xb4\xf3I\x91D\x01i.\xc4#jE\xc5\x97&\x05\xf3ht\x19D\xe8;\xfbB/xf2\xec\x14r:\xd4f2\xeaMZ\xf8\xff\xbe/\x9f+\x7f\x9d'>>> licenseSig'0,\x02\x14|\xbf\xa6f\xe5\x87\xefeeA\x9f\n.c\xbcaO\xe8\xf0R\x02\x14m\x18FU\xa0\x
bc?\xd2B\xbc3\xd3\xd4\xc5\xc8\xc2p\xa0\x1a\xa0'zlib 解壓縮
>>> map(ord, '\r\x0e\x0c\n\x0f')[13, 14, 12, 10, 15] 去掉這個(gè)前綴后的內(nèi)容是經(jīng)過(guò)zlib壓縮的,我們將其解壓后便得到了原始的許可證內(nèi)容。 >>> import zlib>>> licenseTextOriginal = zlib.decompress(licenseText[5:])>>> print licenseTextOriginal#Wed Dec 26 09:17:36 CST 2012Description=JIRA\: EvaluationCreationDate=2012-12-27jira.LicenseEdition=ENTERPRISEEvaluation=truejira.LicenseTypeName=COMMERCIAL jira.active=truelicenseVersion=2MaintenanceExpiryDate=2013-01-26Organisation=Clippit Testjira.NumberOfUsers=-1ServerID=ABCD-1234-EFGH-5678SEN=SEN-L2107857LicenseID=LIDSEN-L2107857LicenseExpiryDate=2013-01-26PurchaseDate=2012-12-27 上面的 DSA with SHA-1 數(shù)字簽名可以看到上面的各種方法至多可以保證許可證內(nèi)容的正確性,卻沒(méi)有辦法保證鑒別性和不可否認(rèn)性。JIRA采用了數(shù)字簽名的方法來(lái)確保軟件許可證的安全,具體而言,便是DSA算法。 DSA(Digital Signature Algorithm)和更為普遍的RSA算法一樣都是基于公鑰私鑰的加密系統(tǒng)(DSA和RSA的比較可以參考這里)。 JIRA客戶端中存儲(chǔ)的公鑰在atlassian-extras-2.2.2.jar文件的 >>> from M2Crypto import DSA>>> import hashlib>>> pk = DSA.load_pub_key('./official_pubkey.pem')>>> pk.verify_asn1(hashlib.sha1(licenseText).digest(), licenseSig)偽造數(shù)字簽名數(shù)字簽名的安全性還是極高的,通過(guò)公鑰推導(dǎo)出私鑰,以現(xiàn)有的計(jì)算能力是幾乎不可能的事。所以一般針對(duì)數(shù)字簽名的破解方法便是設(shè)法替換掉預(yù)設(shè)的公鑰,使用自己的密鑰對(duì)。創(chuàng)建密鑰對(duì)也是很簡(jiǎn)單的事: >>> dsa = DSA.gen_params(1024)..+.....+.......+.+.........+............+.+........+.......+++++++++++++++++++++++++++++++++++++++++++++++++++*.......+.......+....+..+.............+...................+...+........+........+....+.......+......+..........+....+.+....+............+..+....+.......+...+.+..+.........+...+..+................+.........+..+.......+..................+....+....+.................+.............+...........+++++++++++++++++++++++++++++++++++++++++++++++++++*>>> dsa.gen_key()>>> dsa.save_key('./private.pem', cipher=None)>>> dsa.save_pub_key('./public.pem')接下來(lái)的問(wèn)題便是如何修改編譯好的 許可證生成器既然全部的過(guò)程都已經(jīng)還原,那么反推一下便可以生成自己的許可證了。 額外的修改事實(shí)上,在JIRA中還有其他地方保存了這個(gè)公鑰,具體來(lái)說(shuō)是它的Universal Plugin Manager的相關(guān)代碼。如果僅僅修改了上面提到的文件,是沒(méi)有辦法使用JIRA的插件功能的。只有將所有有關(guān)的地方全部替換成自己偽造的公鑰,才能保證整個(gè)軟件全部可用。 作者:大眼夾的鳥(niǎo)巢
原文地址:Atlassian JIRA 授權(quán)許可證機(jī)制分析, 感謝原作者分享。 |
|
|
來(lái)自: quasiceo > 《待分類(lèi)1》