• 移动应用安全开发指南(Android)--数据存储


    1、数据存储

    概述

    移动应用经常需要在某些场景下(比如用户登录)处理和用户或业务相关的敏感数据,有时候为满足某些业务需求,需要把这些敏感数据存储在本地,如果不对这些数据进行适当处理,就有可能存在敏感信息泄漏的风险。

    安全准则

    A.      敏感数据总是优先考虑存储在内部空间。

    B.      敏感数据无论是存储在内部还是外部空间均应经过加密后再存储,应避免直接明文存储。

    C.      避免将敏感数据存储在全局可访问的缓存里(如log、剪切板等)。

    D.      敏感数据避免硬编码在代码里面,常见的有用户账户口令和加密密钥等。

    详细描述

    A.      可以使用JDK提供的javax.crypto包进行加/解密,注意加密算法的选择以及密钥复杂度策略(参考第6条以及附录1)。

    B.      使用System.out.print系列以及android.util.Log类的方法(比如Log.d())会将日志存储在系统缓冲区,任意应用都可以通过logcat指令查看缓存里面的敏感信息(比如密码和sessionID等),因此Release版本应移除这些主要用于debug的方法。

    备注

    A.      常见的敏感数据有用户口令、用户个人信息和sessionID等等,但也有一些是和业务强相关的,当不太容易判断时,可以和安全工程师一起确认。

    B.      Android使用沙箱技术对不同应用之间的内部存储空间进行了隔离,但考虑到应用自身的漏洞(比如SQL注入)和ROOT的场景,对内部存储数据进行加密还是非常必要的。

    提示:如果IE显示不正常,请使用chrome浏览器

    附录1:

    1、安全的加/解密方案:

    1.1AES128对称加密方案:

     public class AES128Enc {

             public static String encrypt(byte[] rawKey, String cleartext) throws Exception {     

            SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");     

            Cipher cipher = Cipher.getInstance("AES");     

            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);     

            byte[] encrypted = cipher.doFinal(cleartext.getBytes());

            return toHex(encrypted);     

        }     

             

        public static String decrypt(byte[] rawKey, String encrypted) throws Exception {       

            byte[] enc = toByte(encrypted);     

            SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");     

            Cipher cipher = Cipher.getInstance("AES");     

            cipher.init(Cipher.DECRYPT_MODE, skeySpec);     

            byte[] decrypted = cipher.doFinal(enc);

            return new String(decrypted);     

        }     

        

        /* 产生随机的128bit AES密钥 */

        public static byte[] getRawKey(byte[] seed) throws Exception {     

            KeyGenerator kgen = KeyGenerator.getInstance("AES");     

            SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");     

            sr.setSeed(seed);     

            kgen.init(128, sr);      

            SecretKey skey = kgen.generateKey();     

            byte[] raw = skey.getEncoded();     

            return raw;     

        }                   

             

        public static byte[] toByte(String hexString) {     

            int len = hexString.length()/2;     

            byte[] result = new byte[len];     

            for (int i = 0; i < len; i++)     

                result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();     

            return result;     

        }     

        

        public static String toHex(byte[] buf) {     

            if (buf == null)     

                return "";     

            StringBuffer result = new StringBuffer(2*buf.length);     

            for (int i = 0; i < buf.length; i++) {     

                appendHex(result, buf[i]);     

            }     

            return result.toString();     

        } 

       

        private final static String HEX = "0123456789ABCDEF";     

        private static void appendHex(StringBuffer sb, byte b) {     

            sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));

        }

    }

    1.2SHA256哈希算法:

    public class Sha256Hash {

        private static byte [] getHash(String strForHash) {

            MessageDigest digest = null ;

            try {

                digest = MessageDigest. getInstance( "SHA-256");

            } catch (NoSuchAlgorithmException e1) {

                e1.printStackTrace();

            }

            digest.reset();

            return digest.digest(strForHash.getBytes());

        }

     

        public static String bin2hex(String strForHash) {

            byte [] data = getHash(strForHash);

            return String.format( "%0" + (data.length * 2) + "X", new BigInteger(1, data));

        }

    }

  • 相关阅读:
    静态代码块执行时机
    java中的命令
    JDBC
    final, finally, finalize
    面向对象
    线程中常用的一些方法
    线程中的yield()
    线程中的join()
    Thread对象 既传入了Runnable对象又重写了run()方法
    Python 绘制词云
  • 原文地址:https://www.cnblogs.com/fishou/p/4205211.html
Copyright © 2020-2023  润新知