[翻译]ICS 证书存储实现(ICS Credential St

2018-10-03  本文已影响0人  三秋桂子仪同三司

前言:

这是一篇关于Android安全的翻译,这是原文地址。接上一篇翻译。这篇文章主要讲了 key store 的存储位置,加密方式,读写权限等。随着Android源码的更新,这篇文章已经有些过时了,但它表达的思想还是非常可取的。

我会一段一段地复制原文,然后在下面给出翻译,如有图片,我会重新保存再上传,以免出现“图片无法显示的情况”。


原文:

ICS Credential Storage Implementation

November 30, 2011

译文:

ICS 证书存储实现

2011年11月30日

原文:

In the previous entry, we looked at how the new ICS KeyChain API is used and tried installing a user private key/certificate pair and a CA certificate. Now we'll will try to find out where they are actually stored and how they are protected.

译文:

前面的部分,我们学习了新的 ICS KeyChain API 是如何被使用,并且尝试安装了一个用户私有的密钥/证书对和一个 CA 证书,现在我们要找到它们实际存储的地方,还有它们是如何被保护的。

原文:

Looking at frameworks/base/keystore/java/android/security, we notice several interesting classes that are not mentioned in the SDK documentation. The most promising is the KeyStore class, so let's have a look. Sure enough, it is marked as hidden (using the dreaded @hide comment). It does have methods for interacting with the key store (get(), put(), delete(), reset(), etc.), but where is the actual key store? As it turns out, all methods send command to a local socket aptly named 'keystore'. With a little creative grepping, we find out that there is native daemon with the same name listening on that socket. The source is in frameworks/base/cmds/keystore/keystore.cpp, so let's have a look. The file has some helpful comments, and we learn that keys are encrypted, checksummed and saved as files (one key per file). But where are the actual files? Looking at /init.rc we find the keystore daemon startup command looks like this:

译文:

查看 frameworks/base/keystore/java/android/security,我们注意到几个有意思的, SDK 文档没有提到的类。最有价值的是 KeyStore 类,所以我们看一看。果然,它被标记成 hidden (使用了可怕的 @hide 注解)(译注:@hide 注解是 Android 源码中,隐藏一个 JAVA 类或者方法时所用的注解,使用了这个注解,它就不会被编译到 Android SDK 中,所以应用开发是没法调用的。但使用 makefile 在源码环境下编译是可以访问的。)。它有和 key store (凭据存储) 交互的方法(get(), put(), delete(), reset() 等)。但真正的 key store 在哪里?事实证明,所有的方法发送命令到一个本地 socket(套接字),恰好命名为 'keystore' (译注:我看新的源码,没有使用 socket, 而是使用了 Binder, 总之是要跨进程通信)。通过一点有创造性的文本查询,我们发现有一个本地的守护进程有相同的名字,监听在那个 socket 上。代码在 frameworks/base/cmds/keystore/keystore.cpp(译注:新的代码已经没有这个文件了,因为是 Binder, 对应的类是 IKeystoreService, 在 frameworks\base\core\java\android\security 中有一个 IKeystoreService.aidl)。让我们看一下,文件有一些有帮助的注释,我们知道 key 是被加密,校验和保存为一个文件(一个 key per 文件)。但真正的文件在哪儿呢?查看 /init.rc 我们找到 keystore 守护进程的启动命令看起来是这样的(译注:我没有看 ICS 的源码):

service keystore /system/bin/keystore /data/misc/keystore
    class main
    user keystore
    group keystore
    socket keystore stream 666

原文:

Next step is, of course, peeking into /data/misc/keystore

译文:

下一步,查看 /data/misc/keystore 目录

# ls -la /data/misc/keystore
-rw------- keystore keystore       84 2011-11-30 15:26 .masterkey
-rw------- keystore keystore      980 2011-11-30 15:56 1000_CACERT_testca
-rw------- keystore keystore      820 2011-11-30 15:55 1000_USRCERT_test
-rw------- keystore keystore      932 2011-11-30 15:55 1000_USRPKEY_test

原文:

Here each file name consists of the UID of the user that created it (1000 is system), the entry type (CA certificate, user certificate or private key), and the key name (alias) connected with underscores. And, of course, there is a .masterkey. Going back to the keystore daemon source, we find out that:

译文:

这里每一个名字的构成部分有:创建它的用户的 UID (1000 是 system), 条目类型(CA 证书,用户证书或私钥),和 key 的名称(别名),用下划线连接。当然,有一个 .masterkey。回到 keystore 守护进程源码,我们找到了:

原文:

译文:

原文:

What this means in practice is that the Android key store is pretty secure for a software solution: even if you had access to a rooted device and managed to extract the key blobs, you would still need the keystore password to derive the master key. Trying out different password to decrypt the master key would require at least 8192 iterations to derive a key, which is prohibitively expensive. In addition, the derivation function is seeded with a 128-bit random number, so pre-calculated password tables cannot be used.

译文:

这意味着在实践中 Android 凭据存储在软件方案上是非常安全的,即使你访问一个 root 过的设备,并且成功提取凭据文件,你仍然需要 keystore 的密码来导出主密钥。尝试用不同的密码来解密主密钥需要至少 8192 次迭代来衍生一个凭据,这是过度昂贵的。此外,衍生方法用了一个128位数字的随机种子,所以预设的密码表是不能用的。

原文:

Key blobs are owned by the keystore user, so on a regular (not rooted) device, you need to go through the daemon to access the keys. As it turns out, there is a helpful command line utility that talks to the daemon and lets us manipulate the key store: keystore_cli. It has commands for initializing the key store, listing, getting and deleting keys, etc. Experimenting with it shows that the keystore daemon is additionally checking the calling process's UID to grant or deny access to each command:

译文:

keystore 用户拥有凭据文件,因此在一个正常(没有 root)的设备上,你需要通过守护进程访问私钥。事实表明,有一个很有用的命令行工具,它和守护进程对话并让我们操作 key store:keystore_cli。它有初始化(initializing)、列出(listing)、获取(getting)、删除(deleting )等命令。实验显示:keystore 守护进程额外地检查了调用者的进程UID,来对每一个命名授权或者拒绝。

# keystore_cli unlock
keystore_cli unlock
6 Permission denied
# keystore_cli get CACERT_testca
keystore_cli get CACERT_testca
1 No error
-----BEGIN CERTIFICATE-----
MIICiTCCAfKgAwI...

# su system
su system
$ keystore_cli insert foo bar
keystore_cli insert foo bar
1 No error
$ keystore_cli saw ""
keystore_cli saw ""
1 No error
foo
USRPKEY_test
USRCERT_test
CACERT_testca
$ keystore_cli get foo
keystore_cli get foo
1 No error
bar
$ exit

# su app_44
su app_44
$ keystore_cli saw ""
keystore_cli saw ""
1 No error
$ keystore_cli insert baz boo
keystore_cli insert baz boo
1 No error
$ keystore_cli get baz
keystore_cli get baz
1 No error
boo

原文:

This basically translates to:

译文:

这可以简单理解成:

原文:

The android.security.KeyStore class we found while browsing the framework's source is almost a one-to-one port of the keystore_cli command's functionality to Java. By using it Java apps can get direct access to the keystore daemon, but as we said, that class is not part of the public API. There are a couple of reasons for this:

译文:

我们浏览 framework 源码发现的 android.security.KeyStore 类,几乎是 keystore_cli 命令功能到 Java 的一对一的端口。通过使用它,Java 应用能直接访问 keystore 守护进程,但面我们前说过,这个类不是公开 API 的一部分,有下面的一些原因:

原文:

译文:

原文:

As mentioned in the previous article, most of the described credential storage functionality has been available in Android since at least Donut (1.5), but the key store was only accessible to system applications such as Settings, and the WiFi and VPN clients. What ICS adds are a few layers on top of this that make it possible to offer user applications access to the system key store and assert fine-grained control over what keys each app is allowed to use. In the next part of the series we will look at the implementation of the new credential storage functionality added in ICS.

译文:

正如前一篇文章提到的,大多数所描述的证书存储功能已经在 Android Donut(1.5) 以后可用了,但 key store 只对系统应用例如设置、WIFI、VPN客户端等可用。ICS在这上部增加了一些层,使得用户应用访问系统 key store 成为可能,并在允许一个应用使用什么 key 上维护了细粒度控制。在这系列的下一部分,我们将要学习 ICS 添加的新证书存储的实现。

上一篇下一篇

猜你喜欢

热点阅读