Android 在应用程序中存储和保护私有API密钥的最佳实践
大多数应用程序开发人员会将一些第三方库集成到他们的应用程序中。如果是访问服务,如Dropbox或YouTube,或是记录崩溃。第三方图书馆和服务的数量惊人。大多数库和服务都是通过某种方式与服务进行身份验证来集成的,大多数情况下,这是通过API密钥实现的。出于安全目的,服务通常生成公共和私有密钥,通常也称为机密密钥。不幸的是,为了连接到服务,必须使用该私钥进行身份验证,因此可能是应用程序的一部分。 不用说,这面临着巨大的安全问题。公共和私有API密钥可以在几分钟内从APK中提取,并且可以很容易地实现自动化 假设我有类似的东西,我如何保护密钥:Android 在应用程序中存储和保护私有API密钥的最佳实践,android,reverse-engineering,proguard,api-key,Android,Reverse Engineering,Proguard,Api Key,大多数应用程序开发人员会将一些第三方库集成到他们的应用程序中。如果是访问服务,如Dropbox或YouTube,或是记录崩溃。第三方图书馆和服务的数量惊人。大多数库和服务都是通过某种方式与服务进行身份验证来集成的,大多数情况下,这是通过API密钥实现的。出于安全目的,服务通常生成公共和私有密钥,通常也称为机密密钥。不幸的是,为了连接到服务,必须使用该私钥进行身份验证,因此可能是应用程序的一部分。 不用说,这面临着巨大的安全问题。公共和私有API密钥可以在几分钟内从APK中提取,并且可以很容易地实
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
}
您认为存储私钥的最佳和最安全的方法是什么?模糊处理,加密,你怎么看
应用程序密钥应保持私有-但在发布应用程序时
他们可以被一些人逆转
对于那些不会隐藏代码的人,请锁定ProGuard
代码。这是一个重构,一些付费的模糊处理程序正在插入一些位运算符以获取jk433g34hg3
一串如果你工作3天,你可以使黑客攻击延长5-15分钟:)
最好的办法就是保持现状,伊姆霍
即使您将密钥存储在服务器端(您的PC),密钥也可能被破解并打印出来。也许这需要最长的时间?无论如何,最好的情况是几分钟或几小时
普通用户不会对您的代码进行反编译。我认为只有第一种方法可以提供一些保证:
(我是ProGuard和DexGuard的开发者)这篇文章已经过时了,但仍然足够好。我想把它藏在一个.so库里,当然可以,使用NDK和C++。因此,文件可以在十六进制编辑器中查看,但祝你好运,反编译:P
保持这些私有的唯一真正方法是将它们保留在服务器上,让应用程序将任何内容发送到服务器,服务器与Dropbox交互。这样,您就不会以任何格式分发私钥。
一种可能的解决方案是在应用程序中对数据进行编码,并在运行时使用解码(当您想要使用该数据时)。我还建议使用progaurd,使您的应用程序的反编译源代码难以阅读和理解。例如,我在应用程序中放入一个编码密钥,然后在运行时在应用程序中使用解码方法解码我的密钥:// "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";
}
反编译
/**
* @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";
}
}
}
GoolgeAPIKey = "Your API/Secret Key"
buildTypes.each {
it.buildConfigField 'String', 'GoogleSecAPIKEY', GoolgeAPIKey
}
BuildConfig.GoogleSecAPIKEY
$ strings libsecretlib.so | grep My
My_S3cr3t_P@$$W0rD