2024年最全拿来就用:Android 对sharedpreferences 数据进行加密,安卓性能优化面试题

最后

我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了7、8年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。

其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。

不断奔跑,你就知道学习的意义所在!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

}

}

}

} else {

// split只有一位,则已经匹配了

isMatchSplit = true;

}

}

if (isMatchSplit) {

byte[] part = new byte[i - latestStartIndex];

System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);

byte[] decryptPart = decryptByPublicKey(part, publicKey);

for (byte b : decryptPart) {

allBytes.add(b);

}

latestStartIndex = i + splitLen;

i = latestStartIndex - 1;

}

}

byte[] bytes = new byte[allBytes.size()];

{

int i = 0;

for (Byte b : allBytes) {

bytes[i++] = b.byteValue();

}

}

return bytes;

}

/**

  • 使用私钥分段解密

*/

public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted) throws Exception {

int splitLen = DEFAULT_SPLIT.length;

if (splitLen <= 0) {

return decryptByPrivateKey(encrypted);

}

int dataLen = encrypted.length;

List allBytes = new ArrayList(1024);

int latestStartIndex = 0;

for (int i = 0; i < dataLen; i++) {

byte bt = encrypted[i];

boolean isMatchSplit = false;

if (i == dataLen - 1) {

// 到data的最后了

byte[] part = new byte[dataLen - latestStartIndex];

System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);

byte[] decryptPart = decryptByPrivateKey(part);

for (byte b : decryptPart) {

allBytes.add(b);

}

latestStartIndex = i + splitLen;

i = latestStartIndex - 1;

} else if (bt == DEFAULT_SPLIT[0]) {

// 这个是以split[0]开头

if (splitLen > 1) {

if (i + splitLen < dataLen) {

// 没有超出data的范围

for (int j = 1; j < splitLen; j++) {

if (DEFAULT_SPLIT[j] != encrypted[i + j]) {

break;

}

if (j == splitLen - 1) {

// 验证到split的最后一位,都没有break,则表明已经确认是split段

isMatchSplit = true;

}

}

}

} else {

// split只有一位,则已经匹配了

isMatchSplit = true;

}

}

if (isMatchSplit) {

byte[] part = new byte[i - latestStartIndex];

System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);

byte[] decryptPart = decryptByPrivateKey(part);

for (byte b : decryptPart) {

allBytes.add(b);

}

latestStartIndex = i + splitLen;

i = latestStartIndex - 1;

}

}

byte[] bytes = new byte[allBytes.size()];

{

int i = 0;

for (Byte b : allBytes) {

bytes[i++] = b.byteValue();

}

}

return bytes;

}

/**

  • 通过字符串生成私钥,转换服务器传递过来的私钥

*/

public static PrivateKey getPrivateKey(String privateKeyData) {

PrivateKey privateKey = null;

try {

byte[] decodeKey = Base64Decoder.decodeToBytes(privateKeyData);

PKCS8EncodedKeySpec x509 = new PKCS8EncodedKeySpec(decodeKey);//创建x509证书封装类

KeyFactory keyFactory = KeyFactory.getInstance(“RSA”);//指定RSA

privateKey = keyFactory.generatePrivate(x509);//生成私钥

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

} catch (InvalidKeySpecException e) {

e.printStackTrace();

}

return privateKey;

}

/**

  • 通过字符串生成公钥,转换服务器传递过来的公钥

*/

public static PublicKey getPublicKey(String publicKeyData) {

PublicKey publicKey = null;

try {

byte[] decodeKey = Base64Decoder.decodeToBytes(publicKeyData);

X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodeKey);

KeyFactory keyFactory = KeyFactory.getInstance(“RSA”);

publicKey = keyFactory.generatePublic(x509);

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

} catch (InvalidKeySpecException e) {

e.printStackTrace();

}

return publicKey;

}

/**

  • 判断是否创建过秘钥

  • @return

  • @throws KeyStoreException

  • @throws CertificateException

  • @throws NoSuchAlgorithmException

  • @throws IOException

  • @throws UnrecoverableEntryException

*/

public static boolean isHaveKeyStore() {

try {

KeyStore ks = KeyStore.getInstance(“AndroidKeyStore”);

ks.load(null);

if (mAlias == null) {

setAlias(SAMPLE_ALIAS);

}

//从Android加载密钥对密钥存储库中

KeyStore.Entry entry = ks.getEntry(mAlias, null);

if (entry == null) {

return false;

}

} catch (KeyStoreException e) {

e.printStackTrace();

return false;

} catch (CertificateException e) {

e.printStackTrace();

return false;

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

return false;

} catch (IOException e) {

e.printStackTrace();

return false;

} catch (UnrecoverableEntryException e) {

e.printStackTrace();

return false;

}

return true;

}

/**

  • 获得本地AndroidKeyStore中的公钥

  • @return

*/

public static PublicKey getLocalPublicKey() {

try {

KeyStore ks = KeyStore.getInstance(“AndroidKeyStore”);

ks.load(null);

if (mAlias == null) {

setAlias(SAMPLE_ALIAS);

}

//从Android加载密钥对密钥存储库中

KeyStore.Entry entry = ks.getEntry(mAlias, null);

if (entry == null) {

return null;

}

if (!(entry instanceof KeyStore.PrivateKeyEntry)) {

return null;

}

PublicKey publicKey = ((KeyStore.PrivateKeyEntry) entry).getCertificate().getPublicKey();

return publicKey;

} catch (KeyStoreException e) {

e.printStackTrace();

return null;

} catch (CertificateException e) {

e.printStackTrace();

return null;

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

return null;

} catch (IOException e) {

e.printStackTrace();

return null;

} catch (UnrecoverableEntryException e) {

e.printStackTrace();

return null;

}

}

}

package tsou.com.encryption.androidkeystoresign;

public class SecurityConstants {

public static final String KEYSTORE_PROVIDER_ANDROID_KEYSTORE = “AndroidKeyStore”;

public static final String TYPE_RSA = “RSA”;

public static final String TYPE_DSA = “DSA”;

public static final String TYPE_BKS = “BKS”;

public static final String SIGNATURE_SHA256withRSA = “SHA256withRSA”;

public static final String SIGNATURE_SHA512withRSA = “SHA512withRSA”;

}

  • 加密封装在SPSecuredUtils秘钥中方便拿过来直接用

package tsou.com.encryption.sp;

import android.content.Context;

import android.content.SharedPreferences;

import android.util.Base64;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.security.interfaces.RSAPublicKey;

import java.util.Map;

import tsou.com.encryption.AndroidKeyStoreRSA.AndroidKeyStoreRSAUtils;

import tsou.com.encryption.aescbc.Base64Decoder;

import tsou.com.encryption.aescbc.Base64Encoder;

/**

  • Created by zb666 on 2017/2/9.

*/

public class SPSecuredUtils {

/**

  • 保存在手机里面的文件名

*/

public static final String FILE_NAME = “sp_secured”;

private static SharedPreferences mSharedPreferences;

/**

  • 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法

  • @param context

  • @param key

  • @param object

  • @param publicKey

*/

public static void put(Context context, String key, Object object, RSAPublicKey publicKey) {

SharedPreferences sp = context.getSharedPreferences(FILE_NAME,

Context.MODE_PRIVATE);

SharedPreferences.Editor editor = sp.edit();

// byte[] encryptBytes = AndroidKeyStoreRSAUtils.encryptByPublicKeyForSpilt(encryptionString.getBytes(),

// publicKey.getEncoded());

try {

if (object instanceof String) {

byte[] encryptBytes = AndroidKeyStoreRSAUtils.encryptByPublicKey(((String) object).getBytes(),

publicKey.getEncoded());

editor.putString(key, Base64Encoder.encode(encryptBytes));

} else if (object instanceof Integer) {

put(context, key, Integer.toString((Integer) object), publicKey);

} else if (object instanceof Boolean) {

put(context, key, Boolean.toString((Boolean) object), publicKey);

} else if (object instanceof Float) {

put(context, key, Float.toString((Float) object), publicKey);

} else if (object instanceof Long) {

put(context, key, Long.toString((Long) object), publicKey);

} else {

put(context, key, object.toString(), publicKey);

}

SharedPreferencesCompat.apply(editor);

} catch (Exception e) {

e.printStackTrace();

}

}

/**

  • 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值

  • @param context

  • @param key

  • @param defaultObject

  • @return

*/

public static Object get(Context context, String key, Object defaultObject) {

SharedPreferences sp = context.getSharedPreferences(FILE_NAME,

Context.MODE_PRIVATE);

// byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKeyForSpilt(

// Base64Decoder.decodeToBytes(decodeString));

try {

if (defaultObject instanceof String) {

String string = sp.getString(key, (String) defaultObject);

if (!string.equals((String) defaultObject)) {

byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(

Base64Decoder.decodeToBytes(string));

return new String(decryptBytes);

}

return (String) defaultObject;

} else if (defaultObject instanceof Integer) {

String string = sp.getString(key, Integer.toString((Integer) defaultObject));

if (!string.equals(Integer.toString((Integer) defaultObject))) {

byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(

Base64Decoder.decodeToBytes(string));

return Integer.valueOf(new String(decryptBytes));

}

return (Integer) defaultObject;

} else if (defaultObject instanceof Boolean) {

String string = sp.getString(key, Boolean.toString((Boolean) defaultObject));

if (!string.equals(Boolean.toString((Boolean) defaultObject))) {

byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(

Base64Decoder.decodeToBytes(string));

return Boolean.valueOf(new String(decryptBytes));

}

return (Boolean) defaultObject;

} else if (defaultObject instanceof Float) {

String string = sp.getString(key, Float.toString((Float) defaultObject));

if (!string.equals(Float.toString((Float) defaultObject))) {

byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(

Base64Decoder.decodeToBytes(string));

return Float.valueOf(new String(decryptBytes));

}

return (Float) defaultObject;

} else if (defaultObject instanceof Long) {

String string = sp.getString(key, Long.toString((Long) defaultObject));

if (!string.equals(Long.toString((Long) defaultObject))) {

byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(

Base64Decoder.decodeToBytes(string));

return Long.valueOf(new String(decryptBytes));

}

return (Long) defaultObject;

}else if (defaultObject instanceof Double){

String string = sp.getString(key, Double.toString((Double) defaultObject));

if (!string.equals(Double.toString((Double) defaultObject))) {

byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(

Base64Decoder.decodeToBytes(string));

return Double.valueOf(new String(decryptBytes));

}

return (Double) defaultObject;

}

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

/**

  • 将对象储存到sharepreference

  • @param key

  • @param device

  • @param

*/

public static boolean saveDeviceData(Context context, String key, T device, RSAPublicKey publicKey) {

if (mSharedPreferences == null) {

mSharedPreferences = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);

}

ByteArrayOutputStream baos = new ByteArrayOutputStream();

try { //Device为自定义类

// 创建对象输出流,并封装字节流

ObjectOutputStream oos = new ObjectOutputStream(baos);

// 将对象写入字节流

oos.writeObject(device);

// 将字节流编码成base64的字符串

String oAuth_Base64 = new String(Base64.encode

(baos.toByteArray(), Base64.DEFAULT));

byte[] encryptBytes = AndroidKeyStoreRSAUtils.encryptByPublicKey(oAuth_Base64.getBytes(),

publicKey.getEncoded());

mSharedPreferences.edit().putString(key, Base64Encoder.encode(encryptBytes)).apply();

return true;

} catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

  • 将对象从shareprerence中取出来

  • @param key

  • @param

  • @return

*/

public static T getDeviceData(Context context, String key) {

if (mSharedPreferences == null) {

mSharedPreferences = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);

}

try {

T device = null;

String productBase64 = mSharedPreferences.getString(key, null);

if (productBase64 == null) {

return null;

}

byte[] decryptBytes = AndroidKeyStoreRSAUtils.decryptByPrivateKey(

Base64Decoder.decodeToBytes(productBase64));

// 读取字节

byte[] base64 = Base64.decode(new String(decryptBytes).getBytes(), Base64.DEFAULT);

// 封装到字节流

ByteArrayInputStream bais = new ByteArrayInputStream(base64);

// 再次封装

ObjectInputStream bis = new ObjectInputStream(bais);

// 读取对象

device = (T) bis.readObject();

return device;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

/**

  • 移除某个key值已经对应的值

  • @param context

  • @param key

*/

public static void remove(Context context, String key) {

SharedPreferences sp = context.getSharedPreferences(FILE_NAME,

Context.MODE_PRIVATE);

SharedPreferences.Editor editor = sp.edit();

editor.remove(key);

SharedPreferencesCompat.apply(editor);

}

/**

  • 清除所有数据

  • @param context

*/

public static void clear(Context context) {

SharedPreferences sp = context.getSharedPreferences(FILE_NAME,

Context.MODE_PRIVATE);

SharedPreferences.Editor editor = sp.edit();

editor.clear();

SharedPreferencesCompat.apply(editor);

}

/**

  • 查询某个key是否已经存在

  • @param context

  • @param key

  • @return

*/

public static boolean contains(Context context, String key) {

SharedPreferences sp = context.getSharedPreferences(FILE_NAME,

Context.MODE_PRIVATE);

return sp.contains(key);

}

/**

  • 返回所有的键值对

  • @param context

  • @return

*/

public static Map<String, ?> getAll(Context context) {

SharedPreferences sp = context.getSharedPreferences(FILE_NAME,

Context.MODE_PRIVATE);

return sp.getAll();

}

/**

  • 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类

  • @author zhy

*/

private static class SharedPreferencesCompat {

private static final Method sApplyMethod = findApplyMethod();

/**

  • 反射查找apply的方法

  • @return

*/

@SuppressWarnings({“unchecked”, “rawtypes”})

private static Method findApplyMethod() {

try {

Class clz = SharedPreferences.Editor.class;

return clz.getMethod(“apply”);

} catch (NoSuchMethodException e) {

}

return null;

}

/**

  • 如果找到则使用apply执行,否则使用commit

  • @param editor

*/

public static void apply(SharedPreferences.Editor editor) {

try {

if (sApplyMethod != null) {

sApplyMethod.invoke(editor);

return;

}

} catch (IllegalArgumentException e) {

} catch (IllegalAccessException e) {

} catch (InvocationTargetException e) {

}

editor.commit();

}

}

}

  • 执行操作

package tsou.com.encryption.activity.SP;

import android.app.Activity;

import android.content.Context;

import android.os.Build;

import android.os.Bundle;

import android.support.annotation.RequiresApi;

import android.support.v7.app.AppCompatActivity;

import android.text.TextUtils;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

import android.widget.Toast;

import java.security.InvalidAlgorithmParameterException;

import java.security.KeyPair;

import java.security.NoSuchAlgorithmException;

import java.security.NoSuchProviderException;

import java.security.interfaces.RSAPublicKey;

import tsou.com.encryption.AndroidKeyStoreRSA.AndroidKeyStoreRSAUtils;

import tsou.com.encryption.R;

import tsou.com.encryption.aescbc.Base64Encoder;

import tsou.com.encryption.sp.SPSecuredUtils;

public class SPActivity extends AppCompatActivity implements View.OnClickListener {

private EditText encryptionContext;

private Button encryption;

private TextView tvEncryption;

private Button decode;

private TextView tvDecode;

private Activity mActivity;

private Context mContext;

private RSAPublicKey publicKey;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_aes);

mActivity = this;

mContext = this;

encryptionContext = (EditText) findViewById(R.id.et_encryption_context);

encryption = (Button) findViewById(R.id.btn_encryption);

tvEncryption = (TextView) findViewById(R.id.tv_encryption);

decode = (Button) findViewById(R.id.btn_decode);

tvDecode = (TextView) findViewById(R.id.tv_decode);

encryption.setText(“存入”);

decode.setText(“读取”);

initListener();

}

private void initListener() {

encryption.setOnClickListener(this);

decode.setOnClickListener(this);

}

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)

@Override

public void onWindowFocusChanged(boolean hasFocus) {

super.onWindowFocusChanged(hasFocus);

if (AndroidKeyStoreRSAUtils.isHaveKeyStore()) {//是否有秘钥

publicKey = (RSAPublicKey) AndroidKeyStoreRSAUtils.getLocalPublicKey();

if (publicKey != null) {

Toast.makeText(mContext, “已经生成过密钥对”, Toast.LENGTH_SHORT).show();

最后

我一直以来都有整理练习大厂面试题的习惯,有随时跳出舒服圈的准备,也许求职者已经很满意现在的工作,薪酬,觉得习惯而且安逸。

不过如果公司突然倒闭,或者部门被裁减,还能找到这样或者更好的工作吗?

我建议各位,多刷刷面试题,知道最新的技术,每三个月可以去面试一两家公司,因为你已经有不错的工作了,所以可以带着轻松的心态去面试,同时也可以增加面试的经验。

我可以将最近整理的一线互联网公司面试真题+解析分享给大家,大概花了三个月的时间整理2246页,帮助大家学习进步。

由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!以下是部分内容截图:

部分目录截图

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

yption.setText(“存入”);

decode.setText(“读取”);

initListener();

}

private void initListener() {

encryption.setOnClickListener(this);

decode.setOnClickListener(this);

}

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)

@Override

public void onWindowFocusChanged(boolean hasFocus) {

super.onWindowFocusChanged(hasFocus);

if (AndroidKeyStoreRSAUtils.isHaveKeyStore()) {//是否有秘钥

publicKey = (RSAPublicKey) AndroidKeyStoreRSAUtils.getLocalPublicKey();

if (publicKey != null) {

Toast.makeText(mContext, “已经生成过密钥对”, Toast.LENGTH_SHORT).show();

最后

我一直以来都有整理练习大厂面试题的习惯,有随时跳出舒服圈的准备,也许求职者已经很满意现在的工作,薪酬,觉得习惯而且安逸。

不过如果公司突然倒闭,或者部门被裁减,还能找到这样或者更好的工作吗?

我建议各位,多刷刷面试题,知道最新的技术,每三个月可以去面试一两家公司,因为你已经有不错的工作了,所以可以带着轻松的心态去面试,同时也可以增加面试的经验。

我可以将最近整理的一线互联网公司面试真题+解析分享给大家,大概花了三个月的时间整理2246页,帮助大家学习进步。

由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!以下是部分内容截图:

[外链图片转存中…(img-hrmuR2ao-1715127489592)]

[外链图片转存中…(img-fLTj591p-1715127489593)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值