Android API之KeyStore

皇甫鸿远
2023-12-01

相关资料学习:http://blog.csdn.net/innost/article/details/44081147

public class KeyStoreUsage extends Activity implements OnClickListener {
    private static final String TAG = "LDM_KEYSTORE";

    // KeyStore类用于密钥和证书的存储设施
    KeyStore mKeyStore;
    // 适配器
    AliasAdapter mAdapter;
    // 生成密钥对的tton
    Button mGenerateButton;
    // 生成签名的button
    Button mSignButton;
    // 核实签名的Button
    Button mVerifyButton;
    // 删除签名的on
    Button mDeleteButton;
    // 签名明文显示
    EditText mPlainText;
    // 保存签名文本字段
    EditText mCipherText;
    // 选中的签名
    private String mSelectedAlias;
    private ListView listview;
    private EditText aliasInput;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.keystore_usage);
        initViews();
        initEvents();
        mAdapter = new AliasAdapter(getApplicationContext());
        listview.setAdapter(mAdapter);
        // 更新密钥数据
        updateKeyList();
    }

    /**
     * 初始化控件
     * 
     * @description:
     * @author ldm
     * @date 2016-7-20 下午2:45:06
     */
    private void initViews() {
        mVerifyButton = (Button) findViewById(R.id.verify_button);
        aliasInput = (EditText) findViewById(R.id.entry_name);
        mGenerateButton = (Button) findViewById(R.id.generate_button);
        listview = (ListView) findViewById(R.id.entries_list);
        mSignButton = (Button) findViewById(R.id.sign_button);
        mCipherText = (EditText) findViewById(R.id.ciphertext);
        mPlainText = (EditText) findViewById(R.id.plaintext);
        mDeleteButton = (Button) findViewById(R.id.delete_button);
    }

    /**
     * 
     * @descripton:初始化控件监听事件
     * @author ldm
     * @date 2016-7-20 下午2:45:37
     */
    private void initEvents() {
        mVerifyButton.setOnClickListener(this);
        mGenerateButton.setOnClickListener(this);
        mSignButton.setOnClickListener(this);
        mDeleteButton.setOnClickListener(this);
        listview.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                mSelectedAlias = mAdapter.getItem(position);
                // 选中已经存在的数据,则可以进行相应操作
                setKeyActionButtonsEnabled(true);
            }
        });
    }

    /**
     * 已经生成密钥的数据适配器
     * 
     * @description:
     * @author ldm
     * @date 2016-7-20 下午3:26:23
     */
    private class AliasAdapter extends ArrayAdapter<String> {
        public AliasAdapter(Context context) {
            // 使用适当的布局来显示生成的密钥
            super(context, android.R.layout.simple_list_item_single_choice);
        }

        // 更新数据
        public void setAliases(List<String> items) {
            // 先清除数据
            clear();
            // 再添加数据
            addAll(items);
            // 刷新数据
            notifyDataSetChanged();
        }
    }

    private void updateKeyList() {
        setKeyActionButtonsEnabled(false);
        new UpdateKeyListTask().execute();
    }

    // 对已经存在的签名是否可以操作
    private void setKeyActionButtonsEnabled(boolean enabled) {
        mSignButton.setEnabled(enabled);
        mVerifyButton.setEnabled(enabled);
        mDeleteButton.setEnabled(enabled);

    }

    /**
     * 更新数据,把密钥对应的别名展示在列表中
     * 
     * @description:
     * @author ldm
     * @date 2016-7-20 下午4:13:48
     */
    private class UpdateKeyListTask extends
            AsyncTask<Void, Void, Enumeration<String>> {
        @Override
        protected Enumeration<String> doInBackground(Void... params) {
            try {
                // 创建KeyStore实例
                KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
                // 创建空 keystore,或者不能从流中初始化 keystore,则传递 null 作为 stream 的参数
                ks.load(null);
                // 列出此 keystore 的所有别名
                Enumeration<String> aliases = ks.aliases();
                return aliases;
            } catch (Exception e) {
                Log.w(TAG, "Could not list keys", e);
                return null;
            }
        }

        @Override
        protected void onPostExecute(Enumeration<String> result) {
            List<String> aliases = new ArrayList<String>();
            while (result.hasMoreElements()) {
                aliases.add(result.nextElement());
            }
            // 把数据放入适配器中
            mAdapter.setAliases(aliases);
        }
    }

    /**
     * 生成密钥的异步任务
     * 
     * @description:
     * @author ldm
     * @date 2016-7-20 下午3:32:15
     */
    @SuppressLint({ "TrulyRandom", "NewApi" })
    private class GenerateTask extends AsyncTask<String, Void, Boolean> {
        @SuppressLint("TrulyRandom")
        @Override
        protected Boolean doInBackground(String... params) {
            // 获取到别名
            final String alias = params[0];
            try {
                // 生成密钥库内的一个新条目用
                Calendar cal = Calendar.getInstance();
                Date now = cal.getTime();
                cal.add(Calendar.YEAR, 1);
                Date end = cal.getTime();
                // 使用RSA算法创建KeyPair
                KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA",
                        "AndroidKeyStore");
                // 设置Keypair参数
                // http://wear.techbrood.com/reference/android/security/KeyPairGeneratorSpec.html
                kpg.initialize(new KeyPairGeneratorSpec.Builder(
                        getApplicationContext()).setAlias(alias)// 设置别名
                        .setStartDate(now).setEndDate(end)// 设置开始日期和结束日期(证书有效期)
                        .setSerialNumber(BigInteger.valueOf(1))// 设置序列与
                        .setSubject(new X500Principal("CN=test1")).build());// 设置用于生成密钥签名证书的主题
                return true;
            } catch (Exception e) {
                Log.w(TAG, "Could not generate key", e);
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean result) {
            // 更新数据
            updateKeyList();
            // 生成完成后,按钮恢复可用
            mGenerateButton.setEnabled(true);
        }

        @Override
        protected void onCancelled() {
            mGenerateButton.setEnabled(true);
        }
    }

    /**
     * 异步任务进行签名
     * 
     * @description:使用一个密钥的密钥库中的一些数据创建一个签名
     * @author ldm
     * @date 2016-7-20 下午3:34:27
     */
    private class SignTask extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            final String alias = params[0];
            final String dataString = params[1];
            try {
                byte[] data = dataString.getBytes();
                // 创建KeyPair
                KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
                ks.load(null);
                // 获取别名对应地私钥
                KeyStore.Entry entry = ks.getEntry(alias, null);
                if (!(entry instanceof PrivateKeyEntry)) {
                    Log.w(TAG, "Not an instance of a PrivateKeyEntry");
                    return null;
                }
                // 获取签名
                Signature s = Signature.getInstance("SHA256withRSA");
                s.initSign(((PrivateKeyEntry) entry).getPrivateKey());
                s.update(data);
                byte[] signature = s.sign();
                // 返回64位的签名数据
                return Base64.encodeToString(signature, Base64.DEFAULT);
            } catch (Exception e) {
                Log.w(TAG, "Could not generate key", e);
                return null;
            }
        }

        @Override
        protected void onPostExecute(String result) {
            // 把签名生成的数据展示在EditText中
            mCipherText.setText(result);
            setKeyActionButtonsEnabled(true);
        }

        @Override
        protected void onCancelled() {
            mCipherText.setText("error!");
            setKeyActionButtonsEnabled(true);
        }
    }

    /**
     * 对已经存在的签名密钥进行验证
     * 
     * @description:
     * @author ldm
     * @date 2016-7-20 下午3:46:19
     */
    private class VerifyTask extends AsyncTask<String, Void, Boolean> {
        @Override
        protected Boolean doInBackground(String... params) {
            final String alias = params[0];
            final String dataString = params[1];
            final String signatureString = params[2];
            try {
                byte[] data = dataString.getBytes();
                byte[] signature;
                try {
                    signature = Base64.decode(signatureString, Base64.DEFAULT);
                } catch (IllegalArgumentException e) {
                    signature = new byte[0];
                }
                // 对签名进行验证
                KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
                ks.load(null);
                //获取别名对应密钥
                KeyStore.Entry entry = ks.getEntry(alias, null);
                if (!(entry instanceof PrivateKeyEntry)) {
                    Log.w(TAG, "Not an instance of a PrivateKeyEntry");
                    return false;
                }
                Signature s = Signature.getInstance("SHA256withRSA");
                s.initVerify(((PrivateKeyEntry) entry).getCertificate());
                s.update(data);
                return s.verify(signature);
            } catch (Exception e) {
                Log.w(TAG, "Could not generate key", e);
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean result) {
            if (result) {// 验证成功,文字 是绿色
                mCipherText.setTextColor(getResources().getColor(
                        R.color.solid_green));
            } else {// 验证失败则文字显示红色
                mCipherText.setTextColor(getResources().getColor(
                        R.color.solid_red));
            }
            setKeyActionButtonsEnabled(true);
        }

        @Override
        protected void onCancelled() {
            mCipherText.setText("error!");
            setKeyActionButtonsEnabled(true);
            mCipherText.setTextColor(getResources().getColor(
                    android.R.color.primary_text_dark));
        }
    }

    /**
     * 删除操作
     * 
     * @description:
     * @author ldm
     * @date 2016-7-20 下午3:49:48
     */
    private class DeleteTask extends AsyncTask<String, Void, Void> {
        @Override
        protected Void doInBackground(String... params) {
            final String alias = params[0];
            try {
                KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
                ks.load(null);
                // 删除已经有的签名密钥
                ks.deleteEntry(alias);

            } catch (Exception e) {
                Log.w(TAG, "Could not generate key", e);
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            updateKeyList();
        }

        @Override
        protected void onCancelled() {
            updateKeyList();
        }
    }

    @Override
    public void onClick(View v) {
        final String alias = mSelectedAlias;
        switch (v.getId()) {
        case R.id.verify_button:
            final String data = mPlainText.getText().toString();
            final String signature = mCipherText.getText().toString();
            if (alias != null) {
                setKeyActionButtonsEnabled(false);
                // 验证:生成的密钥别名,输入的别名与密钥进行校验
                new VerifyTask().execute(alias, data, signature);
            }
            break;
        case R.id.generate_button:
            // 密钥别名
            if (TextUtils.isEmpty(aliasInput.getText().toString())) {
                // 输入为空时错误提示
                aliasInput.setError(getResources().getText(
                        R.string.keystore_no_alias_error));
            } else {
                // 取消错误提示
                aliasInput.setError(null);
                mGenerateButton.setEnabled(false);
                // 生成密钥
                new GenerateTask().execute(aliasInput.getText().toString());
            }
            break;
        case R.id.sign_button:
            if (mPlainText.getText().toString() != null) {
                setKeyActionButtonsEnabled(false);
                new SignTask().execute(alias, mPlainText.getText().toString());
            }
            break;
        case R.id.delete_button:
            if (alias != null) {
                setKeyActionButtonsEnabled(false);
                new DeleteTask().execute(alias);
            }
            break;

        }
    }
}

—-布局文件——

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="6dip" >

    <RelativeLayout
        android:id="@+id/entries_list_group"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="12dp"
        android:layout_weight="1" >

        <TextView
            android:id="@+id/entries_list_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="12dp"
            android:layout_marginTop="12dp"
            android:text="已经生成的密钥对应的别名列表" />

        <ListView
            android:id="@+id/entries_list"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/entries_list_label"
            android:layout_below="@+id/entries_list_label"
            android:layout_marginBottom="12dp"
            android:choiceMode="singleChoice" >

            <requestFocus />
        </ListView>
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/sign_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="12dp"
        android:layout_marginTop="12dp" >

        <TextView
            android:id="@+id/key_ops_header"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginBottom="6dp"
            android:text="对已经生成的密钥进行操作"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <TextView
            android:id="@+id/plaintext_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@id/key_ops_header"
            android:layout_below="@id/key_ops_header"
            android:layout_marginLeft="6dp"
            android:text="明码内容:" />

        <EditText
            android:id="@+id/plaintext"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/plaintext_label"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/key_ops_header"
            android:layout_toRightOf="@id/plaintext_label"
            android:ems="10"
            android:maxLines="1" />

        <TextView
            android:id="@+id/ciphertext_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@id/plaintext_label"
            android:layout_below="@+id/plaintext"
            android:text="密钥内容:" />

        <EditText
            android:id="@+id/ciphertext"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/ciphertext_label"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/plaintext"
            android:layout_toRightOf="@id/ciphertext_label"
            android:maxLines="1" />

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@id/plaintext_label"
            android:layout_below="@+id/ciphertext" >

            <Button
                android:id="@+id/sign_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:enabled="false"
                android:text="签名" />

            <Button
                android:id="@+id/verify_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:enabled="false"
                android:text="校验" />

            <Button
                android:id="@+id/delete_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:enabled="false"
                android:text="删除" />
        </LinearLayout>
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/generate_group"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_marginTop="12dp" >

        <TextView
            android:id="@+id/generating_header"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginBottom="6dp"
            android:text="通过输入别名生成密钥"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <TextView
            android:id="@+id/entry_name_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@id/generating_header"
            android:layout_below="@+id/generating_header"
            android:layout_marginBottom="12dp"
            android:layout_marginLeft="6dp"
            android:text="输入别名:" />

        <Button
            android:id="@+id/generate_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@id/entry_name_label"
            android:layout_below="@+id/entry_name"
            android:text="生成密钥" />

        <EditText
            android:id="@+id/entry_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/entry_name_label"
            android:layout_alignParentRight="true"
            android:layout_marginBottom="12dp"
            android:layout_toRightOf="@+id/entry_name_label"
            android:ems="10" />
    </RelativeLayout>

</LinearLayout>
 类似资料: