1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-android-app-sec-guidebook

Клонировать/Скачать
4.3.1.3.md 20 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 27.11.2024 20:24 c13bfb7

sWhitelists.add("org.jssec.android.provider.partneruser", isdebug ?

// Сертификат хэш-значения "androiddebugkey" в debug.keystore.
"0EFB7236 328348A9 89718BAD DF57F544 D5CCB4AE B9DB34BC 1E29DD26 F77C8255" :

// Сертификат хэш-значение "партнёрского ключа" в хранилище ключей.
"1F039BB5 7861C27A 3916C778 8E78CE00 690B3974 3EB8259F E2627B8D 4C0EC35A");

// Зарегистрировать другие партнёрские приложения таким же образом.
}

private static boolean checkPartner(Context context, String pkgname) {
if (sWhitelists == null) buildWhitelists(context);
return sWhitelists.test(context, pkgname);
}

// Получить имя пакета вызывающего приложения.
private String getCallingPackage(Context context) {
String pkgname;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
pkgname = super.getCallingPackage();
} else {
pkgname = null;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List procList = am.getRunningAppProcesses();
int callingPid = Binder.getCallingPid();
if (procList != null) {
for (RunningAppProcessInfo proc : procList) {
if (proc.pid == callingPid) {
pkgname = proc.pkgList[proc.pkgList.length - 1];
break;
}
}
}
}
return pkgname;
}

@Override
public boolean onCreate() {
return true;
}

@Override
public String getType(Uri uri) {
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
case ADDRESSES_CODE:
return CONTENT_TYPE;
case DOWNLOADS_ID_CODE:
case ADDRESSES_ID_CODE:
return CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException("Invalid URI:" + uri);
}
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// *** POINT 2 *** Убедитесь, что сертификат запрашивающего приложения зарегистрирован в собственном белом списке.
if (!checkPartner(getContext(), getCallingPackage(getContext()))) {
throw new SecurityException("Вызывающее приложение не является партнёрским приложением.");
}
// *** POINT 3 *** Обработайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают от партнёрского приложения.
// Здесь, является ли uri ожидаемым или нет, проверяется с помощью UriMatcher#match() и switch case.
// Проверка других параметров здесь опущена из-за примера.
// См. «3.2 Обрабатывайте входные данные осторожно и безопасно».
// *** POINT 4 *** Информация, которая предоставляется для раскрытия партнёрским приложениям, может быть возвращена.
// Это зависит от приложения, можно ли раскрыть результат запроса или нет.
switch (sUriMatcher.match(uri)) {
case DOWNLOADS_CODE:
case DOWNLOADS_ID_CODE:
return sDownloadCursor;
case ADDRESSES_CODE:
case ADDRESSES_ID_CODE:
return sAddressCursor;
default:
throw new IllegalArgumentException("Неверный URI:" + uri);
}
}

@Override
public Uri insert(Uri uri, ContentValues values) {
// *** POINT 2 *** Убедитесь, что сертификат запрашивающего приложения зарегистрирован в собственном белом списке.
if (!checkPartner(getContext(), getCallingPackage(getContext()))) {
throw new SecurityException("Вызывающее приложение не является партнёрским приложением.");
}
// *** POINT 3 *** Обработайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают от партнёрского приложения.
// Здесь, является ли uri ожидаемым или нет, проверяется с помощью UriMatcher#match() и switch case

// Здесь опущены проверки для других параметров из-за примера.
// См. «3.2 Осторожно и безопасно обрабатывайте входные данные».
// *** Пункт 4*** Можно вернуть информацию, которую разрешено раскрывать партнёрским приложениям.
// Это зависит от приложения, имеет ли выданный ID чувствительное значение или нет.

switch (sUriMatcher.match(uri)) {
    case DOWNLOADS_CODE:
        return ContentUris.withAppendedId(Download.CONTENT_URI, 3);
    case ADDRESSES_CODE:
        return ContentUris.withAppendedId(Address.CONTENT_URI, 4);
    default:
        throw new IllegalArgumentException("Invalid URI:" + uri);
}

}

Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

// *** Пункт 2*** Проверьте, зарегистрирован ли сертификат запрашивающего приложения в собственном белом списке.
if (!checkPartner(getContext(), getCallingPackage(getContext()))) {
    throw new SecurityException("Calling application is not a partner application.");
}
// *** Пункт 3*** Обрабатывайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают от партнёрского приложения.
// Здесь проверяется, соответствует ли uri ожиданиям, с помощью UriMatcher#match() и switch case.
// Опущены проверки для других параметров из-за примера.
// См. «3.2 Осторожно и безопасно обрабатывайте входные данные».
// *** Пункт 4*** Можно вернуть информацию, которая разрешена к раскрытию партнёрским приложениям.
// Зависит от приложения, имеет ли количество обновлённых записей чувствительное значение или нет.

switch (sUriMatcher.match(uri)) {
    case DOWNLOADS_CODE:
        return 5; // Возвращаем количество обновлённых записей
    case DOWNLOADS_ID_CODE:
        return 1;
    case ADDRESSES_CODE:
        return 15;
    case ADDRESSES_ID_CODE:
        return 1;
    default:
        throw new IllegalArgumentException("Invalid URI:" + uri);
}

Override public int delete(Uri uri, String selection, String[] selectionArgs)

// *** Пункт 2*** Проверьте, зарегистрирован ли сертификат запрашивающего приложения в собственном белом списке.
if (!checkPartner(getContext(), getCallingPackage(getContext()))) {
    throw new SecurityException("Calling application is not a partner application.");
}
// *** Пункт 3*** Обрабатывайте полученные данные запроса осторожно и безопасно,
// даже если данные поступают от партнёрского приложения.
// Здесь проверяется, соответствует ли uri ожиданиям, с помощью UriMatcher#match() и switch case.
// Опущены проверки для других параметров из-за примера.
// См. «3.2 Осторожно и безопасно обрабатывайте входные данные».
// *** Пункт 4*** Можно раскрыть информацию, которая предоставлена партнёрским приложениям.
// Зависит от приложения, имеет ли количество удалённых записей чувствительное значение или нет.

switch (sUriMatcher.match(uri)) {
    case DOWNLOADS_CODE:
        return 10; // Возвращаем количество удалённых записей
    case DOWNLOADS_ID_CODE:
        return 1;
    case ADDRESSES_CODE:
        return 20;
    case ADDRESSES_ID_CODE:
        return 1;
    default:
        throw new IllegalArgumentException("Invalid URI:" + uri);
}

Пример использования контент-провайдера для партнёров

Ключевые моменты (использование контент-провайдера):

  1. Проверить, зарегистрирован ли сертификат целевого приложения в собственном белом списке.
  2. Можно отправлять информацию, открытую для партнёрских приложений.
  3. Даже если данные получены от партнёрского приложения, необходимо осторожно и безопасно обрабатывать полученные результаты. Класс PartnerUserActivity расширяет Activity

// Информация о целевом поставщике контента private static final String AUTHORITY = "org.jssec.android.provider.partnerprovider";

private interface Address { public static final String PATH = "addresses"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH); }

// *** ТОЧКА 4 *** Проверьте, зарегистрирован ли сертификат целевого приложения в собственном белом списке. private static PkgCertWhitelists sWhitelists = null;

private static void buildWhitelists(Context context) { boolean isdebug = Utils.isDebuggable(context); sWhitelists = new PkgCertWhitelists(); // Зарегистрируйте значение хеш-функции сертификата партнёрского приложения org.jssec.android.provider.partnerprovider. sWhitelists.add("org.jssec.android.provider.partnerprovider", isdebug ? // Значение хеш-функции сертификата "androiddebugkey" в debug.keystore. "0EFB7236 328348A9 89718BAD DF57F544 D5CCB4AE B9DB34BC 1E29DD26 F77C8255" : // Значение хеш-функции сертификата "партнёрский ключ" в keystore. "D397D343 A5CBC10F 4EDDEB7C A10062DE 5690984F 1FB9E88B D7B3A7C2 42E142CA"); // Аналогичным образом зарегистрируйте другие партнёрские приложения. }

private static boolean checkPartner(Context context, String pkgname) { if (sWhitelists == null) buildWhitelists(context); return sWhitelists.test(context, pkgname); }

// Получите имя пакета целевого поставщика контента. private String providerPkgname(Uri uri) { String pkgname = null; ProviderInfo pi = getPackageManager().resolveContentProvider(uri.getAuthority(), 0); if (pi != null) pkgname = pi.packageName; return pkgname; }

public void onQueryClick(View view) { logLine("[Query]"); // *** ТОЧКА 4 *** Убедитесь, что сертификат целевого приложения зарегистрирован в собственном белом списке. if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) { logLine(" Целевой поставщик контента не обслуживается партнёрскими приложениями."); return; } Cursor cursor = null; try { // *** ТОЧКА 5 *** Можно отправить информацию, которая разрешена к раскрытию партнёрским приложениям. cursor = getContentResolver().query(Address.CONTENT_URI, null, null, null, null); // *** ТОЧКА 6 *** Обработайте полученные данные результата осторожно и безопасно, // даже если данные поступают от партнёрского приложения. // Опущено, поскольку это пример. Пожалуйста, обратитесь к разделу «3.2 Обработка входных данных осторожно и безопасно». if (cursor == null) { logLine(" нулевой курсор"); } else { boolean moved = cursor.moveToFirst(); while (moved) { logLine(String.format(" %d, %s", cursor.getInt(0), cursor.getString(1))); moved = cursor.moveToNext(); } } } finally { if (cursor != null) cursor.close(); } }

public void onInsertClick(View view) { logLine("[Insert]"); // *** ТОЧКА 4 *** Убедитесь, что сертификат целевого приложения зарегистрирован в собственном белом списке. if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) { logLine(" Целевой поставщик контента не обслуживается партнёрскими приложениями."); return; } // *** ТОЧКА 5 *** Информацию, которую разрешено раскрывать партнёрским приложениям, можно отправить. ContentValues values = new ContentValues(); values.put("city", "Tokyo"); Uri uri = getContentResolver().insert(Address.CONTENT_URI, values); // *** ТОЧКА 6 *** Обработайте полученный результат данных. Перевод текста на русский язык:

carefully and securely, // даже если данные поступают от партнёрского приложения. // Опущено, см. «3.2 Тщательная и безопасная обработка входных данных». logLine(" uri:" + uri); }

public void onUpdateClick(View view) { logLine("[Update]"); // *** ТОЧКА 4 *** Убедитесь, что сертификат целевого приложения зарегистрирован в собственном белом списке. if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) { logLine(" Целевой поставщик контента не обслуживается партнёрскими приложениями."); return; } // *** ТОЧКА 5 *** Можно отправить информацию, которая разрешена к раскрытию партнёрским приложениям. ContentValues values = new ContentValues(); values.put("city", "Tokyo"); String where = "_id = ?"; String[] args = { "4" }; int count = getContentResolver().update(Address.CONTENT_URI, values, where, args); // *** ТОЧКА 6 *** Обработайте полученные данные тщательно и безопасно, // даже если они поступают от партнёрского приложения. // Опущено, см. «3.2 Тщательная и безопасная обработка входных данных». logLine(String.format(" %s записей обновлено", count)); }

public void onDeleteClick(View view) { logLine("[Delete]"); // *** ТОЧКА 4 *** Убедитесь, что сертификат целевого приложения зарегистрирован в собственном белом списке. if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) { logLine(" Целевой поставщик контента не обслуживается партнёрскими приложениями."); return; } // *** ТОЧКА 5 *** Можно отправить информацию, которая разрешена к раскрытию партнёрским приложениям. int count = getContentResolver().delete(Address.CONTENT_URI, null, null); // *** ТОЧКА 6 *** Обработайте полученные данные тщательно и безопасно, // даже если они поступают от партнёрского приложения. // Опущено, см. «3.2 Тщательная и безопасная обработка входных данных». logLine(String.format(" %s записей удалено", count)); }

private TextView mLogView;

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mLogView = (TextView)findViewById(R.org.jssec.android.shared.R.id.logview); }

private void logLine(String line) { mLogView.append(line); mLogView.append("¥n"); }


**PkgCertWhitelists.java**

package org.jssec.android.shared;

import java.util.HashMap;
import java.util.Map;
import android.content.Context;

public class PkgCertWhitelists {

    private Map<String, String> mWhitelists = new HashMap<String, String>();

    public boolean add(String pkgname, String sha256) {
        if (pkgname == null) return false;
        if (sha256 == null) return false;
        sha256 = sha256.replaceAll(" ", "");
        if (sha256.length() != 64) return false; // SHA-256 -> 32 bytes -> 64 chars
        sha256 = sha256.toUpperCase();
        if (sha256.replaceAll("[0-9A-F]+", "").length() != 0) return false; // found non hex char
        mWhitelists.put(pkgname, sha256);
        return true;
    }

    public boolean test(Context ctx, String pkgname) {
        // Получить правильное значение хеш-функции, соответствующее pkgname.
        String correctHash = mWhitelists.get(pkgname);
        // Сравнить фактическое значение хеш-функции pkgname с правильным значением хеш-функции.
        return PkgCert.test(ctx, pkgname, correctHash);
    }
}

**PkgCert.java**

package org.jssec.android.shared;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;

public class PkgCert {

    public static boolean test(Context ctx, String)

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-android-app-sec-guidebook.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-android-app-sec-guidebook.git
oschina-mirror
wizardforcel-android-app-sec-guidebook
wizardforcel-android-app-sec-guidebook
master