首页

关于android开发中如何正确使用Partner Content Providers安全用法及代码示例

标签:android,Partner Content Providers,安全     发布时间:2017-10-31   

一、注意事项

1、显式指定exported属性为true。@b@2、验证请求应用的的证书是否在白名单中。@b@3、处理收到的数据,确认真实性和有效性。@b@4、授权给第三方应用的信息可以返回。

二、原代码示例

1.AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>@b@<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.jssec.android.provider.partnerprovider">@b@    <application@b@        android:icon="@drawable/ic_launcher"@b@        android:label="@string/app_name" >@b@        <!-- *** POINT 1 *** Explicitly set the exported attribute to true. -->@b@        <provider@b@            android:name=".PartnerProvider"@b@            android:authorities="org.jssec.android.provider.partnerprovider"@b@            android:exported="true" />@b@    </application>@b@</manifest>

2.PartnerProvider.java

package org.jssec.android.provider.partnerprovider;@b@import java.util.List;@b@ @b@import org.jssec.android.shared.PkgCertWhitelists;@b@import org.jssec.android.shared.Utils;@b@ @b@import android.app.ActivityManager;@b@import android.app.ActivityManager.RunningAppProcessInfo;@b@import android.content.ContentProvider;@b@import android.content.ContentUris;@b@import android.content.ContentValues;@b@import android.content.Context;@b@import android.content.UriMatcher;@b@import android.database.Cursor;@b@import android.database.MatrixCursor;@b@import android.net.Uri;@b@import android.os.Binder;@b@ @b@    public class PartnerProvider extends ContentProvider {@b@        public static final String AUTHORITY = "org.jssec.android.provider.partnerprovider";@b@        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.org.jssec.contenttype";@b@        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.org.jssec.contenttype";@b@ @b@        // Expose the interface that the Content Provider provides.@b@        public interface Download {@b@            public static final String PATH = "downloads";@b@            public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH);@b@        }@b@ @b@        public interface Address {@b@            public static final String PATH = "addresses";@b@            public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH);@b@        }@b@ @b@    // UriMatcher@b@    private static final int DOWNLOADS_CODE = 1;@b@    private static final int DOWNLOADS_ID_CODE = 2;@b@    private static final int ADDRESSES_CODE = 3;@b@    private static final int ADDRESSES_ID_CODE = 4;@b@    private static UriMatcher sUriMatcher;@b@ @b@    static {@b@        sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);@b@        sUriMatcher.addURI(AUTHORITY, Download.PATH, DOWNLOADS_CODE);@b@        sUriMatcher.addURI(AUTHORITY, Download.PATH + "/#", DOWNLOADS_ID_CODE);@b@        sUriMatcher.addURI(AUTHORITY, Address.PATH, ADDRESSES_CODE);@b@        sUriMatcher.addURI(AUTHORITY, Address.PATH + "/#", ADDRESSES_ID_CODE);@b@    }@b@ @b@    // Since this is a sample program,@b@    // query method returns the following fixed result always without using database.@b@    private static MatrixCursor sAddressCursor = new MatrixCursor(new String[] { "_id", "city" });@b@    static {@b@        sAddressCursor.addRow(new String[] { "1", "New York" });@b@        sAddressCursor.addRow(new String[] { "2", "London" });@b@        sAddressCursor.addRow(new String[] { "3", "Paris" });@b@    }@b@    private static MatrixCursor sDownloadCursor = new MatrixCursor(new String[] { "_id", "path" });@b@    static {@b@        sDownloadCursor.addRow(new String[] { "1", "/sdcard/downloads/sample.jpg" });@b@        sDownloadCursor.addRow(new String[] { "2", "/sdcard/downloads/sample.txt" }); }@b@ @b@    // *** POINT 2 *** Verify if the certificate of a requesting application has been registered in the own white lis t.@b@    private static PkgCertWhitelists sWhitelists = null;@b@    private static void buildWhitelists(Context context) {@b@        boolean isdebug = Utils.isDebuggable(context);@b@        sWhitelists = new PkgCertWhitelists();@b@ @b@        // Register certificate hash value of partner application org.jssec.android.provider.partneruser.@b@        sWhitelists.add("org.jssec.android.provider.partneruser", isdebug ?@b@            // Certificate hash value of "androiddebugkey" in the debug.keystore.@b@            "0EFB7236 328348A9 89718BAD DF57F544 D5CCB4AE B9DB34BC 1E29DD26 F77C8255" :@b@            // Certificate hash value of "partner key" in the keystore.@b@            "1F039BB5 7861C27A 3916C778 8E78CE00 690B3974 3EB8259F E2627B8D 4C0EC35A");@b@ @b@        // Register following other partner applications in the same way.@b@ @b@    }@b@    private static boolean checkPartner(Context context, String pkgname) {@b@        if (sWhitelists == null) buildWhitelists(context);@b@        return sWhitelists.test(context, pkgname);@b@    }@b@    // Get the package name of the calling application.@b@    private String getCallingPackage(Context context) {@b@        String pkgname = null;@b@        ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);@b@        List<RunningAppProcessInfo> procList = am.getRunningAppProcesses();@b@        int callingPid = Binder.getCallingPid();@b@        if (procList != null) {@b@            for (RunningAppProcessInfo proc : procList) {@b@                if (proc.pid == callingPid) {@b@                    pkgname = proc.pkgList[proc.pkgList.length - 1];@b@                    break;@b@                }@b@            }@b@        }@b@        return pkgname;@b@    }@b@ @b@    @Override@b@    public boolean onCreate() {@b@        return true;@b@    }@b@ @b@    @Override@b@    public String getType(Uri uri) {@b@ @b@        switch (sUriMatcher.match(uri)) {@b@        case DOWNLOADS_CODE:@b@        case ADDRESSES_CODE:@b@            return CONTENT_TYPE;@b@ @b@        case DOWNLOADS_ID_CODE:@b@        case ADDRESSES_ID_CODE:@b@            return CONTENT_ITEM_TYPE;@b@ @b@        default:@b@            throw new IllegalArgumentException("Invalid URI:" + uri);@b@        }@b@    }@b@ @b@    @Override@b@    public Cursor query(Uri uri, String[] projection, String selection,@b@        String[] selectionArgs, String sortOrder) {@b@ @b@        // *** POINT 2 *** Verify if the certificate of a requesting application has been registered in the own white list.@b@        if (!checkPartner(getContext(), getCallingPackage(getContext()))) {@b@            throw new SecurityException("Calling application is not a partner application.");@b@        }@b@ @b@        // *** POINT 3 *** Handle the received request data carefully and securely,@b@        // even though the data comes from a partner application.@b@        // Here, whether uri is within expectations or not, is verified by UriMatcher#match() and switch case.@b@        // Checking for other parameters are omitted here, due to sample.@b@        // Refer to "3.2 Handle Input Data Carefully and Securely."@b@        // *** POINT 4 *** Information that is granted to disclose to partner applications can be returned.@b@        // It depends on application whether the query result can be disclosed or not.@b@        switch (sUriMatcher.match(uri)) {@b@        case DOWNLOADS_CODE:@b@        case DOWNLOADS_ID_CODE:@b@            return sDownloadCursor;@b@ @b@        case ADDRESSES_CODE:@b@        case ADDRESSES_ID_CODE:@b@            return sAddressCursor;@b@ @b@        default:@b@            throw new IllegalArgumentException("Invalid URI:" + uri);@b@        }@b@    }@b@ @b@    @Override@b@    public Uri insert(Uri uri, ContentValues values) {@b@ @b@        // *** POINT 2 *** Verify if the certificate of a requesting application has been registered in the own white list.@b@        if (!checkPartner(getContext(), getCallingPackage(getContext()))) {@b@            throw new SecurityException("Calling application is not a partner application.");@b@        }@b@ @b@        // *** POINT 3 *** Handle the received request data carefully and securely,@b@        // even though the data comes from a partner application.@b@        // Here, whether uri is within expectations or not, is verified by UriMatcher#match() and switch case. // Checking for other parameters are omitted here, due to sample.@b@        // Refer to "3.2 Handle Input Data Carefully and Securely."@b@        // *** POINT 4 *** Information that is granted to disclose to partner applications can be returned. // It depends on application whether the issued ID has sensitive meaning or not.@b@        switch (sUriMatcher.match(uri)) {@b@        case DOWNLOADS_CODE:@b@            return ContentUris.withAppendedId(Download.CONTENT_URI, 3);@b@ @b@        case ADDRESSES_CODE:@b@            return ContentUris.withAppendedId(Address.CONTENT_URI, 4);@b@ @b@        default:@b@            throw new IllegalArgumentException("Invalid URI:" + uri);@b@        }@b@    }@b@ @b@    @Override@b@    public int update(Uri uri, ContentValues values, String selection,@b@            String[] selectionArgs) {@b@ @b@        // *** POINT 2 *** Verify if the certificate of a requesting application has been registered in the own white list.@b@        if (!checkPartner(getContext(), getCallingPackage(getContext()))) {@b@            throw new SecurityException("Calling application is not a partner application.");@b@        }@b@ @b@        // *** POINT 3 *** Handle the received request data carefully and securely,@b@        // even though the data comes from a partner application.@b@        // Here, whether uri is within expectations or not, is verified by UriMatcher#match() and switch case.@b@        // Checking for other parameters are omitted here, due to sample.@b@        // Refer to "3.2 Handle Input Data Carefully and Securely."@b@ @b@        // *** POINT 4 *** Information that is granted to disclose to partner applications can be returned.@b@        // It depends on application whether the number of updated records has sensitive meaning or not.@b@        switch (sUriMatcher.match(uri)) {@b@        case DOWNLOADS_CODE:@b@            return 5; // Return number of updated records@b@ @b@        case DOWNLOADS_ID_CODE:@b@            return 1;@b@ @b@        case ADDRESSES_CODE:@b@            return 15;@b@ @b@        case ADDRESSES_ID_CODE:@b@            return 1;@b@ @b@        default:@b@            throw new IllegalArgumentException("Invalid URI:" + uri);@b@        }@b@    }@b@    @Override@b@    public int delete(Uri uri, String selection, String[] selectionArgs) {@b@ @b@        // *** POINT 2 *** Verify if the certificate of a requesting application has been registered in the own white list.@b@        if (!checkPartner(getContext(), getCallingPackage(getContext()))) {@b@            throw new SecurityException("Calling application is not a partner application.");@b@        }@b@ @b@        // *** POINT 3 *** Handle the received request data carefully and securely,@b@        // even though the data comes from a partner application.@b@        // Here, whether uri is within expectations or not, is verified by UriMatcher#match() and switch case.@b@        // Checking for other parameters are omitted here, due to sample.@b@        // Refer to "3.2 Handle Input Data Carefully and Securely."@b@ @b@        // *** POINT 4 *** Information that is granted to disclose to partner applications can be returned.         // It depends on application whether the number of deleted records has sensitive meaning or not.@b@        switch (sUriMatcher.match(uri)) {@b@        case DOWNLOADS_CODE:@b@            return 10; // Return number of deleted records@b@ @b@        case DOWNLOADS_ID_CODE:@b@            return 1;@b@ @b@        case ADDRESSES_CODE:@b@            return 20;@b@ @b@        case ADDRESSES_ID_CODE:@b@            return 1;@b@ @b@        default:@b@            throw new IllegalArgumentException("Invalid URI:" + uri);@b@        }@b@    }@b@}

3、安全使用PartnerActivity.java - 验证目标应用的的证书是不是在白名单里、已授权的信息可以发送给合作方应用、处理收到的数据,确认数据的正确性。

package org.jssec.android.provider.partneruser;@b@ @b@import org.jssec.android.shared.PkgCertWhitelists;@b@import org.jssec.android.shared.Utils;@b@ @b@import android.app.Activity;@b@import android.content.ContentValues;@b@import android.content.Context;@b@import android.content.pm.ProviderInfo;@b@import android.database.Cursor;@b@import android.net.Uri;@b@import android.os.Bundle;@b@import android.view.View;@b@import android.widget.TextView;@b@ @b@public class PartnerUserActivity extends Activity {@b@ @b@        // Target Content Provider Information@b@        private static final String AUTHORITY = "org.jssec.android.provider.partnerprovider";@b@        private interface Address {@b@            public static final String PATH = "addresses";@b@            public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH);@b@        }@b@ @b@    // *** POINT 4 *** Verify if the certificate of the target application has been registered in the own white list.@b@    private static PkgCertWhitelists sWhitelists = null;@b@    private static void buildWhitelists(Context context) {@b@        boolean isdebug = Utils.isDebuggable(context);@b@        sWhitelists = new PkgCertWhitelists();@b@ @b@        // Register certificate hash value of partner application org.jssec.android.provider.partnerprovider.@b@        sWhitelists.add("org.jssec.android.provider.partnerprovider", isdebug ?@b@            // Certificate hash value of "androiddebugkey" in the debug.keystore.@b@            "0EFB7236 328348A9 89718BAD DF57F544 D5CCB4AE B9DB34BC 1E29DD26 F77C8255" :@b@            // Certificate hash value of "partner key" in the keystore.@b@            "D397D343 A5CBC10F 4EDDEB7C A10062DE 5690984F 1FB9E88B D7B3A7C2 42E142CA");@b@ @b@            // Register following other partner applications in the same way.@b@    }@b@    private static boolean checkPartner(Context context, String pkgname) {@b@        if (sWhitelists == null) buildWhitelists(context);@b@        return sWhitelists.test(context, pkgname);@b@    }@b@ @b@    // Get package name of target content provider.@b@    private String providerPkgname(Uri uri) {@b@        String pkgname = null;@b@        ProviderInfo pi = getPackageManager().resolveContentProvider(uri.getAuthority(), 0);@b@        if (pi != null) pkgname = pi.packageName;@b@        return pkgname;@b@    }@b@ @b@    public void onQueryClick(View view) {@b@ @b@        logLine("[Query]");@b@ @b@        // *** POINT 4 *** Verify if the certificate of the target application has been registered in the own white li@b@        if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) {@b@            logLine(" The target content provider is not served by partner applications.");@b@            return;@b@        }@b@ @b@        Cursor cursor = null;@b@        try {@b@            // *** POINT 5 *** Information that is granted to disclose to partner applications can be sent.@b@            cursor = getContentResolver().query(Address.CONTENT_URI, null, null, null, null);@b@ @b@            // *** POINT 6 *** Handle the received result data carefully and securely,@b@            // even though the data comes from a partner application.@b@         // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely"@b@            if (cursor == null) {@b@                logLine(" null cursor");@b@            } else {@b@                boolean moved = cursor.moveToFirst();@b@                while (moved) {@b@                    logLine(String.format(" %d, %s", cursor.getInt(0), cursor.getString(1)));@b@                    moved = cursor.moveToNext();@b@                }@b@            }@b@        }@b@ @b@        finally {@b@            if (cursor != null) cursor.close();@b@        }@b@    }@b@ @b@    public void onInsertClick(View view) {@b@ @b@        logLine("[Insert]");@b@        // *** POINT 4 *** Verify if the certificate of the target application has been registered in the own white list.@b@        if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) {@b@            logLine(" The target content provider is not served by partner applications.");@b@            return;@b@        }@b@        // *** POINT 5 *** Information that is granted to disclose to partner applications can be sent.@b@        ContentValues values = new ContentValues();@b@        values.put("city", "Tokyo");@b@        Uri uri = getContentResolver().insert(Address.CONTENT_URI, values);@b@ @b@        // *** POINT 6 *** Handle the received result data carefully and securely,@b@        // even though the data comes from a partner application.@b@        // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."@b@        logLine(" uri:" + uri);@b@    }@b@    public void onUpdateClick(View view) {@b@ @b@        logLine("[Update]");@b@ @b@        // *** POINT 4 *** Verify if the certificate of the target application has been registered in the own@b@        if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) {@b@            logLine(" The target content provider is not served by partner applications.");@b@            return;@b@        }@b@ @b@        // *** POINT 5 *** Information that is granted to disclose to partner applications can be sent.@b@        ContentValues values = new ContentValues();@b@        values.put("city", "Tokyo");@b@        String where = "_id = ?";@b@        String[] args = { "4" };@b@        int count = getContentResolver().update(Address.CONTENT_URI, values, where, args);@b@ @b@        // *** POINT 6 *** Handle the received result data carefully and securely,@b@        // even though the data comes from a partner application.@b@        // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."@b@        logLine(String.format(" %s records updated", count));@b@    }@b@ @b@    public void onDeleteClick(View view) {@b@ @b@        logLine("[Delete]");@b@        // *** POINT 4 *** Verify if the certificate of the target application has been registered in the own white list.@b@ @b@        if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) {@b@            logLine(" The target content provider is not served by partner applications.");@b@            return;@b@        }@b@ @b@        // *** POINT 5 *** Information that is granted to disclose to partner applications can be sent.@b@        int count = getContentResolver().delete(Address.CONTENT_URI, null, null);@b@ @b@        // *** POINT 6 *** Handle the received result data carefully and securely,@b@        // even though the data comes from a partner application.@b@        // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."@b@        logLine(String.format(" %s records deleted", count));@b@    }@b@ @b@    private TextView mLogView;@b@ @b@    @Override@b@    public void onCreate(Bundle savedInstanceState) {@b@        super.onCreate(savedInstanceState);@b@        setContentView(R.layout.main);@b@        mLogView = (TextView)findViewById(R.id.logview);@b@    }@b@ @b@    private void logLine(String line) {@b@        mLogView.append(line);@b@        mLogView.append("¥n");@b@    }@b@}

4、PkgCertWhitelists.java

package org.jssec.android.shared;@b@ @b@import java.util.HashMap;@b@import java.util.Map;@b@ @b@import android.content.Context;@b@ @b@public class PkgCertWhitelists {@b@    private Map<String, String> mWhitelists = new HashMap<String, String>();@b@ @b@    public boolean add(String pkgname, String sha256) {@b@        if (pkgname == null) return false;@b@        if (sha256 == null) return false;@b@ @b@        sha256 = sha256.replaceAll(" ", "");@b@        if (sha256.length() != 64) return false; // SHA-256 -> 32 bytes -> 64 chars@b@        sha256 = sha256.toUpperCase();@b@        if (sha256.replaceAll("[0-9A-F]+", "").length() != 0) return false; // found non hex char@b@ @b@        mWhitelists.put(pkgname, sha256);@b@        return true;@b@    }@b@ @b@    public boolean test(Context ctx, String pkgname) {@b@        // Get the correct hash value which corresponds to pkgname.@b@        String correctHash = mWhitelists.get(pkgname);@b@ @b@        // Compare the actual hash value of pkgname with the correct hash value.@b@        return PkgCert.test(ctx, pkgname, correctHash);@b@    }@b@}

5、PkgCert.java

package org.jssec.android.shared;@b@ @b@import java.security.MessageDigest;@b@import java.security.NoSuchAlgorithmException;@b@ @b@import android.content.Context;@b@import android.content.pm.PackageInfo;@b@import android.content.pm.PackageManager;@b@import android.content.pm.PackageManager.NameNotFoundException;@b@import android.content.pm.Signature;@b@ @b@public class PkgCert {@b@ @b@    public static boolean test(Context ctx, String pkgname, String correctHash) {@b@        if (correctHash == null) return false;@b@        correctHash = correctHash.replaceAll(" ", "");@b@        return correctHash.equals(hash(ctx, pkgname));@b@    }@b@ @b@    public static String hash(Context ctx, String pkgname) {@b@        if (pkgname == null) return null;@b@        try {@b@            PackageManager pm = ctx.getPackageManager();@b@            PackageInfo pkginfo = pm.getPackageInfo(pkgname, PackageManager.GET_SIGNATURES);@b@            if (pkginfo.signatures.length != 1) return null; // Will not handle multiple signatures.@b@            Signature sig = pkginfo.signatures[0];@b@            byte[] cert = sig.toByteArray();@b@            byte[] sha256 = computeSha256(cert);@b@            return byte2hex(sha256);@b@        } catch (NameNotFoundException e) {@b@            return null;@b@        }@b@    }@b@ @b@    private static byte[] computeSha256(byte[] data) {@b@        try {@b@            return MessageDigest.getInstance("SHA-256").digest(data);@b@        } catch (NoSuchAlgorithmException e) {@b@            return null;@b@        }@b@    }@b@ @b@    private static String byte2hex(byte[] data) {@b@        if (data == null) return null;@b@        final StringBuilder hexadecimal = new StringBuilder();@b@        for (final byte b : data) {@b@            hexadecimal.append(String.format("%02X", b));@b@        }@b@        return hexadecimal.toString();@b@    }@b@}

三、安全代码示例

验证目标应用的的证书是不是在白名单里,已授权的信息可以发送给合作方应用,处理收到的数据,确认数据的正确性。

PartnerActivity.java@b@ @b@package org.jssec.android.provider.partneruser;@b@ @b@import org.jssec.android.shared.PkgCertWhitelists;@b@import org.jssec.android.shared.Utils;@b@ @b@import android.app.Activity;@b@import android.content.ContentValues;@b@import android.content.Context;@b@import android.content.pm.ProviderInfo;@b@import android.database.Cursor;@b@import android.net.Uri;@b@import android.os.Bundle;@b@import android.view.View;@b@import android.widget.TextView;@b@ @b@public class PartnerUserActivity extends Activity {@b@ @b@        // Target Content Provider Information@b@        private static final String AUTHORITY = "org.jssec.android.provider.partnerprovider";@b@        private interface Address {@b@            public static final String PATH = "addresses";@b@            public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH);@b@        }@b@ @b@    // *** POINT 4 *** Verify if the certificate of the target application has been registered in the own white list.@b@    private static PkgCertWhitelists sWhitelists = null;@b@    private static void buildWhitelists(Context context) {@b@        boolean isdebug = Utils.isDebuggable(context);@b@        sWhitelists = new PkgCertWhitelists();@b@ @b@        // Register certificate hash value of partner application org.jssec.android.provider.partnerprovider.@b@        sWhitelists.add("org.jssec.android.provider.partnerprovider", isdebug ?@b@            // Certificate hash value of "androiddebugkey" in the debug.keystore.@b@            "0EFB7236 328348A9 89718BAD DF57F544 D5CCB4AE B9DB34BC 1E29DD26 F77C8255" :@b@            // Certificate hash value of "partner key" in the keystore.@b@            "D397D343 A5CBC10F 4EDDEB7C A10062DE 5690984F 1FB9E88B D7B3A7C2 42E142CA");@b@ @b@            // Register following other partner applications in the same way.@b@    }@b@    private static boolean checkPartner(Context context, String pkgname) {@b@        if (sWhitelists == null) buildWhitelists(context);@b@        return sWhitelists.test(context, pkgname);@b@    }@b@ @b@    // Get package name of target content provider.@b@    private String providerPkgname(Uri uri) {@b@        String pkgname = null;@b@        ProviderInfo pi = getPackageManager().resolveContentProvider(uri.getAuthority(), 0);@b@        if (pi != null) pkgname = pi.packageName;@b@        return pkgname;@b@    }@b@ @b@    public void onQueryClick(View view) {@b@ @b@        logLine("[Query]");@b@ @b@        // *** POINT 4 *** Verify if the certificate of the target application has been registered in the own white li@b@        if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) {@b@            logLine(" The target content provider is not served by partner applications.");@b@            return;@b@        }@b@ @b@        Cursor cursor = null;@b@        try {@b@            // *** POINT 5 *** Information that is granted to disclose to partner applications can be sent.@b@            cursor = getContentResolver().query(Address.CONTENT_URI, null, null, null, null);@b@ @b@            // *** POINT 6 *** Handle the received result data carefully and securely,@b@            // even though the data comes from a partner application.@b@         // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely"@b@            if (cursor == null) {@b@                logLine(" null cursor");@b@            } else {@b@                boolean moved = cursor.moveToFirst();@b@                while (moved) {@b@                    logLine(String.format(" %d, %s", cursor.getInt(0), cursor.getString(1)));@b@                    moved = cursor.moveToNext();@b@                }@b@            }@b@        }@b@ @b@        finally {@b@            if (cursor != null) cursor.close();@b@        }@b@    }@b@ @b@    public void onInsertClick(View view) {@b@ @b@        logLine("[Insert]");@b@        // *** POINT 4 *** Verify if the certificate of the target application has been registered in the own white list.@b@        if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) {@b@            logLine(" The target content provider is not served by partner applications.");@b@            return;@b@        }@b@        // *** POINT 5 *** Information that is granted to disclose to partner applications can be sent.@b@        ContentValues values = new ContentValues();@b@        values.put("city", "Tokyo");@b@        Uri uri = getContentResolver().insert(Address.CONTENT_URI, values);@b@ @b@        // *** POINT 6 *** Handle the received result data carefully and securely,@b@        // even though the data comes from a partner application.@b@        // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."@b@        logLine(" uri:" + uri);@b@    }@b@    public void onUpdateClick(View view) {@b@ @b@        logLine("[Update]");@b@ @b@        // *** POINT 4 *** Verify if the certificate of the target application has been registered in the own@b@        if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) {@b@            logLine(" The target content provider is not served by partner applications.");@b@            return;@b@        }@b@ @b@        // *** POINT 5 *** Information that is granted to disclose to partner applications can be sent.@b@        ContentValues values = new ContentValues();@b@        values.put("city", "Tokyo");@b@        String where = "_id = ?";@b@        String[] args = { "4" };@b@        int count = getContentResolver().update(Address.CONTENT_URI, values, where, args);@b@ @b@        // *** POINT 6 *** Handle the received result data carefully and securely,@b@        // even though the data comes from a partner application.@b@        // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."@b@        logLine(String.format(" %s records updated", count));@b@    }@b@ @b@    public void onDeleteClick(View view) {@b@ @b@        logLine("[Delete]");@b@        // *** POINT 4 *** Verify if the certificate of the target application has been registered in the own white list.@b@ @b@        if (!checkPartner(this, providerPkgname(Address.CONTENT_URI))) {@b@            logLine(" The target content provider is not served by partner applications.");@b@            return;@b@        }@b@ @b@        // *** POINT 5 *** Information that is granted to disclose to partner applications can be sent.@b@        int count = getContentResolver().delete(Address.CONTENT_URI, null, null);@b@ @b@        // *** POINT 6 *** Handle the received result data carefully and securely,@b@        // even though the data comes from a partner application.@b@        // Omitted, since this is a sample. Please refer to "3.2 Handling Input Data Carefully and Securely."@b@        logLine(String.format(" %s records deleted", count));@b@    }@b@ @b@    private TextView mLogView;@b@ @b@    @Override@b@    public void onCreate(Bundle savedInstanceState) {@b@        super.onCreate(savedInstanceState);@b@        setContentView(R.layout.main);@b@        mLogView = (TextView)findViewById(R.id.logview);@b@    }@b@ @b@    private void logLine(String line) {@b@        mLogView.append(line);@b@        mLogView.append("¥n");@b@    }@b@}
PkgCertWhitelists.java@b@ @b@package org.jssec.android.shared;@b@ @b@import java.util.HashMap;@b@import java.util.Map;@b@ @b@import android.content.Context;@b@ @b@public class PkgCertWhitelists {@b@    private Map<String, String> mWhitelists = new HashMap<String, String>();@b@ @b@    public boolean add(String pkgname, String sha256) {@b@        if (pkgname == null) return false;@b@        if (sha256 == null) return false;@b@ @b@        sha256 = sha256.replaceAll(" ", "");@b@        if (sha256.length() != 64) return false; // SHA-256 -> 32 bytes -> 64 chars@b@        sha256 = sha256.toUpperCase();@b@        if (sha256.replaceAll("[0-9A-F]+", "").length() != 0) return false; // found non hex char@b@ @b@        mWhitelists.put(pkgname, sha256);@b@        return true;@b@    }@b@ @b@    public boolean test(Context ctx, String pkgname) {@b@        // Get the correct hash value which corresponds to pkgname.@b@        String correctHash = mWhitelists.get(pkgname);@b@ @b@        // Compare the actual hash value of pkgname with the correct hash value.@b@        return PkgCert.test(ctx, pkgname, correctHash);@b@    }@b@}
PkgCert.java@b@ @b@package org.jssec.android.shared;@b@ @b@import java.security.MessageDigest;@b@import java.security.NoSuchAlgorithmException;@b@ @b@import android.content.Context;@b@import android.content.pm.PackageInfo;@b@import android.content.pm.PackageManager;@b@import android.content.pm.PackageManager.NameNotFoundException;@b@import android.content.pm.Signature;@b@ @b@public class PkgCert {@b@ @b@    public static boolean test(Context ctx, String pkgname, String correctHash) {@b@        if (correctHash == null) return false;@b@        correctHash = correctHash.replaceAll(" ", "");@b@        return correctHash.equals(hash(ctx, pkgname));@b@    }@b@ @b@    public static String hash(Context ctx, String pkgname) {@b@        if (pkgname == null) return null;@b@        try {@b@            PackageManager pm = ctx.getPackageManager();@b@            PackageInfo pkginfo = pm.getPackageInfo(pkgname, PackageManager.GET_SIGNATURES);@b@            if (pkginfo.signatures.length != 1) return null; // Will not handle multiple signatures.@b@            Signature sig = pkginfo.signatures[0];@b@            byte[] cert = sig.toByteArray();@b@            byte[] sha256 = computeSha256(cert);@b@            return byte2hex(sha256);@b@        } catch (NameNotFoundException e) {@b@            return null;@b@        }@b@    }@b@ @b@    private static byte[] computeSha256(byte[] data) {@b@        try {@b@            return MessageDigest.getInstance("SHA-256").digest(data);@b@        } catch (NoSuchAlgorithmException e) {@b@            return null;@b@        }@b@    }@b@ @b@    private static String byte2hex(byte[] data) {@b@        if (data == null) return null;@b@        final StringBuilder hexadecimal = new StringBuilder();@b@        for (final byte b : data) {@b@            hexadecimal.append(String.format("%02X", b));@b@        }@b@        return hexadecimal.toString();@b@    }@b@}
<<热门下载>>