android加密_android加密算法 - CSDN
精华内容
参与话题
  • Android 加密 AES

    2020-05-05 15:56:40
    AES 加密又称对称性加密,在开发中常用于对流数据对加密,尤其是流数据在网络传输过程中,担心被泄露,AES 加密被常用于这块的校验中。下面是 AES 加密的百度百科说明解释: AES加密标准又称为高级加密标准 ...

    AES 加密又称对称性加密,在开发中常用于对流数据对加密,尤其是流数据在网络传输过程中,担心被泄露,AES 加密被常用于这块的校验中。下面是 AES 加密的百度百科说明解释:

    AES加密标准又称为高级加密标准 Rijndael 加密法,是美国国家标准技术研究所NIST旨在取代 DES 的 21 世纪的加密标准。AES 的基本要求是,采用对称分组密码体制,密钥长度可以为 128、192 或 256 位,分组长度 128 位,算法应易在各种硬件和软件上实现。1998 年 NIST 开始 AES 第一轮分析、测试和征集,共产生了 15 个候选算法。
    1999 年 3 月完成了第二轮 AES2 的分析、测试。2000 年 10 月 2 日美国政府正式宣布选中比利时密码学家 Joan Daemen 和 Vincent Rijmen 提出的一种密码算法 Rijndael作为 AES 的加密算法。
    AES 加密数据块和密钥长度可以是 128b、192b、256b 中的任意一个。AES 加密有很多轮的重复和变换。大致步骤如下:
    ①密钥扩展(Key Expansion)
    ②初始轮(InitialRound)
    ③重复轮(Rounds),每一重复轮又包括字节间减法运算(SubBytes)、行移位(ShiftRows)、列混合(MixColumns)、轮密钥加法运算(AddRoundKey) 等操作
    ④最终轮(Final Round),最终轮没有列混合操作(MixColumns)

    接下来把 Android 的代码贴一下:

    • 解密
        public static byte[] decryptData(byte[] data, byte[] key, byte[] iv, String transformation) throws Exception {
    
            if (data == null || data.length == 0
                    || key == null || key.length < 16
                    || iv == null || iv.length < 16
                    || transformation == null || transformation.length() == 0) {
                throw (new InvalidParameterException());
            }
            AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
            SecretKeySpec newKey = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance(transformation,"BC");
            cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
            return cipher.doFinal(data);
        }
    
    • 加密
    public static byte[] encryptEncode(byte[] data, byte[] key, byte[] iv, String transformation) throws Exception {
    
            if (data == null || data.length == 0
                    || key == null || key.length == 0
                    || iv == null || iv.length == 0
                    || transformation == null || transformation.length() == 0) {
                throw (new InvalidParameterException());
            }
    
            AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
            SecretKeySpec newKey = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance(transformation,"BC");
            cipher.init(Cipher.ENCRYPT_MODE, newKey, ivSpec);
            return cipher.doFinal(data);
        }
    
    • key 密钥必须是 16 位以上

    • iv:偏移量,最少 16 位数

    • transformation 的选择
      一般选择 PKCS7Padding,因为 PKCS5Padding 最终调用的是 PKCS7Padding 只是做了块位数的限制 详情请看
      另外要注意 Java 是不支持 PKCS7Padding,需要引入 bouncycastle https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16
      组件实现

    • base64 编码
      与后台人员协商,如果是需要对数据进行编码解码,协商好,只需要通过以下方式中转就可以了

    byte[] baseData = Base64.encode(cipher.doFinal(data), Base64.DEFAULT)
    

    例子

    
        @Test
        public void  test(){
            byte[] data = {0x01,0x02,0x03,0x04,0x05};
            byte[] mAESKey = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
            byte[] iv = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
            String mAESTransformation = "AES/CBC/PKCS7Padding";
    
            try {
                byte[] encrypt = EncryptUtil.encryptEncode(data, mAESKey, iv, mAESTransformation);
                byte[] decrypt = EncryptUtil.decryptData(encrypt, mAESKey, iv, mAESTransformation);
    
                System.out.println("加密前:"+bytes2HexString(data));
                System.out.println("加密后:"+bytes2HexString(encrypt));
                System.out.println("解密后:"+bytes2HexString(decrypt));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static String bytes2HexString(byte[] bytes) {
            String ret = "";
            for (int i = 0; i < bytes.length; i++) {
                String hex = Integer.toHexString(bytes[i] & 0xFF);
                if (hex.length() == 1) {
                    hex = '0' + hex;
                }
                ret += hex.toUpperCase();
            }
            return ret;
        }
    

    结果

    加密前:0102030405
    加密后:F2C0C2091ABB5CC09FC71E4614E0733B
    解密后:0102030405
    
    展开全文
  • Android 加密

    2014-09-11 10:00:27
    Android 加密解密 http://www.eoeandroid.com/thread-66236-1-1.html Android 加密解密字符串 http://www.eoeandroid.com/thread-81425-1-1.html Android 用MD5加密算法加密密码(一) ...
    一、实例教程 

    Android 加密解密
    http://www.eoeandroid.com/thread-66236-1-1.html

    Android 加密解密字符串
    http://www.eoeandroid.com/thread-81425-1-1.html

    Android 用MD5加密算法加密密码(一)
    http://www.eoeandroid.com/thread-97843-1-1.html

    Android 用MD6加密算法加密密码(二)
    http://www.eoeandroid.com/thread-97846-1-1.html

    鉴客 Android客户端与服务器端通过DES加密认证
    http://www.eoeandroid.com/thread-159272-1-1.html

    android下md5加密,大家收藏下吧 ,用到的时候可以直接拿来用
    http://www.eoeandroid.com/thread-51590-1-1.html

    Android 获取自己程序APK包的MD5指纹
    http://www.eoeandroid.com/thread-92389-1-1.html

    给自己的网络数据加密
    http://www.eoeandroid.com/thread-97336-1-1.html

    JAVA加密解密
    http://www.eoeandroid.com/thread-69738-1-1.html


    二、资料下载

    加密记事本,陈年作品(源码放出)
    http://www.eoeandroid.com/thread-99203-1-1.html

    通用DES加密解密方法
    http://www.eoeandroid.com/thread-56774-1-1.html

    一个加密的记事本
    http://www.eoeandroid.com/thread-122363-1-1.html


    三、EOE社区实战问题解答

    Android ZIP 加密解密
    http://www.eoeandroid.com/thread-116230-1-1.html

    android AES加密和解密
    http://www.eoeandroid.com/thread-162137-1-1.html

    关于android加密
    http://www.eoeandroid.com/thread-73308-1-1.html

    android 与 java 的RSA加解密
    http://www.eoeandroid.com/thread-72268-1-1.html

    求高手相助,关于Android加密的问题
    http://www.eoeandroid.com/thread-63822-1-1.html

    Android下DES加密和J2SE平台下加密结果不一样
    http://www.eoeandroid.com/thread-83595-1-1.html

    Android中自带的RSA加密算法和JAVA中的不是一个标准的吗?
    http://www.eoeandroid.com/thread-102614-1-1.html

    在DES解密时候出现pad block corrupted错误
    http://www.eoeandroid.com/thread-63284-1-1.html

    请问一下,android与PHP连接安全问题
    http://www.eoeandroid.com/thread-73501-1-1.html

    短信加密问题
    http://www.eoeandroid.com/thread-75590-1-1.html

    我java des加密后的密文和c加密出来的最后一段密文不一样!
    http://www.eoeandroid.com/thread-57876-1-1.html

    MD5 加密的方法不能理解
    http://www.eoeandroid.com/thread-69619-1-1.html

    全新的数据加密技术
    http://www.eoeandroid.com/thread-69548-1-1.html

    求:文件/文件夹加密 解决方案 或指点
    http://www.eoeandroid.com/thread-114552-1-1.html

    CRC32算法如何加密字符串?
    http://www.eoeandroid.com/thread-102782-1-1.html

    讨论一下 :文件/文件夹 的加密和解密 如何实现
    http://www.eoeandroid.com/thread-114550-1-1.html

    关于程序加密的问题
    http://www.eoeandroid.com/thread-91900-1-1.html

    请教Android上的DSA加密方法
    http://www.eoeandroid.com/thread-63756-1-1.html

    Json在android中的加密传输
    http://www.eoeandroid.com/thread-82508-1-1.html

    怎么给视频加密?
    http://www.eoeandroid.com/thread-101882-1-1.html

    资源图片压缩或加密求助
    http://www.eoeandroid.com/thread-71619-1-1.html

    android客户端 访问服务器的url加密 求加密方式
    http://www.eoeandroid.com/thread-147709-1-1.html

    怎么实现对android的文件夹加密或者锁定啊?
    http://www.eoeandroid.com/thread-24955-1-1.html

    如何给文件加密?
    http://www.eoeandroid.com/thread-68058-1-1.html


    四、社区求助未解答帖

    android 如何对视频加密和解密
    http://www.eoeandroid.com/thread-103350-1-1.html

    android base64加密 解码 apk信息读取问题请教
    http://www.eoeandroid.com/thread-163307-1-1.html

    android与PC socket传输加密密文出错
    http://www.eoeandroid.com/thread-156109-1-1.html

    android下是否能用classloader对class进行加解密
    http://www.eoeandroid.com/thread-72582-1-1.html

    新手请教各位大虾: 一个报错,详细请看里面
    http://www.eoeandroid.com/thread-157399-1-1.html

    开发/调试MD5指纹和生产/发布MD5指纹
    http://www.eoeandroid.com/thread-65795-1-1.html

    加密数据库查询的问题
    http://www.eoeandroid.com/thread-166386-1-1.html

    二维码加密了
    http://www.eoeandroid.com/thread-172262-1-1.html

    求一个能实现短信加密解密功能的源码!
    http://www.eoeandroid.com/thread-161206-1-1.html

    急求android短信加密图片加密的源码
    http://www.eoeandroid.com/thread-166981-1-1.html

    加密相片
    http://www.eoeandroid.com/thread-66466-1-1.html

    明文加密码 加密后密文长度不变 要怎么实现?
    http://www.eoeandroid.com/thread-111009-1-1.html

    加密记事本都用到了android哪些知识 希望能得到详细讲解
    http://www.eoeandroid.com/thread-172381-1-1.html
    展开全文
  • 目录 1. 实战背景 2. 问题分析 3. 实战记录 1) 脱壳 2) 找到解密函数 ...阅读本文之前,建议阅读Android逆向实战篇(Https抓包)。...爬取这款App时发现,抓包抓到的数据是加密过的,如图1所示(原数据较长...

    目录

    1. 实战背景

    2. 问题分析

    3. 实战记录

    1) 脱壳

    2) 找到解密函数

    3) 重现

    4. 总结


    阅读本文之前,建议阅读Android逆向实战篇(Https抓包)。

    1. 实战背景

    由于工作需要,要爬取某款App的数据,App的具体名称此处不便透露,避免他们发现并修改加密逻辑我就得重新破解了。

    爬取这款App时发现,抓包抓到的数据是加密过的,如图1所示(原数据较长,图中有省略),可以看到这个超长的data1字段,而且是加密过的。显然,对方不想让我们直接拿到它的信息,选择传过来一个加密的字段,而我们要做的,就是解密这个字段。

                                                                        

                                                                                              图1  数据包截图

    2. 问题分析

    既然服务器返回了一段无法阅读的加密数据,那么必然,这段数据是在客户端进行解密的。因此,我们要做的就是找出解密代码,重现它,从而来破解这段加密数据。

    所以,我们要做的,就是逆向App→找到解密函数→重现。就这么简单。

    3. 实战记录

    1) 脱壳

    拿到APK后,要做的第一件是就是查壳。如果你第一件事就是用jadx、AndroidKiller、APKTool等各种工具怼的话,那你一定是个愣头青,铁头娃,石乐志。如图2所示,可以看到这个App是经过腾讯加固的,需要费一番功夫才能拿到源码。

                                                                     

                                                                                                图2  查壳

    脱壳是一项比较麻烦的工作,脱壳大神可以直接进入下一步,像我一样的小菜鸡建议转去阅读《Android逆向基础篇(脱壳机)》,拥有一部脱壳机可以助你轻松无脑的脱去市面上大多数的壳。

    2) 找到解密函数

    找源码是有技巧的,一行一行阅读的话头都秃了源码还没读完,因此需要巧用搜索功能。

    对于搜索功能,个人十分推荐jadx,它的搜索功能十分强大,但随之而来的是它对内存的巨大需求。可以看到图3中,它占了1600多MB内存。

                                                                   

                                                                                        图3  jadx占用内存

    这里分享一下我对于代码搜索的一些拙见。想破解请求中的加密字段,首先肯定是搜索加密的字段名,但有时候这些字段叫做“token”、“key”等随便搜搜几千个的名字,那就很难从几千个中找出来了。这种情况,可以搜索请求的URL,然后一步步findusage,找出用这个URL的代码,慢慢抽丝剥茧总能找到的,个人感觉效率直接搜字段名要高。使用URL搜索时不建议输入整个URL,大多数情况下都会拼接的,找几个有特征的词去搜就行了。

    对于返回的加密数据,上面这种搜URL的方法就不好使了。图1中可以看到加密字段叫data1,幸好它不叫data,如果它叫data,那就得从5000多个data中把它挖出来。而源码中的data1,只有52个,瞬间筛掉了99%的无关代码。

    搜索结果如图4所示。截全图的话看不清,因此这里只截取部分。相信有视力5.3英语16级的小伙伴已经发现了,几个闪亮的、引人注目的“Decode”,decode data1,那还有疑问吗?肯定是它干的好事呀。

                                               

                                                                                          图4  “data1”搜索结果

    在上面随便找个decode双击,然后按住ctrl点击函数名,就能看到这个decode函数的源码了,如图5所示,这个名为eee3DecodeECB的函数,八成就是我们想要找到的解密函数了。

                                               

                                                                                          图5  decode函数源码

    3) 重现

    直接把这段代码复制进Intellij中,效果如图6所示。

                  

                                                                                      图6  Intellij截图(1)

    图6红的仿佛梦中的A股,股市越红越好,而代码则是越红越不好。我们需要处理这些cannot resolve的东西。

    缺啥补啥,先看变量,需要ENCODING,f224IV,SECRET_KEY,不出所料,这几个都是类中定义的静态变量,顺便把开头的import也一起复制过来,现在的效果就好多了。

                                 

                                                                                    图7  Intellij截图(2)

    这里的Base64这个包原本是android.util.Base64,在开发安卓时,在Android Studio中直接import就可以了,但在Intellij中直接import是不行的,需要自己把这个包下载一下。

    不报错了,那就写个main函数解密试试。把抓包抓到的巨长无比的data1复制到main中的data1,然后调用一下刚才重现的解密函数。因为data1实在是长,这里就不复制进去的,请自行脑补。还有,记得一定要写try。

                                                                    

                                                                                           图8  main函数

    从头到尾再看一遍我们重现的解密代码,一切都很perfect,运行走起。看一下运行结果,是一段Json格式的数据,找一个json在线格式化的网站把运行结果复制进行,结果如图9所示,显然,完成了对加密数据包的解密

                                      

                                                                                             图9  运行结果

    可以看到,经过上述操作,完成了对加密数据包的解密。

    4. 总结

    上述过程并不复杂,也几乎没有任何难点,因此这种加密方式可以说并不合格,甚至可以说有些自欺欺人。加密的本意显然是为了增加一点破解难度,但我这样的菜鸡也只花了不到半小时就完成了破解,何况专业的逆向大神呢。讲真,哪怕把data1这个名字改成data也能增加一些破解的时间成本。

    单纯的Java代码加密太容易破解了,建议此类场景还是用So加密更好,毕竟想要把so文件执行起来还是得费一番功夫的。

    展开全文
  • Android加密之全盘加密

    万次阅读 2017-08-03 11:19:00
    Android加密之全盘加密前言Android 的安全性问题一直备受关注,Google 在 Android 系统的安全方面也是一直没有停止过更新,努力做到更加安全的手机移动操作系统。在 Android 的安全性方面,有很多模块: 内核安全性 ...

    Android加密之全盘加密

    前言

    Android 的安全性问题一直备受关注,Google 在 Android 系统的安全方面也是一直没有停止过更新,努力做到更加安全的手机移动操作系统。

    在 Android 的安全性方面,有很多模块:

    1. 内核安全性
    2. 应用安全性
    3. 应用签名
    4. 身份验证
    5. Trusty TEE
    6. SELinux
    7. 加密
      等等

    其中,加密又分全盘加密(Android 4.4 引入)和文件级加密(Android 7.0 引入),本文将论述加密中的全盘加密的基本知识。全盘加密在 Android 4.4 中引入,在 Android 5.0 中做了比较大的更新。

    这里写图片描述

    本文部分片段摘自 Android 官网,融合笔者的个人理解和知识。

    什么是全盘加密

    全盘加密是使用已加密的密钥对 Android 设备上的所有用户数据进行编码的过程。设备经过加密后,所有由用户创建的数据在写入磁盘之前都会自动加密,并且所有读取操作都会在将数据返回给调用进程之前自动解密数据。

    Android 5.0 中又引入了以下新功能:

    • 创建了快速加密方式,这种加密方式只会对数据分区中已使用的分块进行加密,以免首次启动用时过长。目前只有 EXT4 和 F2FS 文件系统支持快速加密。
    • 添加了 forceencrypt fstab 标记,以便在首次启动时进行加密。
    • 添加了对解锁图案和无密码加密的支持。
    • 添加了由硬件支持的加密密钥存储空间,该空间使用可信执行环境(TEE,例如 TrustZone)的签名功能。

    全盘加密运作方式

    Android 全盘加密基于在块设备层运行的内核功能 dm-crypt。因此,这种加密方式适用于以块设备的形式呈现给内核的嵌入式多媒体卡 (eMMC) 和类似闪存设备。YAFFS 会直接与原始 NAND 闪存芯片交互,无法进行全盘加密。

    全盘加密采用的是 128 位高级加密标准 (AES) 算法(搭配密码块链接 (CBC) 和 ESSIV:SHA256)。对主密钥进行加密时使用的是 128 位 AES 算法,并会调用 OpenSSL 库。对于该密钥,您必须使用 128 位或更多位(可以选择 256 位)。

    Android 5.0 版中有以下 4 种加密状态:

    • 默认
    • PIN 码
    • 密码
    • 解锁图案

    这里写图片描述

    首次启动时,设备会创建一个随机生成的 128 位主密钥,然后会使用默认密码和存储的盐对其进行哈希处理。默认密码是“default_password”。不过,设备还会通过 TEE(例如 TrustZone)为生成的哈希签名。TEE 会使用相应签名的哈希来加密主密钥。

    您可以在 Android 开放源代码项目 cryptfs.c 文件中找到定义的默认密码。

    当用户在设备上设置 PIN 码/通行码或密码时,只有 128 位的密钥会被重新加密并存储起来(也就是说,更改用户 PIN 码/通行码/解锁图案不会导致重新加密用户数据)。请注意,受管理的设备可能受 PIN 码、解锁图案或密码限制。

    加密操作由 init 和 vold 管理。 init 负责调用 vold,然后 vold 会设置相关属性以触发 init 中的事件。系统的其他部分也会查看这些属性以执行各项任务,例如报告状态、提示输入密码,或有严重错误发生时提示恢复出厂设置。为了调用 vold 中的加密功能,系统会使用命令行工具 vdc 的 cryptfs 命令:checkpw、restart、enablecrypto、changepw、cryptocomplete、verifypw、setfield、getfield、mountdefaultencrypted、getpwtype、getpw 以及 clearpw。

    要加密、解密或清空 /data,/data 不得处于装载状态。但要显示任何界面,框架都必须启动,而框架需要 /data 才能运行。为了解决这一冲突,/data 上会装载一个临时文件系统。通过该文件系统,Android 可以提示输入密码、显示进度或根据需要建议清除数据。不过,该文件系统会带来以下限制:要从临时文件系统切换到实际的 /data 文件系统,系统必须停止临时文件系统中打开了文件的所有进程,并在实际的 /data 文件系统中重启这些进程。为此,所有服务都必须位于以下其中一个组内:core、main 和 late_start。

    • core:启动后一直不会关闭。
    • main:关闭,然后在用户输入磁盘密码后会重启。
    • late_start:在 /data 未解密并装载之前,一直不会启动。

    为了触发这些操作,vold.decrypt 属性会被设为多种字符串。要结束和重启服务,请使用以下 init 命令:

    • class_reset:停止相应服务,但允许通过 class_start 重启该服务。
    • class_start:重启相应服务。
    • class_stop:停止相应服务并添加 SVC_DISABLED 标记。被停止的服务不会对。
    • class_start 做出响应。

    加密流程和启动流程

    使用 forceencrypt 加密新设备

    这是 Android 5.0 设备首次启动时的常规流程。

    1. 检测带有 forceencrypt 标记的未加密文件系统

      /data 未加密,但需要加密,因为 forceencrypt 强制要求进行此项加密。卸载 /data。

    2. 开始加密 /data

      vold.decrypt = “trigger_encryption” 会触发 init.rc,从而使 vold 对 /data 进行无密码加密。(因为这应该是新设备,还没有设置密码。)

    3. 装载 tmpfs

      vold 会装载一个 tmpfs /data(使用 ro.crypto.tmpfs_options 中的 tmpfs 选项),并会将 vold.encrypt_progress 属性设为 0。 vold 会准备 tmpfs /data 以便启动已加密的系统,并会将 vold.decrypt 属性设为 trigger_restart_min_framework

    4. 启动框架以显示进度

      由于设备上几乎没有要加密的数据,加密过程很快就会完成,因此实际上通常并不会显示进度条。如需关于进度界面的更多详细信息,请参阅加密现有设备。

    5. /data 加密后,关闭框架

      vold 会将 vold.decrypt 设为 trigger_default_encryption,这会启动 defaultcrypto 服务。(这会启动以下流程来装载默认的已加密用户数据。)trigger_default_encryption 会检查加密类型,以了解 /data 加密是否使用了密码。由于 Android 5.0 设备是在首次启动时加密,应该没有设置任何密码,因此我们要解密并装载 /data。

    6. 装载 /data

      接下来,init 会使用从 ro.crypto.tmpfs_options(在 init.rc 中设置)中选取的参数在 tmpfs RAMDisk 中装载 /data。

    7. 启动框架

      将 vold 设为 trigger_restart_framework,这会继续常规启动过程。

    启动未进行默认加密的已加密设备

    当您启动设有密码的已加密设备时,则会发生该流程。设备的密码可以是 PIN 码、解锁图案或密码。

    1. 检测设有密码的已加密设备

      会发现 Android 设备已加密,因为设置了 ro.crypto.state = “encrypted” 标记

      由于 /data 是使用密码加密的,因此 vold 会将 vold.decrypt 设为 trigger_restart_min_framework。

    2. 装载 tmpfs

      init 会设置 5 个属性,以保存为 /data(包含从 init.rc 传入的参数)提供的初始装载选项。 vold 会使用这些属性来设置加密映射:
      ro.crypto.fs_type
      ro.crypto.fs_real_blkdev
      ro.crypto.fs_mnt_point
      ro.crypto.fs_options
      ro.crypto.fs_flags (ASCII 码 8 位十六进制数字,以 0x 开头)

    3. 启动框架以提示输入密码

      框架会启动并看到 vold.decrypt 已设为 trigger_restart_min_framework。这让框架知道自己是在 tmpfs /data 磁盘中启动的,并且需要获取用户密码。

      不过,它首先需要确认磁盘是否已经过适当加密。它会向 vold 发送 cryptfs cryptocomplete 命令。 如果加密已成功完成,vold 会返回 0;如果发生内部错误,则会返回 -1;如果加密未成功完成,则会返回 -2。vold 通过查看 CRYPTO_ENCRYPTION_IN_PROGRESS 标记的加密元数据来确定应返回的值。如果设置了此标记,则表示加密过程中断了,并且设备上没有可用的数据。如果 vold 返回错误,界面中应显示一条消息,提示用户重新启动设备并将其恢复出厂设置,并且界面中应为用户提供一个用于执行该操作的按钮。

    4. 通过密码解密数据

      cryptfs cryptocomplete 成功后,框架会显示一个界面,提示用户输入磁盘密码。界面会向 vold 发送 cryptfs checkpw 命令来检查用户输入的密码。如果密码正确(通过以下方式判定:在临时位置成功装载已解密的 /data,然后将其卸载),vold 会将已解密块设备的名称保存在 ro.crypto.fs_crypto_blkdev 属性中,并向界面返回状态 0。如果密码不正确,则向界面返回 -1。

    5. 停止框架

      界面会显示加密启动图形,然后使用 cryptfs restart 命令调用 vold。vold 会将 vold.decrypt 属性设为 trigger_reset_main,这会使 init.rc 执行 class_reset main 命令。此命令会停止 main 类中的所有服务,以便卸载 tmpfs /data。

    6. 装载 /data

      然后,vold 会装载已解密的实际 /data 分区,并准备新的分区(如果加密时采用了首次发布不支持的数据清除选项,则可能永远无法准备就绪)。它会将 vold.post_fs_data_done 属性设为 0,接着将 vold.decrypt 设为 trigger_post_fs_data。这会使 init.rc 运行其 post-fs-data 命令。这些命令会创建所有必要的目录或链接,然后将 vold.post_fs_data_done 设为 1。当 vold 看到该属性中的 1 时,会将 vold.decrypt 属性设为 trigger_restart_framework。这会使 init.rc 再次启动 main 类中的服务,并启动 late_start 类中的服务(这是设备启动后首次启动这些服务)。

    7. 启动整个框架

      现在,框架会使用已解密的 /data 文件系统启动其所有服务,接下来系统就可以使用了。

    代码解读

    结合上章节的流程,下面用代码来解析启动未进行默认加密的已加密设备这个流程。

    # Android fstab file.
    #<src>                                         <mnt_point>  <type> 
    ...... 
    /dev/block/platform/soc.0/f9824900.sdhci/by-name/userdata     /data           ext4    noatime,nosuid,nodev,barrier=1,data=ordered,nomblk_io_submit,noauto_da_alloc,errors=panic wait,check,fileencryption  
    ......
    defaults
    

    这个配置定义在 device/lge/bullhead/fstab_fbe.bullhead 文件中。

    如上面的代码,在 /data 的末尾加上 fileencryption,便会进行全盘加密。

    步骤1:检测设有密码的已加密设备

    //设置ro.crypto.state标记,手机已被用户加密
    static int do_mount_all(const std::vector<std::string>& args) {
        ......
        if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
            ActionManager::GetInstance().QueueEventTrigger("encrypt");
        } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
            // 全盘加密,ro.crypto.state = encrypted, ro.crypto.type = block
            property_set("ro.crypto.state", "encrypted");
            property_set("ro.crypto.type", "block");
            //发送vdc 命令 defaultcrypto
            ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
        ......
        } else if (ret == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
            if (e4crypt_install_keyring()) {
                return -1;
            }
            property_set("ro.crypto.state", "encrypted");
            property_set("ro.crypto.type", "file");
            ......
    
        return ret;
    }

    这个方法定义在文件 system/core/init/builtins.cpp 中。

    # One shot invocation to deal with encrypted volume.
    # do_mount_all 中写入命令 defaultcrypto,执行 vdc 发送命令 mountdefaultencrypted
    on defaultcrypto
        exec - root -- /system/bin/vdc --wait cryptfs mountdefaultencrypted
        # vold will set vold.decrypt to trigger_restart_framework (default
        # encryption) or trigger_restart_min_framework (other encryption)
    
    # One shot invocation to encrypt unencrypted volumes
    on encrypt
        start surfaceflinger
        exec - root -- /system/bin/vdc --wait cryptfs enablecrypto inplace default noui
        # vold will set vold.decrypt to trigger_restart_framework (default
        # encryption)

    这个服务定义在文件 system/vold/vdc.rc 中。

    int CryptCommandListener::CryptfsCmd::runCommand(SocketClient *cli,
                                                     int argc, char **argv) {
        ......
        } else if (subcommand == "mountdefaultencrypted") {
            ......
            //执行cryptfs_mount_default_encrypted
            std::thread(&cryptfs_mount_default_encrypted).detach();
        }
        ......
    }

    这个方法定义在文件 vold/CryptCommandListener.cpp 中。

    int cryptfs_mount_default_encrypted(void)
    {
        int crypt_type = cryptfs_get_password_type();
        ......
        } else if (crypt_type != CRYPT_TYPE_DEFAULT) {
            SLOGD("Password is not default - "
                  "starting min framework to prompt");
            //不是默认加密, 设置 vold.decrypt = trigger_restart_min_framework
            property_set("vold.decrypt", "trigger_restart_min_framework");
            return 0;
        } else if (cryptfs_check_passwd(DEFAULT_PASSWORD) == 0) {
        ......

    这个方法定义在文件 system/vold/cryptfs.c 中。

    #属性vold.decrypt==trigger_restart_min_framework 时执行
    on property:vold.decrypt=trigger_restart_min_framework
        # A/B update verifier that marks a successful boot.
        exec - root -- /system/bin/update_verifier trigger_restart_min_framework
        class_start main

    这个服务定义在服务 system/core/rootdir/init.rc 中。

    class_start main 可知重启 main 类别的服务。main 类别的服务包括:

    这里写图片描述

    会重启 zygote。

    步骤2:装载 tmpfs

    Zygote 启动后,会 fork() system_process 进程,就是运行 SystemServer 代码了。但是 system_process 的运行需要正常的用户空间(/data),所以,需要临时挂载 tmpfs 分区,这个分区是在内存里分配的临时空间。

    int CommandListener::StorageCmd::runCommand(SocketClient *cli,
                                                          int argc, char **argv) {
        ......
        if (!strcmp(argv[1], "mountall")) {
            if (argc != 2) {
                cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: mountall", false);
                return 0;
            }
            // 挂载所有设备
            fs_mgr_mount_all(fstab);
            cli->sendMsg(ResponseCode::CommandOkay, "Mountall ran successfully", false);
            return 0;
        }

    这个方法定义在文件 system/vold/CommandListener.cpp 中。

    int fs_mgr_mount_all(struct fstab *fstab)
    {
        ......
        /* mount(2) returned an error, handle the encryptable/formattable case */
        bool wiped = partition_wiped(fstab->recs[top_idx].blk_device);
        //挂载 tmpfs 临时分区
        if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) {
           ++error_count;
           continue;
        }
        //全盘加密
        encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
        ......
    }
    
    

    这个方法定义在文件 system/core/fs_mgr/fs_mgr.c 中。

    步骤3:启动框架以提示输入密码

    private void startBootstrapServices() {
        // Only run "core" apps if we're encrypting the device.
        //启动min-framework 显示密码输入界面,仅启动 coreApp, 在AndroidManifest.xml中声明。
        //此时启动的 APP 在 tmpfs 临时分区,所以,所有app都是原始安装状态,不包含任何用户使用产生的数据。
        String cryptState = SystemProperties.get("vold.decrypt");
        if (ENCRYPTING_STATE.equals(cryptState)) {
            Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
            mOnlyCore = true;
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
            Slog.w(TAG, "Device encrypted - only parsing core apps");
            mOnlyCore = true;
        }
        ......
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
        mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        ......
    
    }

    这个方法定义在文件frameworks/base/services/java/com/android/server/SystemServer.java 中。

    private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
                long currentTime, UserHandle user) throws PackageManagerException {
            if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
            PackageParser pp = new PackageParser();
            pp.setSeparateProcesses(mSeparateProcesses);
            // 设置仅解析 core app only,
            pp.setOnlyCoreApps(mOnlyCore);
            .....
    }

    这个方法定义在文件 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java 中

    private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
            final PackageLite lite = parseClusterPackageLite(packageDir, 0);
    
            // 如果不是 !lite.coreApp, 跳过该 app,即启动时,不会安装该app
            if (mOnlyCoreApps && !lite.coreApp) {
                throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                        "Not a coreApp: " + packageDir);
            }

    这个方法定义在文件 frameworks/base/core/java/android/content/pm/PackageParser.java 中。

    安卓中定义为 coreApp 的应用有:

    这里写图片描述

    Framework-res.apk 的 manifest 配置文件如下:

    这里写图片描述

    步骤4:通过密码解密数据

    这个过程不再阐述。

    步骤5:停止框架

    #重启 main 类别服务
    on property:vold.decrypt=trigger_reset_main
        class_reset main

    这个 setion 定义在文件 system/core/rootdir/init.rc 中。

    步骤6:装载 /data

    static int do_mount_all(const std::vector<std::string>& args) {
        pid_t pid;
        .....
        //
        if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
            // 发送 encrypt 事件到 vdc
            ActionManager::GetInstance().QueueEventTrigger("encrypt");
        } else if
        .....
    }

    这个方法定义在文件 system/core/init/builtins.cpp 中。

    on encrypt
        start surfaceflinger
        exec - root -- /system/bin/vdc --wait cryptfs enablecrypto inplace default noui
        # vold will set vold.decrypt to trigger_restart_framework (default
        # encryption)

    这个 setion 定义在文件 system/vold/vdc.rc 中。

    on encrypt
        start surfaceflinger
        #发送命令 enablecrypto 到 vold
        exec - root -- /system/bin/vdc --wait cryptfs enablecrypto inplace default noui
        # vold will set vold.decrypt to trigger_restart_framework (default
        # encryption)

    这个 setion 定义在文件 system/vold/vdc.rc 中。

    int CryptCommandListener::CryptfsCmd::runCommand(SocketClient *cli,
                                                     int argc, char **argv) {
        } else if (subcommand == "cryptocomplete") {
            if (!check_argc(cli, subcommand, argc, 2, "")) return 0;
            dumpArgs(argc, argv, -1);
            rc = cryptfs_crypto_complete();
        // 命令是 enablecrypto
        } else if (subcommand == "enablecrypto") {
            .....
    
            // Spawn as thread so init can issue commands back to vold without
            // causing deadlock, usually as a result of prep_data_fs.
            char* arg2 = argc > 2 ? strdup(argv[2]) : NULL;
            char* arg4 = argc > 4 ? strdup(argv[4]) : NULL;
            // 执行 do_enablecrypto 方法
            std::thread(&do_enablecrypto, arg2, arg4, type, no_ui).detach();
    }

    这个方法定义在文件 system/vold/CryptCommandListener.cpp 中。

    static int do_enablecrypto(char* arg2, char* arg4, int type, bool no_ui) {
        int rc;
        int tries;
        for (tries = 0; tries < 2; ++tries) {
            // 不是默认加密,运行方法 cryptfs_enable()
            if (type == CRYPT_TYPE_DEFAULT) {
                rc = cryptfs_enable_default(arg2, no_ui);
            } else {
                rc = cryptfs_enable(arg2, type, arg4, no_ui);
            }
            .....
        return -1;
    }

    这个方法定义在文件 system/vold/CryptCommandListener.cpp 中。

    int cryptfs_enable(char *howarg, int type, char *passwd, int no_ui)
    {
        return cryptfs_enable_internal(howarg, type, passwd, no_ui);
    }

    这个方法定义在文件 system/vold/cryptfs.c 中。

    int cryptfs_enable_internal(char *howarg, int crypt_type, char *passwd,
                                int no_ui)
    {
        /* restart the framework. */
        /* Create necessary paths on /data */
        if (prep_data_fs()) {
            goto error_shutting_down;
        }
    }

    这个方法定义在文件 system/vold/cryptfs.c 中。

    static int prep_data_fs(void)
    {
        property_set("vold.post_fs_data_done", "0");
        // 设置 vold.decrypt = trigger_post_fs_data,触发 init.rc
        property_set("vold.decrypt", "trigger_post_fs_data");
        SLOGD("Just triggered post_fs_data\n");
    
        /* Wait a max of 50 seconds, hopefully it takes much less */
        for (i=0; i<DATA_PREP_TIMEOUT; i++) {
            char p[PROPERTY_VALUE_MAX];
            // 等待 init 设置 vold.post_fs_data_done = 1
            property_get("vold.post_fs_data_done", p, "0");
            if (*p == '1') {
                break;
            } else {
                usleep(50000);
            }
        }
    }

    这个方法定义在文件 system/vold/cryptfs.c 中。

    on property:vold.decrypt=trigger_post_fs_data
        trigger post-fs-data

    这个 setion 定义在文件 system/core/rootdir/init.rc 中。

    #创建/data 子目录和链接,启动服务
    on post-fs-data
        # We chown/chmod /data again so because mount is run as root + defaults
        chown system system /data
        chmod 0771 /data
        # We restorecon /data in case the userdata partition has been reset.
        restorecon /data
    
        # start debuggerd to make debugging early-boot crashes easier.
        start debuggerd
        start debuggerd64
    
        #task4597305  added by xiwu.peng to output logcat to uart
        start logcat2uart
    
        # Make sure we have the device encryption key.
        start vold
        installkey /data
    
        # Start bootcharting as soon as possible after the data partition is
        # mounted to collect more data.
        mkdir /data/bootchart 0755 shell shell
        bootchart_init
    
        .....
    
        mkdir /data/system_de 0770 system system
        mkdir /data/system_ce 0770 system system
    
        mkdir /data/misc_de 01771 system misc
        mkdir /data/misc_ce 01771 system misc
    
        mkdir /data/user 0711 system system
        mkdir /data/user_de 0711 system system
        symlink /data/data /data/user/0
    
        mkdir /data/media 0770 media_rw media_rw
        mkdir /data/media/obb 0770 media_rw media_rw
    
        init_user0
        # If there is no fs-post-data action in the init.<device>.rc file, you
        # must uncomment this line, otherwise encrypted filesystems
        # won't work.
        # Set indication (checked by vold) that we have finished this action
        #setprop vold.post_fs_data_done 1

    这个 setion 定义在文件 system/core/rootdir/init.rc 中。

    static int cryptfs_restart_internal(int restart_main)
    {
        // init 做完 post-fs-data,继续往下执行代码
        if (prep_data_fs()) {
                return -1;
        }
        //init 做完 post-fs-data, vold 将 vold.decrypt 设为 trigger_restart_framework, 触发init
        /* startup service classes main and late_start */
        property_set("vold.decrypt", "trigger_restart_framework");
    }

    这个方法定义在文件 system/vold/cryptfs.c 中。

    #重启所有服务
    on property:vold.decrypt=trigger_restart_framework
        # A/B update verifier that marks a successful boot.
        exec - root -- /system/bin/update_verifier trigger_restart_framework
        class_start main
        class_start late_start

    步骤7:启动整个框架

    vold.decrypt = trigger_restart_framework, framework 就可以正常启动了。

    加密属性

    vold 和 init 之间通过设置属性进行通信。下面列出了可用的加密属性。

    vold 属性

    属性  说明
    vold.decrypt trigger_encryption     以无密码方式加密存储卷。
    vold.decrypt trigger_default_encryption     检查存储卷是否采用了无密码加密。如果是,则解密并装载存储卷;如果不是,则将 vold.decrypt 设为 trigger_restart_min_framework。
    vold.decrypt trigger_reset_main     由 vold 设置,用于关闭提示输入磁盘密码的界面。
    vold.decrypt trigger_post_fs_data   由 vold 设置,用于准备具有必要目录等内容的 /data。
    vold.decrypt trigger_restart_framework  由 vold 设置,用于启动实际框架和所有服务。
    vold.decrypt trigger_shutdown_framework     由 vold 设置,用于关闭整个框架以开始加密。
    vold.decrypt trigger_restart_min_framework  由 vold 设置,用于启动加密进度条界面或提示输入密码,具体取决于 ro.crypto.state 的值。
    vold.encrypt_progress   框架启动时,如果设置了此属性,则会进入进度条界面模式。
    vold.encrypt_progress 0 to 100  进度条界面中应按照设置显示百分比值。
    vold.encrypt_progress error_partially_encrypted     进度条界面中应显示一条消息,告诉用户加密失败,并且界面中应为用户提供一个用于将设备恢复出厂设置的按钮。
    vold.encrypt_progress error_reboot_failed   进度条界面中应显示一条消息,告诉用户加密已完成,并且界面中应为用户提供一个用于重新启动设备的按钮。此错误不应发生。
    vold.encrypt_progress error_not_encrypted   进度条界面中应显示一条消息,告诉用户发生错误,没有已加密的数据或数据已丢失,并且界面中应为用户提供一个用于重新启动系统的按钮。
    vold.encrypt_progress error_shutting_down   进度条界面未运行,因此不清楚谁将响应此错误。在任何情况下,都不应发生此错误。
    vold.post_fs_data_done 0    由 vold 在将 vold.decrypt 设为 trigger_post_fs_data 的前一刻设置。
    vold.post_fs_data_done 1    由 init.rc 或 init.rc 在完成 post-fs-data 任务之后立即设置。
    

    init 属性

    属性  说明
    ro.crypto.fs_crypto_blkdev  由 vold 命令 checkpw 设置,供 vold 命令 restart 以后使用。
    ro.crypto.state unencrypted     由 init 设置,用于说明相应系统正在未加密的 /data ro.crypto.state encrypted 中运行。由 init 设置,用于说明相应系统正在已加密的 /data 中运行。
    
    ro.crypto.fs_type
    ro.crypto.fs_real_blkdev
    ro.crypto.fs_mnt_point
    ro.crypto.fs_options
    ro.crypto.fs_flags
    这 5 个属性由 init 在尝试装载 /data(包含从 init.rc 传入的参数)时设置。vold 会使用这些属性来设置加密映射。
    ro.crypto.tmpfs_options     由 init.rc 设置,包含 init 在装载 tmpfs /data 文件系统时应使用的选项。
    

    init 操作

    on post-fs-data
    on nonencrypted
    on property:vold.decrypt=trigger_reset_main
    on property:vold.decrypt=trigger_post_fs_data
    on property:vold.decrypt=trigger_restart_min_framework
    on property:vold.decrypt=trigger_restart_framework
    on property:vold.decrypt=trigger_shutdown_framework
    on property:vold.decrypt=trigger_encryption
    on property:vold.decrypt=trigger_default_encryption.
    

    Android 全盘加密分析到此为止。

    参考 https://source.android.com/security/encryption/full-disk

    展开全文
  • Android安全加密:对称加密

    万次阅读 2018-08-04 09:02:45
    Android安全加密专题文章索引 Android安全加密:对称加密 Android安全加密:非对称加密 Android安全加密:消息摘要Message Digest Android安全加密:数字签名和数字证书 Android安全加密:Https编程 以上学习所有...
  • android 三种常用的加密方式

    万次阅读 2018-07-23 10:49:01
    android应用中常用的加密方式有三种:MD5,AES,RSA。在进行实际的开发过程中,一般是几种加密方式配合使用,这样加密效果会更好,被破解的概率会越小。下面我们就分别讲一下三种加密方式的实现过程。 一、MD5 MD5...
  • Android常用加密方式

    千次阅读 2019-09-02 17:17:53
    加密解密简介 加密技术是最常用的安全保密手段,利用技术手段把重要的数据变为乱码(加密)传送,到达目的地后再用相同或不同的手段还原(解密)。加密技术包括两个元素:算法和密钥。算法是将普通的信息或者可以...
  • 数据的安全是非常重要的,现在无论干什么都要账号和密码,一旦账号与密码泄露出去必将造成财产的损失,所以做好数据保密是非常重要的。 Android加密算法有多种多样,常见的有MD5、RSA、AES、3DES四种。
  • Android AES加密和解密

    千次阅读 2015-03-12 14:08:02
    在移动开发中,不论IOS还是Android都支持基于PCK5Padding的AES加密,本文提供实现方法。也算自己造轮子了 MainActivity.java package com.hongyan.encryption_aes;import android.app.Activity; import ...
  • 加密结果是否可以被解密分为: 1,不可逆: MD5(Message-Digest消息摘要):不可逆,长度固定(32位),容易计算,仅一字节只差加密结果都会有很大区别 通常情况下为了让加密过程变得不可预测,我们会进行加盐...
  • android 文件/文件夹加密

    千次阅读 2013-05-31 15:18:19
    1. 加密算法文件加密,输出新加密文件(自定义后缀)后,将文件删除。并自定义文件管理器用于查看自定义后缀文件 2. 点击加密文件,通过后缀识别加密文件,弹出密码验证界面 3. 密码验证通过后,解密文件,并将...
  • 完成的一个android视频加密解密播放的案例

    千次阅读 热门讨论 2012-07-04 10:48:53
    android视频加密PC端,支持windows,linux,mac os多操作系统。支持对整目录进行加密。 根据android手机或者平板唯一识别号,设置过期时间,播放次数,水印来计算播放密码。所有设备均有唯一播放密码。 ...
  • Android SQLite加密

    千次阅读 热门讨论 2013-04-27 22:38:02
    最近因为一些项目的安全性需要将数据库加密,一开始想到的就是先将数据库通过AES加密,然后运行时再解密,另一种是将数据库里的内容加密。 很快这两种方案都是不理想的,第一种加密方式形同虚设,第二种,如果...
  • Android中Base64位的加密和解密

    千次阅读 2018-03-24 11:48:23
    在一些登录和注册的时候需要对用户的密码进行加密和...加密: /** * 加密 * oldWord:需要加密的文字/比如密码 */ public void setEncryption(String oldWord){ try { String encodeWord = Base64.encodeT...
  • android中的sqlite数据库加密

    万次阅读 2013-04-28 11:25:35
    说到android的数据安全又不得不说这sqlite的加密了,sqlite的加密现在用得比较爽的估计还是wxsqlite扩展了,但在android中要使用这个扩展还得用NDK重新编译一次成为.so的适用于android动态链接库,就是无奈地还要...
  • 项目中网络请求框架使用Retrofit+OKHTTP,如果需要进行参数加密呢?第一想法就是通过拦截器实现,Retrofit及OKHTTP都支持拦截器,但是拦截器却没有提供获取请求参数内容的方法,实现起来比较复杂需要修改框架源码,...
  • Java/Android中SHA1和SHA256加密

    万次阅读 2016-06-22 21:51:07
    SHA1(Secure Hash Algorithm,译作安全散列算法)是Hash算法中的一种,适合用于数字签名数据认证,加密过程不可逆不能进行解密。 MD5与SHA1都是Hash算法,MD5输出是128位的,SHA1输出是160位的,SHA256输出是256...
  • Android 获取wifi的加密方式

    万次阅读 2015-08-01 16:05:03
    Android 获取当前wifi的加密方式由于有需求是搜索附近的网络,通过...原文地址: android获取当前隐藏和未隐藏wifi的加密方式(安全性)1.一般WIFI加密有几种方式 WPA-PSK/WPA2-PSK(目前最安全家用加密) WPA/WPA2
  • Android - 字符串的加密和解密

    千次阅读 2018-06-13 10:17:33
    Android - 字符串的加密和解密
  • 快速集成Android最常用八种加密算法

    千次阅读 2017-03-30 17:16:12
    数据的安全性可谓是重中之重的,前两年大司频发的安全事件也是被炒的热火朝天~究竟该如何增加数据机密安全性,我们来唠唠。 说到安全,范围大的让人喘不过气来,关于安全的知识以及如何...我们就从最简单的加密来扯扯。
1 2 3 4 5 ... 20
收藏数 64,762
精华内容 25,904
关键字:

android加密