Most app developers will integrate some third party libraries into their apps. If it's to access a service, such as Dropbox or YouTube, or for logging crashes. The number of third party libraries and services is staggering. Most of those libraries and services are integrated by somehow authenticating with the service, most of the time, this happens through an API key. For security purposes, services usually generate a public and private, often also referred to as secret, key. Unfortunately, in order to connect to the services, this private key must be used to authenticate and hence, probably be part of the application. Needless to say, that this faces in immense security problem. Public and private API keys can be extracted from APKs in a matter of minutes and can easily be automated.

假设我有类似的东西,我如何保护密钥:

public class DropboxService  {

    private final static String APP_KEY = "jk433g34hg3";
    private final static String APP_SECRET = "987dwdqwdqw90";
    private final static AccessType ACCESS_TYPE = AccessType.DROPBOX;

    // SOME MORE CODE HERE

}

你认为储存私钥的最佳及最安全的方法是什么?混淆,加密,你怎么看?


当前回答

老帖子,但仍然足够好。我认为把它藏在一个。so库中会很棒,当然使用NDK和c++。.so文件可以在十六进制编辑器中查看,但祝你能反编译它:P

其他回答

Whatever you do to secure your secret keys is not going to be a real solution. If developer can decompile the application there is no way to secure the key, hiding the key is just security by obscurity and so is code obfuscation. Problem with securing a secret key is that in order to secure it you have to use another key and that key needs to also be secured. Think of a key hidden in a box that is locked with a key. You place a box inside a room and lock the room. You are left with another key to secure. And that key is still going to be hardcoded inside your application.

因此,除非用户输入PIN或短语,否则无法隐藏密钥。但要做到这一点,你必须有一个方案来管理发生在带外的pin码,这意味着通过不同的渠道。当然,对于谷歌api这样的服务来说,保护密钥是不实际的。

app - secret密钥应该是私有的-但在发布应用程序时 它们可以被某些人逆转。

对于那些家伙,它不会隐藏,锁定或ProGuard的代码。这是一个重构,一些付费的混淆器正在插入一些位操作符以恢复jk433g34hg3 字符串。如果你工作3天,你可以延长5 -15分钟的黑客时间:)

恕我直言,最好的办法就是保持现状。

即使你存储在服务器端(你的PC),密钥也可能被黑客攻击并打印出来。也许这个花的时间最长?无论如何,在最好的情况下,这只是几分钟或几个小时的问题。

普通用户不会反编译你的代码。

将秘密保存在firebase数据库中,并在应用程序启动时从中获取, 它比调用web服务好得多。

保持这些隐私的唯一方法是把它们保存在你的服务器上,让应用程序把它们发送到服务器上,然后服务器与Dropbox交互。这样你就不会以任何格式分发你的私钥。

一个可能的解决方案是在应用程序中编码数据,并在运行时(当你想使用该数据时)使用解码。我还建议使用progaard来增加应用程序反编译源代码的阅读和理解难度。例如,我把一个编码的密钥在应用程序,然后使用解码方法在我的应用程序解码我的秘密密钥在运行时:

// "the real string is: "mypassword" "; 
//encoded 2 times with an algorithm or you can encode with other algorithms too
public String getClientSecret() {
    return Utils.decode(Utils
            .decode("Ylhsd1lYTnpkMjl5WkE9PQ=="));
}

一个受保护的应用程序的反编译源代码如下:

 public String c()
 {
    return com.myrpoject.mypackage.g.h.a(com.myrpoject.mypackage.g.h.a("Ylhsd1lYTnpkMjl5WkE9PQ=="));
  }

至少对我来说够复杂了。当我别无选择只能在我的应用程序中存储一个值时,我就是这样做的。当然我们都知道这不是最好的方法,但对我来说很管用。

/**
 * @param input
 * @return decoded string
 */
public static String decode(String input) {
    // Receiving side
    String text = "";
    try {
        byte[] data = Decoder.decode(input);
        text = new String(data, "UTF-8");
        return text;
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return "Error";
}

反编译版本:

 public static String a(String paramString)
  {
    try
    {
      str = new String(a.a(paramString), "UTF-8");
      return str;
    }
    catch (UnsupportedEncodingException localUnsupportedEncodingException)
    {
      while (true)
      {
        localUnsupportedEncodingException.printStackTrace();
        String str = "Error";
      }
    }
  }

你可以在谷歌中找到这么多的加密类。