IT박스

Android In App Billing : 애플리케이션 공개 키 보안

itboxs 2020. 12. 2. 08:16
반응형

Android In App Billing : 애플리케이션 공개 키 보안


Android In App Billing 버전 3 (TrivialDrive)에서 SDK와 함께 제공되는 샘플 애플리케이션

MainActivity.java

/* base64EncodedPublicKey should be YOUR APPLICATION'S PUBLIC KEY
 * (that you got from the Google Play developer console). This is not your
 * developer public key, it's the *app-specific* public key.
 *
 * Instead of just storing the entire literal string here embedded in the
 * program,  construct the key at runtime from pieces or
 * use bit manipulation (for example, XOR with some other string) to hide
 * the actual key.  The key itself is not secret information, but we don't
 * want to make it easy for an attacker to replace the public key with one
 * of their own and then fake messages from the server.
 */
String base64EncodedPublicKey = "CONSTRUCT_YOUR_KEY_AND_PLACE_IT_HERE";

이 보안 조치를 이해하고 있는지 잘 모르겠습니다. Google Play 개발자 콘솔에서 애플리케이션 공개 키 (이미 Base 64로 인코딩 됨)를 얻는 방법을 알고 있습니다.

내가 이해하지 못하는 것은이 부분

 /* Instead of just storing the entire literal string here embedded in the
 * program,  construct the key at runtime from pieces or
 * use bit manipulation (for example, XOR with some other string) to hide
 * the actual key
 */

내가 아는 한,이 공개 키는 애플리케이션 업로드 프로세스 중에 Google에서 제공하는 상수 문자열입니다.

비트 조작 프로세스를 사용하여 프로그래밍 방식으로 동일한 키를 어떻게 만들 수 있습니까? 누군가 전에 해본 적이 있습니까? 이를 수행하는 방법에 대한 샘플 코드가 있습니까?


이 같은:

String Base64EncodedPublicKey key = "Ak3jfkd" + GetMiddleBit() + "D349824";

또는

String Base64EncodedPublicKey key = 
         DecrementEachletter("Bl4kgle") + GetMiddleBit() + ReverseString("D349824");

또는 단일 문자열의 base64 일반 텍스트에 키를 넣지 않는 모든 것. 아마도 base64에 키를 저장하지 않는 것도 좋은 생각 일 것입니다. 원시 base64 텍스트 조각은 찾기가 매우 쉽기 때문입니다.

키를 보호하는 데 특히 좋은 방법은 아닙니다. 그러나 누군가가 APK에서 문자 그대로 문자열을 검색하여 base64로 인코딩 된 공개 키처럼 보이는 것을 찾는 사소한 공격으로부터 보호합니다. 적어도 당신은 # $ # $ ers가 약간 작동하도록합니다.

아마도 악한 사람들이 공개 키를 식별하면 나쁜 일을 할 수 있습니다. Google은 분명히 그렇게 생각하는 것 같습니다. 이 단계가 무엇을하는지 짐작할 수 있지만 공개 포럼에서 그것에 대해 추측하고 누구에게나 아이디어를주고 싶은지 잘 모르겠습니다. 그래도하고 싶어요.

기본 플롯 요약은 누군가가 응용 프로그램을 프로그래밍 방식으로 LVL을 해제하는 응용 프로그램을 작성하는 것을 더 어렵게 만드는 것입니다.

한 사람은이 일을하는 사람이 20 ~ 30,000 개의 안드로이드 앱을 크래킹하고 다시 퍼블리싱한다고 가정합니다. 실제로 약간의 수동 작업을해야한다면 프로그램에 의해 이미 고장난 20,000 개의 Android 앱 목록에 앱을 추가하는 데 10 분이 더 걸리지 않을 가능성이 있습니다. 최상위 계층 응용 프로그램이없는 경우. 그리고 전투는 잠재적으로 끝이 없으며 아마도 궁극적으로 쓸데없는 일입니다.

키를 연속적인 청크로 분할하는 것은 (다른 답변에서 제안한대로) 아마도 충분하지 않을 것입니다. 키는 APK의 문자열 상수 테이블에서 연속 문자열로 끝나기 때문입니다. 프로그램으로 찾기가 너무 쉽습니다.


대안은 키에 대한 몇 가지 기본 변환을 수행하는 것입니다.

// Replace this with your encoded key.
String base64EncodedPublicKey = "";

// Get byte sequence to play with.
byte[] bytes = base64EncodedPublicKey.getBytes();

// Swap upper and lower case letters.
for (int i = 0; i < bytes.length; i++) {
    if(bytes[i] >= 'A' && bytes[i] <= 'Z')
        bytes[i] = (byte)( 'a' + (bytes[i] - 'A'));
    else if(bytes[i] >= 'a' && bytes[i] <= 'z')
        bytes[i] = (byte)( 'A' + (bytes[i] - 'a'));
}

// Assign back to string.
base64EncodedPublicKey = new String( bytes );

따라서 원래 키를 as에 넣고 base64EncodedPublicKey위 코드를 실행하면 소문자와 대문자를 바꾸고 결과를 다시 base64EncodedPublicKey. 그런 다음 디버거의 결과를 복사하여 원래 base64EncodedPublicKey으로 코드에 붙여 넣을 수 있습니다. 이 시점에서 키가 변환되고 (대문자와 소문자가 전환됨) 런타임에 올바른 대 / 소문자로 다시 고정되고 계속 작동합니다.

The above is obviously quite a basic transcode, but you can be more creative, reverse the ordering of A-Z, swap odd and even numbers, swap vowels for even numbers. The issue here is that if I put code in the above snippet that does a bunch of more interesting transcodes, and then everyone copy and pastes that into their projects, a cracker will easily be able to see and use the transcode themselves (from looking at this post)! So you just have to come up with a few transforms yourself.

I've purposely made the above work in both direction (so if you run it twice, you'll get your original value back) as it makes it easy to run the algorithm on your original key. I think it is kind of neat it looks like the real key is sitting there as plain text, a casual cracker may try to switch this and then be confused when it doesn't work.


You can split it into pieces like this

String piece1 = "SDFGJKGB4UIH234WE/FRT23RSDF/3DFUISDFVWE";
String piece2 = "SDFGJKGB4UIHUISDFVWE";
String piece3 = "BDYASGBDNAWGRET24IYE23das4saGBENWKD";
String piece4 = "432423SDF23R/+SDDS";

mHelper = new IabHelper(this, piece1 + piece2 + piece3 + piece4);

Any kind of manipulations will do.

You can't hide the public key perfectly from the attacker, you just need to manipulate the string to confuse a attacker a little bit

You can add some strings and remove it when it's needed or split it into chunks.


What I did was to transform the key into a char array, split it in two and then reconstruct it when needed like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shop);

    char[] base64KeyByteArray = ArrayUtils.addAll(getPublicKeyChunk1(), getPublicKeyChunk2());

    Log.d(TAG, String.valueOf(base64KeyByteArray));
}

private char[] getPublicKeyChunk1() {
    return new char[]{82, 73, 67, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107,
            105, 71, 57, 119, 79, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73,
            73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 121, 55, 81, 76, 122, 67, 105, 80, 65,
            110, 105, 101, 72, 66, 53, 57};
}

private char[] getPublicKeyChunk2() {
    return new char[]{82, 43, 68, 47, 79, 121, 122, 110, 85, 67, 118, 89, 108, 120, 43, 49,
            80, 100, 67, 108, 55, 90, 57, 103, 119, 57, 87, 78, 79, 111, 53, 101, 80, 71,
            117, 74, 104, 82, 87, 97, 100};
}

Building on Steven Craft's Answer with help i got from gidds

Here's a cleaner code. In addition it swaps out digit (0-9) for ascii character (37-46) and vice versa. Written in Kotlin.

 val string = "Hello World 012345679 %&()"
 fun String.swapCase() = map {
        when {
            it.isUpperCase() -> it.toLowerCase()
            it.isLowerCase() -> it.toUpperCase()
            it.isDigit() -> (37 + (it.toInt() - 48)).toChar()
            it.isDefined() -> if (it.toInt() >= 37 && it.toInt() <= 46) (48 + (it.toInt() - 37)).toChar() else it
            else -> it
        }
    }.joinToString("")
    println(string.swapCase()) // hELLO wORLD %&'()*+,. 0134

Use this -> https://edge-developer.github.io/BillingGenerator/ to generate all those in a fly


Follow 3 simple steps to secure API/Secret key

We can use Gradle to secure the API key or Secret key. Check my answer.


Is someone is really need you private key? I think the whole idea is replace it. IMHO any manipulations are useless. The only thing to do by evil person is just initialize variable with correct (his own key) value one line begore google API call.

참고URL : https://stackoverflow.com/questions/14352758/android-in-app-billing-securing-application-public-key

반응형