java - purchase - Cómo proteger la clave pública de Google Play al realizar la facturación de InApp
in-app purchase android studio (5)
En realidad, esto es un poco tonto acerca de la protección de la clave pública (¿cuál es la definición de clave pública entonces?) Pero según la documentación de Google :
Para mantener su clave pública a salvo de usuarios malintencionados y piratas informáticos, no la incruste en ningún código como una cadena literal. En su lugar, construya la cadena en tiempo de ejecución a partir de piezas o use la manipulación de bits (por ejemplo, XOR con alguna otra cadena) para ocultar la clave real. La clave en sí no es información secreta, pero no desea facilitar que un pirata informático o un usuario malintencionado reemplace la clave pública con otra clave.
¿Hay alguna forma recomendada de hacerlo?
Sé que hay muchas maneras de hacerlo, simplemente no quiero seguir la misma manera en que las personas manejan el hash de contraseñas en el pasado (por ejemplo, md5, sha1, etc.), quiero saber las mejores prácticas en el caso de uso anterior.
Almacene su clave pública en el lado del servidor y, una vez que obtenga respuesta de google play, verifique que la clave envíe esa respuesta al servidor y realice su operación allí en el servidor.
Como alternativa a ofuscar la clave manualmente, también puede dejar que un ofuscador lo haga automáticamente. ProGuard es parte del SDK de Android, pero sobre todo confunde los nombres de clase / campo / método, no cadenas. Su hermano especializado para Android, DexGuard , puede agregar más capas de ofuscación, aplicando el cifrado de cadenas, el cifrado de clase y la reflexión. No es gratis, pero ahorra tiempo y probablemente sea más efectivo que hacerlo manualmente.
(Soy el desarrollador de ProGuard y DexGuard)
Hacer al menos texto simple transformar. La idea es que el simple desmontaje de dex no revelará su clave pública.
Este es un ejemplo de la función que realiza la codificación / decodificación de cadenas simples:
/**
* 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);
}
Luego, su clave privada se almacena en la fuente como cadena codificada (codifíquela con esta función), y se decodifica en tiempo de ejecución con la misma función. Este es el tipo de método "XOR" sugerido por Google.
Usted mismo crea el parámetro ''i'', cualquier cosa aleatoria como 0x27 u otra funcionará. Si oculta más cadenas de esta manera, use una ''i'' diferente para cada transformación.
La clave pública está codificada en base64 ( [a-zA-Z0-9+/]
), por lo que puede evitar fácilmente la necesidad de escapar de la cadena confusa, ya que es un problema molesto en la solución de @ PointerNull.
En su lugar, puede realizar la ofuscación convirtiendo primero el carácter en cuestión en un int de 6 bits. Luego realice la manipulación de bits (por ejemplo, XOR-ing) y luego vuelva a convertir a un char codificado en base64. Garantizado que ningún personaje escapado es necesario.
Esto surge mucho por aquí :) La idea detrás del párrafo que está citando es que para que la facturación en la aplicación sea segura, debe verificar las firmas de las transacciones. Esos están firmados con una clave privada, asociada con su cuenta de desarrollador. La clave reside en los servidores de Google, por lo que es bastante seguro asumir que nadie más puede firmar datos con ella. Para verificarlo, necesita su clave pública, que puede copiar desde la consola del desarrollador. Si alguien lo reemplazó en su aplicación, podría engañarlo para que acepte transacciones de facturación dentro de la aplicación de fuentes no autorizadas, ya que si colocan la clave pública, probablemente también controlen la clave privada correspondiente. Sin embargo, en la práctica, es mucho más fácil simplemente modificar su código en los lugares correctos para devolver siempre el verdadero para isLicensed()
, hasItem()
o métodos similares que pueda tener y nadie lo hace.
La mejor manera de proteger la clave es, por supuesto, no tener la clave en su aplicación en absoluto. Mueva toda la lógica de validación de transacciones a su servidor y use HTTPS para conectarse a él. Valide correctamente la cadena de certificados para asegurarse de que está hablando con su (s) servidor (es). De lo contrario, alguien podría jugar con DNS y engañar a su aplicación para que se conecte a sus propios servidores. Un ataque similar contra la compra de iOS se anunció hace un par de semanas.
Lo siguiente mejor es ofuscar de alguna manera la clave, e incluirla en su aplicación. Esto tiene la ventaja de que no necesita un servidor, pero la desventaja es que si alguien tiene la determinación suficiente, lo resolverá, ya que siempre puede revertir el código de bytes de su aplicación. Entonces, lo mejor es encontrar una manera original de hacerlo que no se muestre en foros públicos :) Para hacerlo un poco más difícil, puede implementar la parte de validación en el código nativo, que es más difícil (pero no imposible) analizar. Aún así, como se mencionó anteriormente, parchar el código de bytes en los lugares correctos es mucho más fácil que tratar de reemplazar la clave pública, así que eso es lo que hará la mayoría de los crackers.