混淆字符串

Ben*_*olf 5 java obfuscation credentials

我们在App中使用了一些Networkcredentials.我只是反编译应用程序,并能够看到名称和密码等凭据.我真的没有办法防止这种情况发生.我认为"混淆器"这个词是我必须走的方向.我们测试proguard但它没有字符串加密或我错了吗?

有一种简单而自由的方式来做到这一点吗?

谢谢.

Pet*_*ček 5

Sorry, but this simply does't work no matter what you'll try. If you obfuscate/encrypt the credentials, the program still must be able to decrypt them at run-time. Therefore, the encryption keys must also be in the generated bytecode somewhere and therefore it's possible to take them, and decrypt the credentials manually outside the program (or just step through the program and read the credentials once they're decrypted).

What you're trying to do is Security by Obscurity and it doesn't work.

Whatever you do, if the program can obtain the credentials at run-time without any external help, a skilled attacker can do the same given enough time.

What you should do:

  1. Store the credentials in plain-text in a property file. Don't bother with encryption, it's pointless. You must make sure the db user you're using is read-only or add-only or something similar so you prevent any damage.
  2. Let the user input the password. If it's not stored in the bytecode, it's safe. He could e.g. input his password and have an account in the db...
  3. Use a safe and known authentication mechanism. Plaintext login+password is not that.
  4. 不要让你的应用程序靠近数据库.使用API​​在某处设置服务,该API将保持读取DB连接.您的应用程序可以连接到该应用程序并通过此API获取数据.这样,攻击者无法直接访问您的数据库.但是,他可以在新服务中调用任何内容,因此您必须确保其中没有可访问的敏感数据.


Giu*_*ini 3

您应该考虑对用户名和密码进行加密: How to encrypt String in Java

// bytes to encrypt
byte[] input;

// the key and the initialization vector
byte[] keyBytes;
byte[] ivBytes;

// initialize the Cipher
SecretKeySpec key = new SecretKeySpec(keyBytes, "DES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

// encryption
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encrypted= new byte[cipher.getOutputSize(input.length)];
int enc_len = cipher.update(input, 0, input.length, encrypted, 0);
enc_len += cipher.doFinal(encrypted, enc_len);

// decryption
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = new byte[cipher.getOutputSize(enc_len)];
int dec_len = cipher.update(encrypted, 0, enc_len, decrypted, 0);
dec_len += cipher.doFinal(decrypted, dec_len);
Run Code Online (Sandbox Code Playgroud)

通常,key(字节数组)应存储在只能在服务器运行的特定实例上访问的文件中,而不能编码到应用程序源文件中。

否则,您可以使用哈希(例如:md5sha1)并存储指纹而不是纯字符串:

// SHA1("hello world") -> "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
Run Code Online (Sandbox Code Playgroud)

这是一个简单的方法,可以让您计算SHA1 hash字符串的:

public static String SHA1(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException { 
    MessageDigest md = MessageDigest.getInstance("SHA-1");
    md.update(text.getBytes("iso-8859-1"));
    byte[] hash = md.digest();

    Formatter formatter = new Formatter();
    for (byte b : hash)
        formatter.format("%02x", b);
    return formatter.toString();
}
Run Code Online (Sandbox Code Playgroud)

导入java.io.UnsupportedEncodingExceptionjava.security.MessageDigestjava.security.NoSuchAlgorithmException是必需的。

  • 这是验证输入密码的正确方法 - 但据我了解OP的应用程序必须向其他服务器进行身份验证的问题 - 因此需要发送密码。散列不会对你有帮助。 (2认同)