转录:OAuth 2.0:通往地狱之路

译者: HorseLuke 原作者:Eran Hammer

人们常说,通往地狱之路,常由善意铺就[2][3]。好吧,我说的就是Oauth 2.0

上个月我做出了一个痛苦的决定,彻底和Oauth 2.0标准断绝关系。我辞去首席作者和校订者,从规范中删掉自己的名字,然后离开了工作组。从一份呕心沥血3年之久的文档和超过24份的草稿中去掉自己的名字是多么的不容易;而决定离开一个我领导5年之久为之努力的领域则是多么的痛心。

我做出这个极端决定,并不是单一问题或者事件可以解释的。这是一次由数千次刀割所引发的死亡。随着工作接近尾声,我越来越深思究竟我们在干什么。到了最 后,我得出一个结论,Oauth 2.0是个烂协议,烂得和WS-*有得一拼,烂得我不想再和它产生任何关联。这是我事业生涯中最大的一次职业挫败。

无论是邮件列表、会议讨论、特别设计委员会还是秘密渠道,无数次艰难的争论和妥协,最终产出的规范却在两个最重要目标上双缺失——安全性和互操作性。实际上,有一份折中方案将它从“协议”重新命名为“框架”,而另一份则添加了一个免责声明,警告这份规范并不能阐述互操作性的实现。

Oauth 1.0相比,Oauth 2.0规范更复杂,缺乏互操作性,实用性打折扣,更加不完整,最重要的是,更加不安全。

说得更明确些,Oauth 2.0如果在一个对互联网安全有深入了解开发者手上,实现结果大抵是安全的。然而,就这两年经历的情况来看,Oauth 2.0在大部分开发者手中明显出现了不安全的实现结果。

我们怎么到达这里的?

这个问题的核心在于,互联网(web)企业(enterprise)这两个世界之间有着强烈且难以弥合的冲突。IETF的OAuth工作组始于强烈的互联网驱动气势。然而一年之后随着工作一拖再拖,互联网工作者已从最初的1.0社区一个个离去,结果工作组剩下的大部分都是企业人员……然后还有我。

互联网社区一直在寻找与1.0非常相似的协议,并且在某些缺乏的方面进行小改善:简化签名,增加轻量级识别层,标记native application,增加更多流程以适应新的client类型,还有增强安全性。而企业社区则在寻找一种可以最小化改动已有系统的框架,对某些人来 讲,还试图寻求一种通过定制获利的新来源。举个例子理解这种分歧之深——在早期会议中,互联网工作者想实现一种在浏览器内client的流程优化,而企业 人员则想实现基于安全断言标记语言(SAML)的流程。

由上述冲突产生的规范成为了一种基于委员会设计、且更多是为了服务企业方的东拼西凑妥协物。更确切来说,它并非用于满足企业所有直接的需求,它给予的是几乎无限制的可扩展性。正是这种可扩展性和必须要求的灵活性,把这些协议给毁了。现在几乎啥东西都不用费什么努力,就可以宣称达到“Oauth 2.0兼容”标准了。

 

深入了解[4]

要明白OAuth 2.0的问题,你需要了解它相比OAuth 1.0在核心架构上有哪些变化:

无绑定token(Unbounded tokens) – 在1.0中,client若要访问受保护资源(protected resource),则必须提供两组凭据:token凭据(the token credentials,即Access Token和Access Token Secret)和client凭据(the client credentials,即常说的应用APP KEY和APP SECRET)。在2.0中,client凭据已经不再被使用了,意味着token已经不再绑定于任何一个特定的client类型或者实例。这样的结果, 既削弱了access token作为一种认证(authentication)手段的作用,同时也增加了出现安全问题的可能性。[5]

无记名token(Bearer tokens[8]) – 2.0在协议层去掉所有签名和加密要求,而仅仅依赖于传输层的TLS[6]。这意味着2.0的token在本质上处于更低安全系数的情况。任何想提高token安全性的行为必然要求额外的规范,而从目前提案展示的情况来看,工作组仅仅着眼于企业应用范畴。

token失效(Expiring tokens) – 2.0 的token存在过期时效,并且必须在过期时进行刷新。这对从1.0过来的client开发者而言是最大的改变,现在他们需要自行实现token状态管 理。之所以有token过期一说,是因为要适应自编码token的实现——一种在服务器端无需进行数据库查找即可进行认证的加密token。正因为这种自 编码token的存在,他们不可能被回收,只能强制为短时效存在,以此减少遭受危险时带来的损失。无论怎样从(server端)去掉签名所带来的好处,都 要在(client端)实现token状态管理面前输了两回。

准许类型(Grant types[7]) – 在2.0中,授权准许(authorization grants)被用于交换获取access token。准许是一种抽象概念,代表最终用户已同意授权。它可以是用户在访问许可授权页中点击“Approve(同意)”后获取的一个code,也可以 是用户实际的用户名和密码。之所以有这个概念,是为了实现多重认证流程。1.0着眼于用1个认证流程适应于多种client类型,而2.0则是明显为不同 的client类型增加多个特殊化认证流程。

犹豫不决的决策

以上的那些改变,若在一个良好定义的协议上实施是可控管理的。然而由于工作组的组成性质,导致了问题(issue)要不陷在细节纠缠不清,要不就只能保持开放等待所有执行成员共同决定。以下仅是工作组无法达成共识的一小部分例子

– 不强制要求token类型

– 不能对协定基于HMAC算法token类型目标统一意见

– 不要求实施token过期

– 没有关于token字段值长度的指导,其他值类似

– 没有严格要求注册登记流程

– 弱定义client类型

– 缺乏明晰的client安全属性

– 不强制要求准许类型

– 没有一个关于准许类型的适宜性或者适用性指导

– 没有一个实用的native application支持(倒是有许多空口说白话)

– 没有强制要求client认证机制

– 没有限制可扩展性

另一方面,OAuth 2.0为可扩展性定义4个新的登记值,以及通过URI增加额外扩展点,结果引发了一堆关于扩展性的提案。然而真正的问题在于,工作组还是不能为协议定义真 正的安全属性。这很清晰地表现在安全考虑环节上,大多处于扑朔迷离的情况。这导致安全专家几乎没有有效的聚焦点可供分析。实际上,工作组推出过70多页用 于描述2.0威胁模型的文档,它试图提供更多额外信息,但仍受困于一个相同的根本问题:没有一个实质的协议可供分析。

现实

在现实世界,Facebook仍在运行着一年半前的草案12,而且也完全没有理由要他们升级现有的实现形式。毕竟,一个升级过的、用于实现 Facebook对接的2.0 client也不太可能复用于其它Oauth服务提供方,反之亦然。Oauth 2.0一点也没有提供代码复用的潜力。

Oauth 2.0提供的是一个关于授权协议的蓝图(a blueprint for an authorization protocol)。正如上述定义所说,(独立使用)它基本上毫无用武之地,必须要迁并入一个具体的工作解决方案中——而这正是企业化的方式,WS-*的套路。2.0提供了一个全新的领域,用来推销咨询服务和整合方案。

然而互联网并不需要又一套安全框架。它需要的是一个简单、良好定义、和恰如其分合适的协议,以此提高安全性和增强互操作性。(可以说,)OAuth 2.0在寻求任何有意义的协议替代实现上失败了。
升级,还是停留

在最近几个月,许多人都问我,他们是否应该升级到Oauth 2.0,又或者应该推荐哪个协议版本给他们实现。我的答案是不能一概而论。

如果你现在用1.0用得很成功,忽略掉2.0吧。它并没有比1.0体现出更好的价值。(我猜测,用你们服务的client开发者现在已经很熟悉1.0的签名机制了。)

如果你在这个领域是个新来者,而且认为自己是个安全专家,务必要在仔细小心地审查Oauth 2.0的各种特性后再使用。如果你不是专家,要不就使用Oauth 1.0,要不就复制一个你信得过的Oauth 2.0服务方实现形式,来把事情做对(Facebook的API文档是一个很好的着手地方)。2.0对于大规模扩展(实施)相对较好,但是如果要运行大规 模改造,你很可能还需要一些安全专家现场估算各种情况和解决方案。
现在该咋办?

我现在希望有人接手2.0,然后创作10页左右、抛弃企业用途并更适用于绝大部分互联网服务提供方的文档。版本2.1应该更接近于版本1.5。但是在IETF,这根本不可能发生。在那个社区氛围中,全都是企业级用例。如果你看看他们的其他努力(比如OpenID Connect,本来超级简单的提案最终变成了一大打复杂的规范)就会知道,他们没能力让事情简化。

我认为OAuth牌子已经在衰退。这个框架还会存在一段时间,并且在当前缺乏替代品的情况下,它还会得到更广泛的接纳。然而我们更乐于看到接下来的几年里,Oauth 2.0会爆发各种重大的安全故障,还有其缓慢但稳步的品牌贬值。这将成为又一个你所厌恶却陷于其中泥潭的协议。

与此同时,我希望众多新兴社区们提出一些骨子里更接近1.0而非2.0的东西。Oauth 1.0是所有关于小型互联网创业团队寻找快速解决已明确定义问题的用户方案。老实点说,我都不知道Oauth 2.0究竟要解决什么样的用例。


写在最后

对于一个曾经有前途的社区,结论却是悲哀的。OAuth曾作为小型、快速且有用的标准模范,在标准机构之外无需繁琐过程和法律花销中产生。

(然而现在,)我们的标准制定过程已经破碎地无法修复。这个结局直接来源于IETF的本性,还有监督这份工作时的某些特定性格。更直白地说,这并非由于某 些坏人或者无能者导致的。恰恰相反,大家都非常有才华、聪明、和蔼可亲等等。然而大多数人表态只为自身企业领域服务,而剩下的我们已在事实上无法与之竞 争。

将OAuth带入IETF是个巨大的错误。另一种替代方案WRAP也不会有更好的结局,但至少不用花费3年时间才得知这个下场。只要能坚持住,我尽可能地留在里面,去为我自认为最适合互联网的模式而战。可是就自己而言,我并没有从所做的决策中得到什么。到了最后,一个反对派的声音只能将事情延缓,但不能改变什么。

我失败了。

我们都失败了。

http://hueniverse.com/2012/07/26/oauth-2-0-and-the-road-to-hell/

ARM Open Source & Optimization

ARM tool:                       Streamline analyzer / DS-5

http://ds.arm.com/ds-5/optimize/

 

Ne10:            Open Source Library based on Neon

http://projectne10.github.io/Ne10/

https://github.com/projectNe10/Ne10

http://community.arm.com/groups/android-community/blog/2013/10/28/ne10-a-new-open-source-library-to-accelerate-your-applications-with-neon

 

Liano

http://www.linaro.org/

 

FreeRtos

www.freertos.org/portcortexgcc.html

http://www.freertos.org/portcortexgcc.html

 

Yeppp:

http://www.yeppp.info/downloads.html

 

 

CoOS:

http://www.coocox.org/CoOS.htm

 

Mirror:

http://www.myir-tech.com/download.asp

 

Open Source RTOS

eCOS:

wget http://mirrors.kernel.org/sources.redhat.com/ecos/ecos-install.tcl

 

sh   ecos-install.tcl

 

FreeRTOS:

wget http://sourceforge.net/projects/freertos/files/latest

 

RT-Kernel

http://www.rt-thread.org/

 

 

RTEMS

Build Tools:

 http://www.rtems.org/wiki/index.php/RTEMS_Source_Builder

sudo apt-get install binutils gcc g++ gdb unzip git python2.7-dev

sudo apt-get install cvs

sudo apt-get install texinfo

cd ${HOME}

mkdir -p rtems/src

cd rtems/src

git clone git://git.rtems.org/rtems-source-builder.git

cd rtems-source-builder

source-builder/sb-check

cd rtems

../source-builder/sb-set-builder --list-bsets

../source-builder/sb-set-builder --log=l-arm.txt --prefix=$HOME/rtems/4.11 4.11/rtems-arm

ls $HOME/rtems/4.11

ls $HOME/rtems/4.11/bn

export PATH=$HOME/rtems/4.11/bin:$PATH

 

ftp://ftp.rtems.com/pub/rtems/

 

 

 

uCOS

http://micrium.com/

 

 

FIDO Alliance

https://fidoalliance.org/

 

Strong Authentication

Formed in July 2012 to address the lack of interoperability among strong authentication technologies, and remedy the problems users face with creating and remembering multiple usernames and passwords.

FIDO specifications will support a full range of authentication technologies, including biometrics such as fingerprint, eye and iris scanners, voice and facial recognition, as well as further enabling existing solutions and communications standards, such as Trusted Platform Modules (TPM), USB Security Tokens, embedded Secure Elements (eSE), Smart Cards, Bluetooth Low Energy (BLE), and Near Field Communication (NFC). The open specifications are being designed to be extensible and to accommodate future innovation, as well as protect existing investments.

Sponsor Member:    $25,000

Associate Member:  $15,000

Build Courgette of Chromium project

http://www.chromium.org/chromium-os

http://git.chromium.org/gitweb/

https://chromium.googlesource.com/?format=HTML

http://www.chromium.org/glossary


sudo apt-get install python-setuptools

git clone https://chromium.googlesource.com/external/gyp.git

cd gyp

sudo python setup.py install

cd ..

#git clone http://git.chromium.org/chromium/src/base.git
git clone https://chromium.googlesource.com/chromium/src/base

#git clone http://git.chromium.org/chromium/src/courgette.git
git clone https://chromium.googlesource.com/chromium/src/courgette

#git clone https://chromium.googlesource.com/experimental/chromium/src

mkdir -p third_party/lzma_sdk
cd third_party/lzma_sdk
wget --no-check-certificate  http://chromium.googlesource.com/experimental/chromium/src/+archive/lkgr/third_party/lzma_sdk.tar.gz
tar xvfz lzma_sdk.tar.gz
rm -rf Executable 7zr.exe lzma_sdk.tar.gz

Android mount sdcard (again)

===>  execute_media_format
android/packages/apps/Settings/src/com/android/settings/MediaFormat.java

===>  mountService.formatVolume(extStoragePath);
android/frameworks/base/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java

====>  formatVolume
====>  doFormatVolume
android/frameworks/base/services/java/com/android/server/MountService.java

===> int CommandListener::VolumeCmd::runCommand
===> rc = vm->formatVolume(argv[2]);
android/system/vold/CommandListener.cpp

==> int VolumeManager::formatVolume
==> mVolumes = new VolumeCollection();
==> return v->formatVol()
android/system/vold/VolumeManager.h
android/system/vold/VolumeManager.cpp

===> int Volume::formatVol
===> Fat::format(devicePath, 0))
android/system/vold/Volume.cpp

===> int Fat::format(const char *fsPath, unsigned int numSectors)
===> static char MKDOSFS_PATH[] = “/system/bin/newfs_msdos”
android/system/vold/Fat.cpp

android/frameworks/base/services/java/com/android/server/NativeDaemonConnector.java

# C code
android/system/vold

# Launch sd formater in setting
adb shell
am start -n com.android.settings/.MediaFormat

##############################################################################

以下是打开“无线和网络设置”界面:

Intent intent = new Intent(“/”);
ComponentName cm = new ComponentName(“com.android.settings”,”com.android.settings.WirelessSettings”);
intent.setComponent(cm);
intent.setAction(“android.intent.action.VIEW”);
activity.startActivityForResult( intent , 0);

以下是可以直接打开的系统界面:

com.android.settings.AccessibilitySettings 辅助功能设置
com.android.settings.ActivityPicker 选择活动
com.android.settings.ApnSettings APN设置
com.android.settings.ApplicationSettings 应用程序设置
com.android.settings.BandMode 设置GSM/UMTS波段
com.android.settings.BatteryInfo 电池信息
com.android.settings.DateTimeSettings 日期和时间设置
com.android.settings.DateTimeSettingsSetupWizard 日期和时间设置
com.android.settings.DevelopmentSettings 应用程序设置=》开发设置
com.android.settings.DeviceAdminSettings 设备管理器
com.android.settings.DeviceInfoSettings 关于手机
com.android.settings.Display 显示——设置显示字体大小及预览
com.android.settings.DisplaySettings 显示设置
com.android.settings.DockSettings 底座设置
com.android.settings.IccLockSettings SIM卡锁定设置
com.android.settings.InstalledAppDetails 语言和键盘设置
com.android.settings.LanguageSettings 语言和键盘设置
com.android.settings.LocalePicker 选择手机语言
com.android.settings.LocalePickerInSetupWizard 选择手机语言
com.android.settings.ManageApplications 已下载(安装)软件列表
com.android.settings.MasterClear 恢复出厂设置
com.android.settings.MediaFormat 格式化手机闪存
com.android.settings.PhysicalKeyboardSettings 设置键盘
com.android.settings.PrivacySettings 隐私设置
com.android.settings.ProxySelector 代理设置
com.android.settings.RadioInfo 手机信息
com.android.settings.RunningServices 正在运行的程序(服务)
com.android.settings.SecuritySettings 位置和安全设置
com.android.settings.Settings 系统设置
com.android.settings.SettingsSafetyLegalActivity 安全信息
com.android.settings.SoundSettings 声音设置
com.android.settings.TestingSettings 测试——显示手机信息、电池信息、使用情况统计、Wifi information、服务信息
com.android.settings.TetherSettings 绑定与便携式热点
com.android.settings.TextToSpeechSettings 文字转语音设置
com.android.settings.UsageStats 使用情况统计
com.android.settings.UserDictionarySettings 用户词典
com.android.settings.VoiceInputOutputSettings 语音输入与输出设置
com.android.settings.WirelessSettings 无线和网络设置

##############################################################################
Generate SD Card Image file

#64G:
dd if=/dev/zero of=64G.img  count=0 seek=128M

#8G:
dd if=/dev/zero of=64G.img  count=0 seek=16M

#8G (with zero filled)
dd if=/dev/zero of=64G.img count=16M

##############################################################################
Loop device

#List loop devices:
losetup -a

#Add a loop device
losetup /dev/loop1 8G_zero.img

#Delete loop device
losetup -d /dev/loop1

find . -type f |xargs grep sd_format
find . -name *.java |xargs grep sd_format

###################################################################
Modify sd_format of android/packages/apps/Settings/res/values, impact on:

target R.java/Manifest.java: Settings (out/target/common/obj/APPS/Settings_intermediates/src/R.stamp)
target Java: Settings (out/target/common/obj/APPS/Settings_intermediates/classes)
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Copying: out/target/common/obj/APPS/Settings_intermediates/classes-jarjar.jar
Copying: out/target/common/obj/APPS/Settings_intermediates/emma_out/lib/classes-jarjar.jar
Copying: out/target/common/obj/APPS/Settings_intermediates/classes.jar
Copying: out/target/common/obj/APPS/Settings_intermediates/noproguard.classes.jar
target Dex: Settings
Copying: out/target/common/obj/APPS/Settings_intermediates/noproguard.classes.dex
target Package: Settings (out/target/product/generic/obj/APPS/Settings_intermediates/package.apk)
‘out/target/common/obj/APPS/Settings_intermediates/classes.dex’ as ‘classes.dex’…
Processing target/product/generic/obj/APPS/Settings_intermediates/package.apk
Done!
Install: out/target/product/generic/system/app/Settings.odex
Install: out/target/product/generic/system/app/Settings.apk
Finding NOTICE files: out/target/product/generic/obj/NOTICE_FILES/hash-timestamp
Combining NOTICE files: out/target/product/generic/obj/NOTICE.html
target Java: SettingsTests (out/target/common/obj/APPS/SettingsTests_intermediates/classes)
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Installed file list: out/target/product/generic/installed-files.txt
Target system fs image: out/target/product/generic/obj/PACKAGING/systemimage_intermediates/system.img
Install system fs image: out/target/product/generic/system.img

******************************************************
SD FORMAT

==> StorageVolumePreferenceCategory
==> mAllowFormat = mStorageVolume != null && !mStorageVolume.isEmulated()
android/packages/apps/Settings/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java

SD Card Mount

=> “Preparing SD card”
=> “Damaged SD card”
==> ext_media_checking_notification_title
==> ext_media_unmountable_notification_title
frameworks/base/core/res/res/values/strings.xml
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
===>MEDIA_UNMOUNTABLE

*****************************************************

#/system/etc/vold.fatab
#/system/etc/vold.conf

=>fatab
==>system/vold/main.cpp
===>process_config
====>VolumeManager
=====>system/vold/VolumeManager.cpp
=======>CommandListener
========>system/vold/CommandListener.cpp

********************************
FAT
===> system/vold/Fat.cpp
====> FSCK_MSDOS_PATH
=====> Fat::check
======>system/vold/Volume.cpp
=======>createDeviceNode
=========>Volume::mountVol
=========>DirectVolume::handleBlockEvent

Volume::mountVol
==> No impact on SDCard Mount, just for security fs

DirectVolume::handleBlockEvent
==>NetlinkEvent
===>system/core/include/sysutils/NetlinkEvent.h
=====>NetlinkEvent.mSubsystem==”block”, send to volume manage ==> DirectVolume::handleBlockEvent
======>NlActionAdd
========>system/core/libsysutils/src/NetlinkEvent.cpp

==========>system/core/libsysutils/src/NetlinkListener.cpp
==========>NetlinkListener::onDataAvailable

============>system/core/libsysutils/src/SocketListener.cpp
============>system/core/include/sysutils/NetlinkListener.h
============>class NetlinkListener : public SocketListener

***************************************************************************************
*** Triger of  NlActionAdd ***

“add”:
=>NetlinkEvent::parseAsciiNetlinkMessage,    system/core/libsysutils/src/NetlinkEvent.cpp
==>NetlinkEvent::decode
===>NetlinkListener::onDataAvailable,        system/core/libsysutils/src/NetlinkListener.cpp
====>SocketListener::runListener,            system/core/libsysutils/src/SocketListener.cpp
=====>SocketListener::threadStart,           system/core/libsysutils/src/SocketListener.cpp
======>SocketListener::startListener,        system/core/libsysutils/src/SocketListener.cpp
=======>main,                                system/vold/main.cpp
=======>NetlinkHandler::start,               system/vold/NetlinkHandler.cpp

*** Handle of NlActionAdd ***

“NlActionAdd”
=>DirectVolume::handleBlockEvent,            system/vold/DirectVolume.cpp
==>VolumeManager::handleBlockEvent,          system/vold/VolumeManager.cpp
==>NetlinkHandler::onEvent,                  system/vold/NetlinkHandler.cpp

**************************************************************************
Framework:   MountService

frameworks/base/services/java/com/android/server/SystemServer.java
=>public MountService(Context context),     frameworks/base/services/java/com/android/server/MountService.java
==>mContext.registerReceiver(mBroadcastReceiver, filter, null, null);
===>BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver()
====>action.equals(Intent.ACTION_BOOT_COMPLETED)
=====>if (state.equals(Environment.MEDIA_UNMOUNTED)) {
int rc = doMountVolume(path);
if (rc != StorageResultCode.OperationSucceeded) {
Slog.e(TAG, String.format(“Boot-time mount failed (%d)”,
rc));
}
======>private int doMountVolume(String path)
=======>mConnector.doCommand(String.format(“volume mount %s”, path));

==>mConnector = new NativeDaemonConnector
===>class NativeDaemonConnector,    frameworks/base/services/java/com/android/server/NativeDaemonConnector
====>public void run(),             frameworks/base/services/java/com/android/server/NativeDaemonConnector.java
=====>listenToSocket,               frameworks/base/services/java/com/android/server/NativeDaemonConnector.java
======>mCallbacks.onDaemonConnected();     (mCallbacks=MountService)
=======>onDaemonConnected()         frameworks/base/services/java/com/android/server/MountService.java

**********************************************************************************
Sd Card Mount Summary:

frameworks/base/services/java/com/android/server/MountService.java:
private int doMountVolume(String path):

Use case of doMountVolume

Case 1:  private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver()
===> Boot up SD Card mount

Case 2:  public boolean onEvent(int code, String raw, String[] cooked)
===>frameworks/base/services/java/com/android/server/NativeDaemonConnector.java
===>Callback
===>public boolean handleMessage(Message msg)
===> SD Card Insert mount

Case 3: public int mountVolume(String path)
==> packages/apps/Settings/src/com/android/settings/deviceinfo/Memory.java
==> User Setting/Mount

Case 4: public int mountVolume(String path)
===> frameworks/base/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
===> Factory Reset

Binary Diff

bsdiff:                       http://www.daemonology.net/bsdiff/

Courgette:                http://www.chromium.org/developers/design-documents/software-updates-courgette

http://blog.chromium.org/2009/07/smaller-is-faster-and-safer-too.html

 

xdelta:                        http://code.google.com/p/xdelta/

rdiff:                            http://librsync.sourcefrog.net/