随着基于web的应用以及移动终端的普及,越来越多的私人资料/数据在网络上储存和处理,比如个人通讯录、照片、日程安排表、备忘,甚至还有业务文档、合同、报表等。一般情况下这些数据是明文或服务端加密后储存于应用服务提供商(有些应用服务提供商把数据托管于第三方云服务商),理论上应用服务提供商、云服务商、已成功入侵服务器的黑客等均可以获得用户的私人数据。经过实践可知,只有在技术层面上——而不是依赖服务商的承诺、信誉或者商业道德——对用户的私人数据提供充分的隐私保障,用户才拥有对自己数据的控制能力。@ivarptr
OpenPGP
在保障隐私的各种技术当中,对数据先加密再传送到网络(即客户端加密/端对端加密)是比较简单而有效的方式。其中 OpenPGP 是一套成熟的数据加密和数字签名标准(RFC4880)。
不过 OpenPGP 在实际应用中有一定难度,OpenPGP依赖非对称加密技术(如RSA、DSA非对称算法),要求每位用户都要有一个钥匙对(注:一般情况下需要两个钥匙对,一个用于数字签名,另一个用于加密数据,这里做了适度简化),钥匙对包含一个公钥和一个私钥。(有关OpenPGP更多的使用方法可以参考这篇文章《使用 GnuPG 实现电子邮件加密和数字签名》)。加密信息或者核对一个数字签名都必须先取得对方的公钥,因此当联系人不断增多时,用户需要手动管理大量的钥匙对,虽然现有很多免费的公钥服务器解决了公钥分发问题,不过取回的公钥仍然需要用户手动维护。除此之外,当用户有多个终端设备如手机或平板电脑,要在不同的设备里同步维护钥匙对也是一件不太容易的事情。
OSID
为了解决上诉的钥匙对维护问题以及实现如下目标:
- 简化用户加密数据的操作步骤;
- 简化应用程序实现加密数据的流程。
这里设计了一种开放式的安全用户 ID 系统(Open Secure ID,以下简写为 OSID)。OSID 的主要任务是让加密数据操作在复杂度以及方便性之间取得一个均衡。一个 OSID 系统包括如下几个部分:
- 用户Public Key 列表;
- 用户Public Profile;
- (可选)管理工具;
- OAuth;
- (可选)用户Private Key 列表;
- (可选)通讯录;
- (可选)Public 信任列表。
图1:Open Secure ID 系统的组成部分
排除可选部分之后,实际上OSID系统是一个很简单的系统,大致可以认为它是一个升级版的 key server,用于管理用户的钥匙对。而具体的数据加密和签名则由应用程序在客户端使用OpenPGP或者相似的技术实现。
OSID系统是去中心化的,即任何实现了OSID标准的站点都可以作为OSID的服务提供者(以下简称 OSID provider)。用户可以在一个OSID provider 创建一个帐号,也可以在一个OSID provider 导出帐号然后再导入到其他OSID provider。下面将对各个部分详细说明。
用户 Public Key 列表
OSID 系统的每位用户都有一个 Public Key 列表,Public Key 用于储存用户自己的钥匙对当中的公钥部分。每个 Public Key 列表有两个默认公钥:
- 用于数字签名的公钥;
- 用于数据加密的公钥。
这两个公钥是在用户创建帐号时由客户端产生并提交的。其中用于数字签名的公钥除了可以签名一般的信息之外,同时也用于签名用户的帐号信息,比如签名姓名、头像,以确保这些信息是该用户提供的。另外也用于签名用户的其他公钥,以确保这些公钥是该用户所拥有,所以这个公钥称为Master Key。
列表允许用户添加公钥,也允许应用程序添加公钥。应用程序通过OAuth经过用户的授权即可创建和管理属于自己公钥;用户也可以创建多个用于加密或数字签名的公钥,以细化每个公钥的用途。一个Public Key 列表的结构如下:
- key:公钥的值;
- key_id:钥匙对的id,算法同 OpenPGP;
- expires:公钥的有效期;
- algorithm:钥匙对的算法名称及密码长度,比如RSA-2048,DSA-1024,Elgamal-2048等;
- usage:标识公钥的用途,可以是sign、encrypt,或者两种用途都有;
- is_master_key:标识是否 Master Key;
- is_default_encrypt:标识是否默认加密公钥;
- name:公钥的名称,一般用于应用程序标识公钥的细分用途。名称可以为空白,如果不是空白,则必须经过加密,加密过程是:使用一个跟Public Key列表相关联的随机产生的session key加密name,然后使用默认加密公钥加密这个session key;
- app_id:创建公钥的应用程序的id,这个id是也是经过加密的,这样可以防止他人试图获取一个用户的应用程序列表。加密过程同name的;
- sign:对当前公钥使用 Master Key 签名的签名值;
- revoke_sign:如果要作废当前公钥,则使用 Master Key 签名该公钥并填写该字段。
用户 Public Profile
用户 Public Profile 是指可完全公开的个人资料,如unique id、名称、头像、个人简介、master key的指纹值等。
更新Public Profile每项信息时,用户都需要签名该项信息,比如更新姓名时,需要把姓名以及这个新名字的数字签名一起提交,服务器验证数字签名通过之后才允许更新。
其中的unique id是用户创建帐号时由OSID provider产生并签名的一个随机数——UUID,用于全局惟一标识一个用户。unique id除了用来关联一位用户的其他OSID信息(如Public Key列表)之外,还可以方便用户在不同的OSID provider 之间迁移帐号。
除了以上的信息之外,Public Profile还包括一些社会属性的其他站点的Profile,比如用户的 Twitter、Facebook等Profile,OSID provider 可以通过这些网站的 OAuth 接口验证用户是否真正拥有这些Profile,经过验证之后 OSID provider 应该使用自己的密钥对这些 Profile 签名,以表示通过服务器验证。
另外Public Profile还可以包括Email地址、电话号码等通信信息。对于 Email 地址 OSID provider可以通过发送邮件验证用户,通过验证的同样需要对其签名。由于一般用户可能不希望其他人看到(完整的)Email地址,OSID provider 应该只记录Email地址的Hash值,这样可以防止他人查看Email地址的同时,还能根据Hash值搜索或者核对一个Email地址。
Public Profile 的结构如下:
- name:项目的名称,比如name, unique_id, photo, email, social_twitter 等。
- value:项目的值。
- screen_value:项目值用于显示时的内容。比如一个用户的Twitter Profile 是一个 Twitter User Id,为了显示时比较直观,可能设置screen_value为 @ivarptr。
- sign:项目值的用户签名。
- provider_sign:项目值的OSID provider方的签名。sign和provider_sign存在叠加关系,比如用户的社会属性Profile,先由用户签名,然后再由OSID provider把原始数据以及用户的签名再作一次签名。
管理工具
OSID provider 在很多情况下不处理业务,而只起读/写用户信息的作用。而大部分业务处理在客户端运行的管理工具完成,比如创建帐号、更新头像等。管理工具除了在桌面操作系统运行的应用程序以及在移动终端运行的app这两种形式之外,也包括Web版的应用程序。为保障安全,Web版管理工具的业务功能应该由javascript在本地运行实现,不能由OSID provider服务器运行。
管理工具的主要功能除了让用户管理自己帐号信息之外,同时还充当信息传输代理角色。因为用户的部分信息是经过加密的,所以应用程序无法直接获取这些信息,这时应用程序只能通过IPC(指进程间通信,比如dbus、named pipe、socket等)访问管理工具,然后由管理工具访问OSID provider得到信息并且解密后再返回给应用程序。对于 Web应用程序可以通过JSONP或者iframe proxy技术跟Web版管理工具通信。
图2:应用程序与管理工具
为便于应用程序OSID,OSID provider 应该提供一种或者多种形式的管理工具,或者以SDK的方式提供基本的管理功能,比如登录、获取Public Key列表、Public Profile和Private Key列表的功能。
OAuth
通过 OAuth,(第三方)应用程序可以访问受保护的用户 OSID 资源,同时也可以通过 OSID 标识一位用户以登录自己的应用程序(类似一些应用程序所使用的“使用Twitter登录”功能)。
跟大部分提供OAuth的服务一样,(第三方)应用程序开发者需要先在 OSID provider 登记自己的应用程序,然后当用户使用这个应用程序时会跳转到 OSID 管理工具询问用户授权,当应用程序获得用户授权之后就可以访问受保护的用户资源。对于已加密的信息,应用程序应该访问管理工具,然后由管理工具代理访问并返回解密后的信息。
图3:应用程序通过OAuth与Provider 通信
用户 Private Key 列表
为了提高移动性,对安全性要求不非常高的用户可以选择把钥匙对当中的私钥部分加密后储存于 OSID provider,这样能大幅度方便用户在多个设备上使用OSID。
跟用户Public Key列表一样,Private Key列表也有一个相关联的随机产生的 session key,用户的所有私钥都会被这个 session key 所加密,然后用户只需提供一种可靠的方式加密这个 session key 就可以了。而加密方式大概有如下几种:
- 用户口令;
- 类似随机数id卡等标识硬件;
- 类似指纹、面孔、视网膜、DNA等跟用户相关的特征值。
相对来说用户口令最方便,不过也最不安全,在创建帐号时系统应该提示用户使用强密码。
图4:加密Private Key列表的原理
应用程序经过用户授权也可以添加私钥到Private Key列表,不过需要注意的是,每添加一个私钥都必须同时添加对应的公钥到 Public Key列表。因为没有公钥的私钥是没有意义的。
管理工具应该提供用户选择不使用 Private Key列表的选项,让对安全性要求较高的用户把私钥保存在本地。
用户Private Key列表的结构跟Public Key列表基本相同。
通讯录
OSID provider 可以提供一个用户级的通讯录,方便用户管理常用联系人。联系人信息是经过加密后再添加到通讯录里的。
联系人资料除了包括用户unique id、email、电话号码等基本资料之外,还应该包括对该联系人的信任程度的信息,比如是完全信任还是一般信任。这些资料都经过一个跟用户通讯录相关联的随机产生的session key加密,而 session key 则由用户的默认加密公钥加密。
一个通讯录的结构如下:
- key:条目编号,一个随机UUID,用于更新/删除条目是定位。
- value:联系人的资料,使用JSON格式组织,然后经过session key加密。
第三方应用程序可以通过OAuth以及管理工具读取/写入通讯录。
Public 信任列表
Public信任列表用于标识一位用户的public profile可信程度。如果你认识一位朋友,并且通过现实生活的方式(比如面对面或者打电话)核对过他的OSID public profile,则可以标识他的public profile为可信(对unique id签名)。这样当查看一位用户的 public profile时可以查看到所有信任他的用户的列表,这在OSID用于业务往来时会比较实用。
比如用户A收到C发送过来的加密信息,虽然A在现实生活中不认识C,不过A认识并信任B,而B信任C,那么当次信息可认为是可信的。
登录方式
因为OSID当中跟隐私相关的信息都经过加密,所以大部分信息都是无需通过验证登录而能够直接读取的,包括public key列表、public profile、private key列表、public信任列表。仅当用户需要修改OSID信息时,才需需要登录系统。跟一般的应用程序(网站)的用户系统不同,OSID provider 并不储存用户的登录口令、也不储存口令的hash值,而是采用如下步骤向用户派发一个会话令牌(access token):
- OSID provider 随机产生一个 access token,并使用用户的默认加密公钥加密这个 access token并返回给用户
- 用户获取自己Private Key列表的被加密过的 session key以及被session key加密过的默认加密私钥。
- 在客户端用户使用正确的口令(或其他解密方式)解密session key,然后再解密私钥,最后用私钥解密得到 access token。
- 用户使用正确的 access token 就可以访问自己受保护的资源。
应用示例
OSID主要目的是为了简化用户操作步骤以及简化应用程序的开发。通过OSID,应用程序开发者可以较为简单地开发能充分保障用户隐私的应用程序,诸如在线相册、在线文档库、音乐库、讨论组、聊天工具等,而用户在使用这些应用的过程中也无需关心具体数据加密和解密工作,因为大部分操作都可以透明地封装起来。
下面举一个端到端加密邮件应用程序(以下简称email app)的例子。
首先假设Alice和Bob都已经创建了自己的OSID帐号,然后email app也已经在 OSID provider 登记过。当Alice要发送一封加密邮件给Bob时,步骤如下:
- Alice 在 email app里填写收件人地址为 bob@domain.com,书写完邮件内容之后点击发送;
- email app 根据这个收件人地址在 OSID provider搜索Bob的public profile以及默认加密公钥。
- email app 使用 Bob 的默认加密公钥加密邮件内容并发送出去。
- Bob 收到邮件之后用 email app打开;
- email app 通过管理工具获取Bob 的默认加密私钥(此时管理工具可能会要求Bob输入private key列表的口令),解密邮件内容并显示。
由此可见,Alice发送加密邮件给Bob的所有幕后过程都已经自动完成了,用户的操作步骤被大幅度地简化。
有关OSID的API接口定义以及数据结构的定义将会在另一篇文章说明。
附:OpenPGP 的工作原理
用户Alice加密一段信息发送给Bob的过程:Alice必须先取得Bob的公钥,用之加密信息后再发送给Bob。Bob收到消息之后使用自己的 私钥解密然后得到原始信息(注:为了提高效率,实际加密过程是用一个随机产生的密钥——称为session key——和对称加密算法来加密信息,然后公钥只加密这个session key。解密时先用私钥解密session key,然后再用它来解密信息)。
图5:OpenPGP加密信息的过程
Alice 发送一条带有数字签名的信息给Bob的过程:首先Alice使用散列算法计算出信息的Hash值,然后用自己的私钥加密这个Hash得一个数字签名值,然 后把原始信息以及数字签名值同时发送给Bob,Bob收到之后用Alice的公钥解密数字签名值,得到Hash值,然后自己也计算一次原始信息的Hash 值并跟刚才得到的Hash值做比较,如果两个Hash值一致则说明信息的确是由Alice发出并且中途没有被篡改。
图6:OpenPGP的数字签名过程