2012-07-26 46 views
40

其實這是一個有點傻關於保護公共密鑰(什麼是公共密鑰的定義呢?),但作爲每documentation by Google如何保護做應用程式內結算時,谷歌播放公鑰

爲了保持您的公共密鑰不受惡意用戶和黑客的侵害,因此不要將 作爲文字字符串嵌入到任何代碼中。相反,在運行時從零件構造 字符串或使用位操作(例如, XOR與其他字符串)來隱藏實際的鍵。密鑰本身並不是祕密信息,但您不希望讓黑客或惡意用戶輕易地用另一個密鑰替換公鑰。

有沒有推薦的方法來做到這一點?

我知道有很多方法可以做到這一點,我只是不希望用同樣的方法的人如何處理密碼在過去的散列(例如MD5,SHA1等),我想知道的最佳實踐在上面的用例中。

回答

35

在這裏出現很多:)您引用的段落背後的想法是,爲了保證應用內結算安全,您需要驗證交易簽名。這些使用與您的開發者帳戶相關聯的私鑰進行簽名。關鍵在於Google的服務器,所以假設沒有其他人可以用它來簽署數據是相當安全的。要驗證它,您需要您的公鑰,您可以從開發者控制檯複製該公鑰。如果有人在您的應用中替換了它,他們可能會欺騙它接受來自未授權來源的應用內結算交易,因爲如果他們種植公鑰,他們可能也會控制相應的私鑰。然而,在實踐中,只需在正確的位置修改代碼,以便始終爲isLicensed()hasItem()或您可能具有的類似方法返回true,並且沒有人執行此操作,則更容易。

保護密鑰的最佳方式當然不是在您的應用中擁有密鑰。將所有交易驗證邏輯移至您的服務器,並使用HTTPS連接至您的服務器。正確驗證證書鏈以確保您正在與自己的服務器通信。否則,有人可能會混淆DNS並欺騙你的應用程序連接到他們自己的服務器。幾周前宣佈了針對iOS採購的類似攻擊。

接下來最好的辦法是以某種方式混淆密鑰,並將其包含在您的應用中。這樣做的好處是你不需要服務器,但缺點是如果有人足夠肯定,他們會發現它,因爲它們總是可以顛倒你的應用程序的字節碼。所以你最好的選擇是提出你自己的原創方式,它不會在公共論壇上顯示出來:)爲了讓它更難一點,你可以在本地代碼中實現驗證部分,這很難(但不是不可能)分析。不過,正如上面提到的,在正確的位置修補字節代碼比試圖替換公鑰更容易,所以這就是大多數破解者所要做的。

+1

你是什麼意思「然而,在實踐中,在正確的位置簡單地修改你的代碼總是爲isLicensed(),hasItem()或類似的方法你可能有,沒有人這樣做。「?這句話沒有完全意義。請澄清。 – Stunner 2013-01-16 21:41:22

+10

這意味着修補應用程序並徹底禁用您可能擁有的任何許可檢查會更容易,而不是嘗試更換密鑰和混亂嘗試欺騙簽名驗證。 – 2013-01-17 01:06:53

+0

〜「**可能也會控制相應的私鑰**」。但是,應用內結算請求會通過設備上的Play Store APK進行。那麼,某人如何控制或操縱該邏輯? – 2016-09-02 14:29:36

4

將您的公鑰存儲在服務器端,一旦您從google play獲得響應,以驗證密鑰將響應發送到服務器並在服務器上執行您的操作。

+1

這假定有一個這樣的服務器端基礎設施建立。 – 2016-09-02 14:40:40

32

做至少簡單的文字轉換。這個想法是,普通的dex反彙編不會揭示你的公鑰。

這裏的實施例的功能,使得簡單的字符串編碼/解碼:

/** 
* Simple String transformation by XOR-ing all characters by value. 
*/ 
static String stringTransform(String s, int i) { 
    char[] chars = s.toCharArray(); 
    for(int j = 0; j<chars.length; j++) 
     chars[j] = (char)(chars[j]^i); 
    return String.valueOf(chars); 
} 

然後您的私人密鑰被存儲在源作爲編碼的字符串(與此功能進行編碼的話),並在具有相同功能的運行時解碼。這是Google建議的一種「異或」方法。

你自己製作'i'參數,任何隨機的東西,比如0x27或其他都可以。 如果以這種方式隱藏更多字符串,請對每個轉換使用不同的「i」。

+14

神祕:)如果你是程序員,你肯定會克服這樣的問題。 – 2012-08-02 10:02:30

+2

@NPike,你需要轉義字符串才能在Java中使用它。試試這個網站:http://www.htmlescape.net/javaescape_tool.html不幸的是,我發現轉換過程通常會導致Eclipse無法應對的字符串(即使在轉義時),所以您必須調整直到你得到一些你可以使用的值... – 2013-06-11 23:47:03

11

作爲手動混淆密鑰的替代方法,您還可以讓混淆器自動執行此操作。 ProGuard是Android SDK的一部分,但它主要混淆了類/字段/方法名稱,而不是字符串。它的Android專用同級,DexGuard可以添加更多層混淆,應用字符串加密,類加密和反射。這不是免費的,但它可以節省時間,而且可能比手動更有效。

(我的ProGuard和DexGuard的開發者)

+0

真棒!謝謝..異或方法是安全的?? – 2012-08-28 10:26:53

+1

DexGuard是否僅僅是對一個簡單的字符串進行混淆就是矯枉過正?我的意思是,無論如何,它能做到這一點的保證是什麼? – 2016-09-02 14:39:53

1

公鑰是base64編碼([a-zA-Z0-9+/]),這樣你可以很容易地避免需要躲避混淆字符串,就好象是在@ PointerNull的一個惱人的問題解。

相反,您可以通過首先將相關字符轉換爲6位整數來執行混淆處理。然後進行位操作(例如異或),然後轉換回base64編碼的字符。保證不需要角色轉義。

相關問題